使用git log显示合并期间更改的文件

时间:2016-06-14 00:55:29

标签: git merge git-log

我正在执行以下命令:

git log --name-only –pretty="format:%H %s" -- *.sql --grep="JIRA-154"

以格式返回结果:

[commitid1] [comment]
path/to/file1/file1.sql
path/to/file2/file2.sql
path/to/file3/file3.sql

[commitid2] [comment]
path/to/file2/file2.sql
path/to/file4/file4.sql

输出被重定向到一个文件,格式正是我正在寻找的,但是合并提交是个问题。从未列出作为合并的一部分而更改的文件。相反,我最终会得到以下内容:

[commitid3] [merge comment]
[commitid4] [comment]
path/to/file3/file3.sql

我显然在这里误解了一些东西,因为我希望看到合并期间发生变化的文件。有没有办法在输出中包含这些文件?

2 个答案:

答案 0 :(得分:21)

TL; DR

尝试将-m选项添加到git log选项中。这使得Git"分裂"每次合并,以便它将合并两次,一次针对每个父项。如果没有这个或其他类似的选项,git log会找到合并但后来根本看不到它们。

此外,作为ElpieKay commented,您需要将--grep=<regexp>放在--之前。编写"*.sql"(也就是引号)也可能是一个好主意,以防止shell扩展星号本身(细节因shell而异,取决于是否有*.sql当前工作目录中的文件。)

长版

作为Tim Biegeleisen said,问题源于合并提交的性质。

通常,为了向您展示提交中的更改,Git会运行一个简单的git diff parent self,其中 parent self 分别是提交的父级和提交本身。 git loggit show都以不同的方式和略有不同的情况执行此操作。最明显的是git show默认每次都显示差异,但git log仅在给定-p或其中一种差异控制选项(例如--name-only)时执行差异

合并是不同的

合并提交是一个包含两个 1 父项的提交。这意味着git loggit show必须运行两个 git diff命令。 2 事实上,git show确实运行了两个差异,但是 - 默认情况下 - 将它们变成combined diffshows only those files whose merge-commit version differs from both parents。但无论出于何种原因, 3 git log默认情况下不会这样做。

即使git log显示差异,但它在合并时表现得特别奇怪(我甚至可能会说很糟糕)。虽然git log -pgit log --name-status在常规提交上运行(单个)差异,但在具有多个可见父项的提交上并不运行差异 ,除非你强迫它。

单独使用-m始终有效。该标志实质上告诉git log(和git show)将分解合并为多个单独的虚拟提交&#34;。也就是说,如果提交 M 是与父母 P1 P2 的合并,那么 - 为了diff的目的,至少-Git充当虽然有一个提交 MP1 与父 P1 ,另一个提交 MP2 与父 P2 。你得到两个差异(以及差异标题中的两个提交ID)。

添加--first-parent告诉git log忽略合并的第二个(以及任何其他)父级,这使得它只有一个父级。这意味着git log不会跟随所有的旁边分支。因此,您可以使用-m --first-parent,前提是您对合并的其他方面的历史不感兴趣。这会让你只针对第一个父级而不是每个父级的一个差异。

(哪个家长是第一个?嗯,当你跑HEAD时,它就是你git merge的那个。通常情况下,&# #34;提交的主线和#34;即你的分支上的#34;但是如果你的小组随便使用git pull,你可能想要忽略合并的另一面,因为git pull将其他人的主要工作转变为"foxtrot merges"小方分支。)

组合差异,再次

除了-m,您可以提供-c--cc(请注意-c有一个短划线而--cc有两个 4 git log让它产生组合差异,就像git show一样。但是,与所有组合差异一样,这会忽略合并提交与父级之间匹配的文件。也就是说,再次给出相同的合并 M ,这次Git比较 M vs P1 M vs < EM> P2 。对于 F 的任何文件,其中 M:F P1:F P2:F 相同,Git什么都没显示。

事实证明,这通常是你想要的。如果提交 M 中的文件 F 与两个父提交之一中的文件 F 匹配,则表示文件来自那个父母。 P1 F P2 F 不匹配的事实通常并不有趣:中的任何更改 P1 P2 中的> F 可能是历史记录中某些早期更改的结果,其中包含我们应该注意它,而不是合并 M

无论如何,这是组合差异背后的逻辑。它并不适用于所有情况,这就是-m存在的原因:&#34;分裂&#34;合并成其组成部分。

1 实际上是两个或两个以上,但是&#34;更多&#34;不寻常;大多数合并提交都有两个父母。具有两个以上父项的合并提交称为章鱼合并

2 git loggit show都内置了大部分git diff,因此他们实际上不必运行其他命令,但它两种方式都是一样的。

3 我不知道原因,当我浏览git log来源时,我才了解到这种特殊行为,试图解释原因git log --name-status没有表现出什么。

4 这是因为--cc long 选项,并且在GNU选项解析中,所有长选项如name-only或{{1获取两个短划线,而所有(单个字母)选项(如cc)获取一个短划线。

答案 1 :(得分:1)

您观察此行为的原因是,在合并提交的情况下,有两个更改的文件集,其中一个来自每个父项。此处的一个选项是在运行--first-parent -m时使用git log选项:

git log --name-only --grep="JIRA-154" --first-parent -m –-pretty="format:%H %s" -- "*.sql"

这将告诉Git将重点放在发生合并的主分支上,仅显示此提交的文件集。

检查here以获取文档,并here查看精彩的博文。