在git log中显示提交大小

51

如何在git log的输出中显示提交大小?

您可以将提交大小理解为其父级与自身之间的差异,或者任何能告诉您提交有多大的合理内容。

git log有一个--log-size选项,但它是日志消息的大小,而不是提交本身的大小。


你能举个提交的例子并解释一下它的“大小”吗?此外,为什么需要这个? - Schwern
@Schwern,我认为你在下面的回答中展示了提交(commit)是什么。我需要提交大小来快速确定在一长串提交(commit)中每个提交(commit)完成了多少工作。这对于确定主要更改很有帮助。只要定义合理,我不会限制它的定义。 - Cyker
“每个提交中完成了多少工作”是什么意思?您将使用该信息做什么?我嗅到了代码指标被误用的味道。 - Schwern
也要注意提交中更改的行数可能会产生误导性。例如,如果我重新缩进代码,那么它将显示为更改了很多行,但实际上需要的工作量很少。 -b-w 这样的选项可以用于忽略空格更改,但一些自动代码风格化程序超越了简单的空格更改。 - Schwern
我偶尔遇到的一种情况是,当我进行推送时,即使是非常小的更改也需要几分钟的时间。如果更改实际上很小,我知道我应该检查慢速网络或慢速服务器。如果它花费了那么长时间,因为我实际上正在推送100MB的数据,则我想找出为什么我要推送这么多数据。 - Troy Daniels
显示剩余5条评论
2个回答

37

一个提交的“大小”可能有不同的含义。如果您指的是它占用了多少磁盘空间......在Git中很难确定,而且可能没有什么意义。相比之下,像SVN这样的工具将提交存储为增量,但在Git中更改文件时,它会将文件的新副本作为图形数据库中的对象进行存储。一个对象可以在许多提交中共享。尽管这听起来可能效率不高,但Git有许多聪明的方法以惊人的效率使用磁盘空间。

如果您指的是它更改了多少行代码,那很容易。您可以使用各种标志来获取更改了多少个文件和多少行代码,其中大多数标志都包含单词“stat”。例如,git log --shortstat会告诉您更改了多少个文件,插入了多少行代码,删除了多少行代码。这里是一个示例。

commit e3d1909c875ea0c1a64246d735affa039ad11aa0 (origin/master, origin/HEAD)
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Thu Aug 11 13:04:24 2016 -0700

    Add default Travis and AppVeyor configs.

    The AppVeyor one is set up for Dist::Zilla, the hardest of the bunch.

 2 files changed, 60 insertions(+)

如果你想了解一个提交所占用的磁盘存储空间,你需要获取该提交创建的新文件(blob对象)的ID,然后检查它们的大小。你可以在git log -p中看到它们。

commit 0f28d9a96bc92d802b57900ce4a06db71cbaef6d
Author: Michael G. Schwern <schwern@pobox.com>
Date:   Wed Aug 10 09:13:40 2016 -0700

    Remove my name from the gitconfig.

    Now it can be used by anyone. Git will prompt for the user info.

diff --git a/.gitconfig b/.gitconfig
index 1d539bd..538440f 100644
--- a/.gitconfig
+++ b/.gitconfig
@@ -1,18 +1,10 @@
-# If you use this file, remember to change the [user] and [sendemail] sections.
-
...and so on...

index 1d539bd..538440f 100644 表示该替换的 blob 对象(文件)1d539bd 已被 538440f 替换,并使用了权限 0644。如果你运行 git cat-file -s 538440f,它会告诉我这个对象是 4356 字节。这是它的未压缩大小。在磁盘上,它只有 1849 字节。

$ ls -l .git/objects/53/8440f84014584432fa5bf09d761926b3d70dbe 
-r--r--r-- 1 schwern staff 1849 Aug 10 09:14 .git/objects/53/8440f84014584432fa5bf09d761926b3d70dbe

我执行了git gc操作后,对象文件也消失了。现在所有的东西都被打包到一个文件中,文件大小不到10K。

$ tree -h .git/objects/
.git/objects/
├── [ 102]  info
│   └── [  54]  packs
└── [ 136]  pack
    ├── [1.9K]  pack-d5b7110001ed35cce1aa0a380db762f39505b1c0.idx
    └── [7.8K]  pack-d5b7110001ed35cce1aa0a380db762f39505b1c0.pack

这个回答展示了如何更自动化地获取提交中的blob。


5
我认为使用统计数据是识别带有重大更改的提交的好方法,但它们在输出中看起来很乏味。我们是否有机会通过对统计数据进行一些计算,并以单行格式打印漂亮的结果?例如,打印每个提交及其校验和、标题和数字(#添加的行数+#删除的行数)?我没有在git log格式占位符中找到这样的占位符。我有什么遗漏吗? - Cyker
4
类似于 git log --pretty=format:"%h %s" --shortstat 的命令。 - Schwern

20
这里提供一种非常简单/粗暴的方法来实现这个目标:
用以下命令可以获得差异大小:git format-patch --stdout ref1..ref2 | wc -c 其中,format-patch 命令会给出 ref1ref2 之间的差异。
对于 ref1/ref2,您可以使用任何有效的Git引用名称,例如 a0b1c2d3HEADHEAD~1 等。
wc -c 命令会给出文件大小(以字节为单位)。
注意:Git提交元数据也会计入字节数。这可能是该方法的一个功能或缺陷,具体取决于您所需的信息。您可以使用更多的 git format-patch 和/或 Unix 管道/grep 命令来更好地控制其结果。

这是一种非常好的、简单明了的技巧,可以让你了解你的提交有多少字节。在接受的答案几年之后,我们仍然分享更好的做事方法。向@EdwardTeach致敬! - Gio
1
请注意,Git 中存储的不是增量而是新对象。该方法显示增量的大致大小。因此,这很有趣,但很难从产生的数字中得出结论。 - Eric Walker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接