git rev-list
一种快速的方法是执行类似于git status
中"upstream"的操作。具体来说,git status
只会计算当前分支上没有在上游分支中的修订版本数量。例如,考虑分支foo
有一个上游分支origin/foo
,并假设您已经进行了三次本地提交,然后使用git fetch
带入了一个上游提交:
L - L - L <-- foo
/
... - C - C
\
U <-- origin/foo
这里的C
代表普通提交,L
代表本地提交,U
代表上游提交。如果你在分支foo
上运行git status
,你会看到 "ahead 3, behind 1"。
以下是git如何得出这些数字:
git rev-list foo --not origin/foo
:这将生成一个列表,其中包含在foo
上但不在origin/foo
上的所有提交。也就是说,从origin/foo
(即提交U
)开始,划掉提交和所有之前可达的提交:这是U
和所有的C
提交。然后,从foo
开始查找所有可达的提交,而这些提交尚未被划掉:这仅是三个L
提交。
添加--count
参数到git rev-list
的参数中,以使其输出计数而不是原始提交ID SHA-1值。
对于git rev-list origin/foo --not foo
,重复上述步骤:这是从origin/foo
可达但从foo
不可达的所有提交,例如此示例中只有提交U
。(同样,添加--count
以仅获得计数,而不是实际的提交ID。)
请注意,foo --not origin/foo
在gitrevisions语法中也可以写成origin/foo..foo
。(在git status
的情况下,它始终查看当前分支 - 这个分支通过HEAD
命名 - 以及其上游。您可以使用@{upstream}
语法来获取上游的名称,或缩短为@{u}
;如果完全没有列出名称,则默认使用HEAD
。因此,要重新实现git status
,您可以只查看git rev-list --count ..@{u}
和git rev-list --count @{u}..
。)
rev-list
与使用git cherry
因此,如果您想计算从分支feature
可达但从分支master
不可达的提交数量,您可以使用相同的方法,但使用名称feature
和master
。 git rev-list
语法master..feature
命名从feature
可达但不从master
可达的所有提交,而--count
会得到计数:
git rev-list --count master..feature
如果您从一个分支挑选了一些提交到另一个分支,使它们具有不同的提交ID但相同的差异,则这将“重复计算”。例如,假设feature
有五个提交,而master
没有,但随后您(或其他人)决定将这五个提交中的一个挑选到master
中,那么现在可能是这样的: D - E - F - G - H <-- feature
/
... - C - C
\
F' <-- master
其中F'
基本上只是提交F
的副本。如果您要求git rev-list
计算不在master
上的feature
提交次数,那么您将得到5;但如果您要求git cherry
查找不在master
上的feature
提交,它将从列表中消除提交F
,因为它会看到F'
是F
的副本。因此,如果您计算git cherry
列出的提交次数,则会得到4而不是5。
使用 git cherry
命令查找存在于一个分支中而不存在于另一个分支中的提交记录。
git cherry -v master feature
它将列出功能分支中存在但在主分支中不存在的所有提交。
同样,
git cherry -v feature master
会列出主分支中存在但特性分支中不存在的所有提交。
您还可以提供第三个参数,以选择起始点。
git cherry -v feature master 1b219e
更新:
您可以创建一个别名来将这两个内容合并。
[alias]
mydiff = !sh -c 'echo "Commits in $2 not in $1" && git cherry -v $1 $2 && echo "Commits in $1 not in $2" && git cherry -v $2 $1' -
使用,
git mydiff master feature
git cherry
实际上比git status
的方法更高级,因为它比较差异,我将在另一个答案中写出。 - torek[alias] cdiffcount = !sh -c 'echo "Commits in $2 not in $1: " && git cherry $1 $2 | wc -l && echo "Commits in $1 not in $2: " && git cherry $2 $1 | wc -l' -
- Michael