在一个包含多个分支的git仓库中,我已将一个功能分支合并到主分支中,并从主分支合并到功能分支中。 我现在如何使用git log
只查看在功能分支上进行的提交?我需要过滤掉对其他分支发出的评论,即使它们已被合并回这个功能分支。
$ git status
On branch some_feature
$ git checkout master
$ git merge some_feature
$ git checkout some_feature
$ git merge master
$ # Lots of coding and days gone by
$ git log --some_magic_here
如果重要,我想要运行git log
的机器与用于编码该功能的机器不同。我需要此功能才能对其他开发人员的工作执行代码审核。在审核一个特定功能分支时,按author=SomeDev
过滤并没有帮助。
答案 0 :(得分:4)
--first-parent
(请参阅git rev-list
documentation)和其他一些选择标准。 Git没有跟踪"实际提交了哪个分支"。例如,假设您在分支B
上并执行此操作:
$ git checkout --detach B
[message about "detached head"]
[edit some file here, and git add result]
$ git commit -m message
$ git branch -f B HEAD
$ git checkout B
这将向分支B
的提示添加新提交,即使提交是在不在分支上的时候进行的。或者,假设有两个分支B1
和B2
都指向提交C7
:
... <- C5 <- C6 <- C7 <-- B1, B2
如果您的父项为C8
的新提交C7
,则将分支B2
指向C8
,该提交现在位于分支B2
上。如果您在分支B1
上进行了新提交,那么B1
也会指向C8
,但如果您然后使用git reset
移动B1
指向C7
,无法再告诉 1 提交最初是在B1
而不是B2
进行的。
所有这一切,如果你在合并分支时保持良好的一致性,你可以在提交图上执行图遍历,找到提交&#34;之间的#34;特定的合并,然后通过一个特定的父链,来检测提交可能完成的提交。例如,如上所述feature
和master
,假设始终在feature
上进行提交,然后feature
会定期合并到master
--no-ff
这样可以确保master
上的每个合并提交都是真正的合并提交,而不仅仅是快进。然后图形模式将如下所示:
... --X--*------*-o---o-----*--* <-- master
\ / \ / /
A--B--C--D--E--F--G--H <-- feature
(其中&#34;时间&#34;随着向右移动而增加,*
节点是在分支master
上进行的合并提交,其中o
个节点代表其他提交在主人身上。)
在这种情况下,您可以通过从feature
(提交feature
)的提示开始并且仅遍历第一个父提交来查找(可能)在H
上进行的提交 - 这些是A
到H
- 然后通过仅master
上的第一次父提交来丢弃可查找的提交。第二个标准消除了上面标记为X
的提交(以及任何先前的提交)。 (请注意,在合并提交E
的情况下,其第一个父级为D
,其第二个父级为o
在master
左侧将其提交到左侧。对于master
上的所有合并,第一个父级位于同一行,而第二个父级位于feature
下方和左侧。)
这是否足够取决于您(和其他人)在提交过程中的纪律。如果master
有自己的内部分支和合并,您可能会有一个更像这样的图表:
... --X---Y---*-----*-o---o---------*--* <-- master
\ \ / / \ / /
\ Z / \ / /
\ / \ / /
A--B--C--D------E--F--G--H <-- feature
现在您不能轻易地使用第一个/非第一个父测试,因为提交Y
或Z
必然是{{1}上合并的第二个父级},但请注意,master
无法首先遍历Z
feature
,E
是直接在&#34;上的合并提交&#34}。 feature
,其第二个父提交位于master
。
换句话说,我直接在&#34;上使用了一个稍微特别的短语&#34;一个分支,用于标识从分支提示开始可查找的提交,以及仅通过第一个父级向后工作的提交。对于feature
,这些{仍然是A
到H
,加上不幸的是X
及其(第一个)父母。
git rev-list
命令,这是git非常重要的命令之一 - 它是git rev-parse
的大姐姐版本,也是非常重要的 - 有一个标志,专门实现这个&#34;直接在&#34;概念,即--first-parent
。 rev-list命令通过提交图的某些部分遍历 2 :你告诉它一些提交开始,它发现提交的父母和那些父母&#39 ;父母和他们的父母,等等。如果您指定--first-parent
,则只会找到每个提交的第一个父级。 (这显然只会影响合并提交,因为根据定义,非合并提交最多只有一个父提交。)
在您的特定情况下,您还表示您希望消除合并到您的feature
分支,即合并直接在feature
上的提交。要执行此操作,只需告诉rev-list使用--no-merges
从其输出中排除合并提交。
消除提交X
及更早版本有点困难,但事实证明, 难以提供知道哪些分支包含X
等提交,你想要排除,是的。 --not
参数(包括几种替代拼写)告诉rev-list提交 exclude 的内容。所以:
git rev-list --first-parent feature --not master --no-merges
直接识别提交列表&#34;&#34;功能(A
到H
)但不直接在master
(X
及更早版本),然后仅列出那些不合并的功能(从而消除了提交E
)。
您可能希望进一步减少这种情况,例如,可能使用提交时间戳(--since
和--until
)。您可能(或可能不)想要更改列出修订的顺序,例如,可能使用--topo-order
将它们按图形顺序而不是日期顺序放置。
git log
幸运的是,git log
有效地使用您的修订说明符调用git rev-list
。因此,不必首先使用git rev-list
,然后以某种方式将结果提供给git log
,您可以将这些相同的说明符赋予git log
。事实上,在确定你想要的限制器时(使用--since
和--until
之类的东西),git log
更容易使用,因为大量的原始SHA-1是对人类没有多大用处。
1 实际上,保留分支运动历史的reflog确实能让你知道,但只能在一台本地机器上运行;问题是这必须在不同的系统上完成,其中reflog不可用。在任何情况下,reflog条目都会在一段时间后过期,默认情况下会在90天内过期。
2 当然,除非您使用--no-walk
。