两个Commitishes之间的提交数量

63

如何在git中查找两个提交(Commit)之间的提交数量?

此外,是否有一种方法可以在GitHub上的任何项目中执行相同操作(使用UI而非API)?


如果你有两个提交,那么你就有它们的修订号,对吧?然后相减?我可能过于简化或者没有理解这个问题。 - Carlos Bribiescas
1
@CarlosBribiescas 在 git 中,commitish 不一定是 commit ID。此外,即使您有 commit ID,在 git 中,commit ID 也是哈希值(ff3823ac、554fbae3 等)。 - haneefmubarak
4个回答

64

在我回答你之前,请考虑一下这个提交图:

        o -----------
       /             \
... - A - o - o - o - B
       \         /
        o ----- o
每个 o 表示一个提交,AB 也代表提交(它们只是字母,让我们谈论“特定的”提交)。在提交 A 和提交 B 之间有多少次提交?
对于更线性的情况,可以使用 git rev-list --count A..B 命令来计算它们之间的提交数量,然后再决定“之间”是什么意思(是否包括 B 而不包括 A?这是 git rev-list --count 命令的行为)。在分支较多的情况下,该命令会列出所有分支的提交。例如,添加参数 --first-parent 可以只跟踪“主线”。
(您还提到了“commitish”,表示我们可能有注释标签。这不会影响 git rev-list 命令的输出,因为它只计算具体的提交。)
修改:由于 git rev-list --count A..B 命令包括提交 B(但省略提交 A),而您想要排除两个端点,所以需要减去一。在现代 Shell 中,您可以使用 Shell 算术完成这一操作。
count=$(($(git rev-list --count A..B) - 1))

例如:

$ x=$(($(git rev-list --count HEAD~3..HEAD) - 1))
$ echo $x
2

(这个特定的仓库具有非常线性的图形结构,因此这里没有分支,在最新提交版本和向前三个版本之间有两个提交记录)。但请注意,如果AB标识相同的提交,则会产生-1:

$ x=$(($(git rev-list --count HEAD..HEAD) - 1))
$ echo $x
-1

所以您可能首先想要检查一下:

count=$(git rev-list --count $start..$end)
if [ $count -eq 0 ]; then
    ... possible error: start and end are the same commit ...
else
    count=$((count - 1))
fi

如果您想要获取所有分支的总和,该怎么做呢?此外,通过“between”,我想到的是“排除”(不包括A和B)。 - haneefmubarak
git rev-list 命令(不带 --count)遍历整个图形,打印出您选择的每个提交的 SHA-1。A..B 表示“从 B 开始选择可到达的每个提交,并通过所有父提交向后工作,但然后排除从 A 开始可到达的每个提交”,因此如果您想要它们全部,那么您就很棒,因为这就是您得到的。同时,由于 rev-list 包括 A 本身,所以需要减去一个。 - torek
你能在你的答案中加上注释,还有一个一行代码来减去一个数(也许把结果管道传递到 | xargs expr -1 +),然后我会标记它为正确的。 - haneefmubarak
完成。同时我修正了关于哪个提交包含在遍历的修订版本中的注释(计数的是B,而不是A)。 - torek
这是否保证AB的父节点?如果A在另一个分支中,尚未合并...或者是B的后代呢? - aross

51
$ git log 375a1..58b20 --pretty=oneline | wc -l

指定起始提交和终止提交,然后计数行数。这应该是这两个提交范围之间的提交数。使用"--pretty=oneline"格式化,以使每个提交占用单独的一行。

请注意,使用两个点(375a1..58b20)与使用三个点(375a1...58b20)是不同的;有关此事以及确定要使用哪个的更多信息,请参见Git提交范围中双点“..”和三点“…”之间的差异是什么?

至于GitHub上的GUI,我不知道如何完成同样的任务。但是,因为以上是直接使用Git和Bash执行此操作的可能方式,所以这应该很简单。


1
在上述命令中,需要在提交 ID 之间放置两个点或三个点? - a.saurabh
1
这可能只是从这里复制过来的:http://gal.steinitz.com/blog/2013/07/27/git-tips-count-number-of-commits-between-two-commits/。 - kghbln
1
值得阅读@kghbln评论链接中的评论,以了解第一次和第二次提交的顺序以及不依赖于wc的选项(即git rev-list [newer] ^[older] --count)的详细信息。 - matt wilkie
用两个点,我什么也得不到。用三个点,它就可以工作了。 - Abhijit Sarkar

7

另一个单行代码

git rev-list newer ^older --pretty=oneline --count

使用修订号或SHA值:

git rev-list db8fb95e6256bd52a668bae82d8b5a73152869fa ^1aeae117c58c173fee9cb3550297498142887aa5 --pretty=oneline --count
  • [newer]和[older]可以是SHA、分支或标签。
  • 重要提示:如果你的git图表比较复杂,你应该阅读@torek的优秀答案
  • 感谢@matt wilkie在评论中以及原始来源的贡献。

0

提交范围在损坏的代码库上可能会失败:

$ git rev-list --count b00aa8ded74..master
error: Could not read 29026cc404895cc9f9afa55c4e2d53b7a4a5a319
fatal: revision walk setup failed

$ git log --oneline b00aa8ded74..master | wc -l
error: Could not read 29026cc404895cc9f9afa55c4e2d53b7a4a5a319
fatal: revision walk setup failed

替代方案:git loggrep

depth=$(git log --format=%H $rev2 | grep -m1 -n -x $rev1 | cut -d: -f1)

grep -m1 会在第一次匹配后停止 git log,因此不会出现错误。


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