如何使用git log -p显示合并提交中的更改

18

我有一个分支,其中缺少一个函数定义,但该函数仍在使用,导致崩溃。这个函数定义可能是在合并过程中被删除的。我已经运行了"git log -p",并搜索了该函数的定义,可以看到它被定义了,但后来却找不到被删除。这让我相信"git log -p"不显示合并更改?如何获得这个功能?


1
你可以使用 git show <merge commit> 或者 git log -c 命令。从 git log 的手册中可以看到:-c 选项可以同时显示合并结果与每个父提交之间的差异,而不是一次只显示一个父提交和结果之间的差异。此外,它只列出了所有父提交中被修改的文件。 - odradek
使用 Git 2.33 (Q3 2021) 版本,简单的 git log -m 命令就足够了,因为它会显示补丁。请参见我的更新答案 - VonC
2个回答

16
这让我相信 'git log -p' 不显示合并更改?我如何获得此功能?您是正确的:默认情况下,'git log -p' 会显示合并提交,但根本不尝试显示其差异。如评论中 odradek 写道,添加 '-c' 选项将使 'git log' 显示组合差异。您还可以使用 '--cc'(请注意,对于 '-c' 只有一个破折号,而对于 '--cc' 则有两个破折号),它也显示组合差异,或者使用 '-m',它有效地为差异目的拆分合并,并针对每个父级显示一个差异。
这三个选项同样适用于git show。但不知何故,git show默认为--cc,而git log则没有默认值。
只有在某些合并情况下,这三个选项之间的区别才能清楚地显示出来,而且有点棘手。然而,我们可以非常清楚地说一件事情:任何组合差异仅显示与所有父级不同的文件。也就是说,git show -cgit show --cc都会修剪所显示的内容,以提供帮助。(根据可以显示的内容,--cc形式可能修剪比-c更多。但我没有方便的例子。)

例如,考虑在Git存储库中的提交3e5c63943d35be1804d302c0393affc4916c3dc3commit)。这是一个合并(其父代是c13c783...20690b2...),如果我们运行两个独立的git diff命令,我们可以看到与其第一个父代相比,只有两个文件发生了更改:

$ git diff --name-status 3e5c639^1 3e5c639
M       builtin/remote.c
M       t/t5505-remote.sh

但与其第二个父文件相比,许多文件(包括那两个)都会发生变化:

$ git diff --name-status 3e5c639^2 3e5c639 | expand
M       .gitignore
M       .mailmap
M       Documentation/Makefile
A       Documentation/RelNotes/2.12.0.txt
M       Documentation/SubmittingPatches
A       Documentation/asciidoctor-extensions.rb
M       Documentation/blame-options.txt
M       Documentation/cat-texi.perl
M       Documentation/config.txt
M       Documentation/diff-config.txt
[snipped here - but the same two files do appear in the 339-entry list]

如果我在这个上运行git show --cc,我将得不到任何差异列表;如果我在其上运行git show -c,我将得到一个builtin/remote.ct/t5505-remote.sh的差异列表。
如果我在此上运行git show -m,我会得到两个单独的git diff列表。 两个都不是“组合差异”。第一个以以下方式开始:
commit 3e5c63943d35be1804d302c0393affc4916c3dc3 (from
 c13c783c9d3d7d3eff937b7bf3642d2a7fe32644)

并且只显示前两个文件。第二个以以下内容开始:
commit 3e5c63943d35be1804d302c0393affc4916c3dc3 (from
 20690b213975ad3e9b1bc851f434d818bd2d1de9)

并显示所有339个文件。

使用-m是非常强大的工具,但你需要浏览很多内容进行排序。通常使用--cc-c就足够了。

(另外一个可能有用的技巧是,在使用git log -p查找此类更改时,添加--full-history以确保git log跟踪每个合并的两个分支。只有在通过添加-- <path>选项进行历史简化时才需要这样做。)


6
这让我相信'git log -p'不会显示合并更改?但是从Git 2.31(2021年第一季度)开始,"git log"(man)学会了一个新的--diff-merges=<how>选项,可以显示合并更改。而在Git 2.33(2021年第三季度),git log -m将意味着-p(补丁)(请参见此答案末尾)。

请查看提交 af04d8f提交 1d24509提交 e58142a提交 8efd2ef提交 b5ffa9e提交 388091f提交 5071c75提交 a6d19ec提交 5733b20提交 8c0ba52提交 255a4da提交 3d2b5f2提交 a6e66af提交 d9b1bc6提交 1a2c4d8提交 6fc944d提交 ec315c6提交 14c14b4提交 e121b4b提交 0c627f5提交 3291eea提交 3b6c17b提交 09322b1提交 564a4fc提交 4f54544提交 7acf0d0提交 18f0947提交 a37eec6提交 3d4fd94提交 027c478提交 299a663提交 891e417(2020年12月21日),由Sergey Organov (sorganov)完成。
(由Junio C Hamano -- gitster --合并于提交 aac006a,2021年2月5日)

diff-merges: 实现新的值用于 --diff-merges

Signed-off-by: Sergey Organov

We first implement new options as exact synonyms for their original counterparts, to get all the infrastructure right, and keep functional improvements for later commits.

The following values are implemented:

--diff-merges=            old equivalent 
first|first-parent      = --first-parent (only format implications)
sep|separate            = -m
comb|combined           = -c
dense| dense-combined   = `--cc`

diff-merges: 添加旧助记符选项到--diff-merges

Signed-off-by: Sergey Organov

这里添加了--diff-merges={m|c|cc}的值,以匹配旧选项的助记符,方便那些习惯于使用它们的人。

请注意,例如--diff-meres=cc--cc的行为不同,因为后者意味着-p,从而启用所有提交的差异,而前者仅启用合并提交的差异输出。

diff-merges: 添加'--diff-merges=1'作为'first-parent'的同义词

Signed-off-by: Sergey Organov

现在我们有了--diff-merges={m|c|cc},添加--diff-merges=1作为--diff-merges=first-parent的同义词,以便它也具有更短的助记符。
--diff-merges选项的描述从git-log.txt移动到diff-options.txt中,以便在git-show(man)帮助文档中包含该描述。

doc/git-show:包括--diff-merges说明

diff-options现在在其man页面中包括:

--diff-merges=(off|none|first-parent|1|separate|m|combined|c|dense-combined|cc)

--no-diff-merges

指定用于合并提交的差异格式。默认情况下是{diff-merges-default},除非使用了--first-parent,这种情况下first-parent是默认值。

--diff-merges=(off|none):

--no-diff-merges:

禁用合并提交的差异输出。有助于覆盖隐含值。

--diff-merges=first-parent:

--diff-merges=1:

此选项使合并提交仅显示与第一个父提交相关的完整差异。

--diff-merges=separate:

--diff-merges=m:

-m:

这使合并提交显示相对于每个父提交的完整差异。
为每个父提交生成单独的日志条目和差异。
-m不带-p不会产生任何输出。

--diff-merges=combined:

--diff-merges=c:

-c:

使用此选项,合并提交的差异输出同时显示每个父提交与合并结果之间的差异,而不是逐个显示一个父提交和结果之间的差异。

此外,它仅列出从所有父提交中修改的文件。

-c意味着-p

--diff-merges=dense-combined:

--diff-merges=cc:

--cc:

使用此选项进一步压缩--diff-merges=combined产生的输出,省略在父提交中只有两个变体且合并结果选择其中一个而没有修改的不感兴趣的块。 --cc意味着-p

--combined-all-paths

此标志导致组合差异(用于合并提交)列出所有父提交的文件名。因此,它仅在使用了--diff-merges=[dense-]combined并检测到文件名更改时才起作用(即请求重命名或复制时)。endif::git-log[]

git log现在在其手册页中包括:

:diff-merges-default: off

git show现在在其手册页中包括:

DIFF FORMATTING

下面的选项可用于更改git show生成差异输出的方式。

git show现在在其手册页中包括:

:diff-merges-default: dense-combined


这是基于 Git 2.29(2020年第四季度)的工作,正式记录如下:

请参见 提交5fbb4bc, 提交9a6d515, 提交6cea104, 提交6f2e02a, 提交9ab89a2, 提交6fae74b, 提交eed5332 (2020年7月29日) 由 Jeff King (peff) 提交。
(由Junio C Hamano -- gitster --合并于提交eca8c62, 2020年8月17日)

doc/git-log:澄清合并提交差异的处理方式

签署人:Jeff King

令人惊讶的是,默认情况下,git-log 不会显示合并提交的任何差异。
可以说 "--cc" 是一个合理的默认值,但这非常耗费资源(这就是为什么我们为 "git show"(man) 打开它,但不为 "git log" 打开它的原因)。

至少让我们记录当前的行为,包括最近的 "--first-parent implies -m" 情况。

git log现在在其手册页面中包含以下内容:

请注意,除非使用-c--cc-m之一,否则合并提交将永远不会显示差异,即使选择了像--patch这样的差异格式,也不会匹配像-S这样的搜索选项。

例外情况是当使用--first-parent时,合并将被视为普通单父提交(可以通过提供组合差异选项或使用--no-diff-merges来覆盖此设置)。


还有:

当使用 "git log"(man) 的 "--first-parent" 选项时,为了取消隐式的 "-m" 选项,我们在 jk/log-fp-implies-m 主题中添加了 "--[no-]diff-merges" 选项。

为了保持 "--diff-merges" 选项接受指令如何计算合并提交的补丁的可能性(例如 "cc"? "-p 针对第一个父级?), 重新定义 "--diff-merges" 以获取非可选值,并实现与 "--no-diff-merges" 相同含义的 "off"。

请查看提交 298889d, 提交 405a2fd, 提交 6501580 (2020年8月6日)由Sergey Organov (sorganov)进行。
(由Junio C Hamano -- gitster --提交 a555b51中合并,2020年8月17日)

doc/git-log: 描述 --diff-merges=off

Signed-off-by: Sergey Organov

git log 现在在其man page中包括以下内容:

--diff-merges=off

--no-diff-merges

禁用合并提交的差异输出(默认)。
有助于覆盖 -m-c--cc


在Git 2.32(2021年第二季度), "git log"(man) 学会了 --diff-merges=<style> 选项,并配有一个关联的配置变量 log.diffMerges

查看 提交 364bc11, 提交 17c13e6, 提交 38fc4db, 提交 26a0f58, 提交 4320815(于2021年4月13日)由Sergey Organov (sorganov)提交。
(由Junio C Hamano -- gitster --提交 59bb0aa中合并,于2021年4月30日)

diff-merges: 引入log.diffMerges配置变量

签名:Sergey Organov

新的log.diffMerges配置变量设置了--diff-merges=on将使用的格式。
默认值为“separate”。

添加了log.diffMerges的文档。

git config现在包含在其man页面中:

log.diffMerges

将合并提交的默认diff格式设置为--diff-merges。有关详细信息,请参见git log。默认为separate


从Git 2.33(2021年第三季度)开始,在 "git log"(man) 中,如果没有指定所需的差异格式,则 "-m" 选项将没有任何可见效果;现在它意味着会生成某种形式的差异(默认为 "--patch")。

请查看 提交记录f5bfcc8, 提交记录fd16a39, 提交记录1e20a40, 提交记录23f6d40, 提交记录19b2517, 提交记录e0b1642, 提交记录3ae7fe2, 提交记录faf16d4, 提交记录48229c1, 提交记录7a55fa0 (2021年5月21日) 作者为Sergey Organov (sorganov)
(由Junio C Hamano -- gitster --合并于提交记录8e444e6, 2021年6月14日)

diff-merges: 让 "-m" 隐含 "-p"

签署者:Sergey Organov

Fix long standing inconsistency between -c/--cc that do imply -p on one side, and -m that did not imply -p on the other side.

Change corresponding test accordingly, as "log -m" output should now match one from "log -m -p", rather than from just "log".

Change documentation accordingly.

NOTES:

After this patch

git log -m

produces diffs without need to provide -p as well, that improves both consistency and usability.
It gets even more useful if one sets "log.diffMerges" configuration variable to "first-parent" to force -m produce usual diff with respect to first parent only.

This patch, however, does not change behavior when specific diff format is explicitly provided on the command-line, so that commands like

git log -m --raw
git log -m --stat

are not affected, nor does it change commands where specific diff format is active by default, such as:

git diff-tree -m

It's also worth to be noticed that exact historical semantics of -m is still provided by --diff-merges=separate.

diff-options现在在其手册页面中包含了默认格式。

默认格式可以使用以下方式进行更改:

diff-options现在在其手册页面中包含了:

-m意味着-p

diff-options现在在其手册页面中包含了:

这是-m历史上产生的格式。


注意:从 Git 2.33(2021年第三季度),之前的 "git log -m"(man) 已更改为始终生成补丁输出,这会破坏现有脚本,因此已被撤销。

请查看 提交 6a38e33 (2021年8月5日),作者为Jonathan Nieder (artagnon)
(由Junio C Hamano -- gitster --提交 4c90d89中合并,于2021年8月11日)

撤销'diff-merges:让“-m”意味着“-p”'

署名:Jonathan Nieder

This reverts commit f5bfcc8 (diff-merges: let , 2021-05-21, Git v2.33.0-rc0 -- merge listed in batch #2), which made "git log -m"(man) imply --patch by default.
The logic was that "-m", which makes diff generation for merges perform a diff against each parent, has no use unless I am viewing the diff, so we could save the user some typing by turning on display of the resulting diff automatically.
That wasn't expected to adversely affect scripts because scripts would either be using a command like "git diff-tree"(man) that already emits diffs by default or would be combining -m with a diff generation option such as --name-status.
By saving typing for interactive use without adversely affecting scripts in the wild, it would be a pure improvement.

The problem is that although diff generation options are only relevant for the displayed diff, a script author can imagine them affecting path limiting.
For example, I might run

git log -w --format=%H -- README

hoping to list commits that edited README, excluding whitespace-only changes.
In fact, a whitespace-only change is not TREESAME so the use of -w here has no effect (since we don't apply these diff generation flags to the diff_options struct rev_info::pruning used for this purpose), but the documentation suggests that it should work

Suppose you specified foo as the <paths>. We shall call
commits that modify foo !TREESAME, and the rest TREESAME. (In
a diff filtered for foo, they look different and equal,
respectively.)

and a script author who has not tested whitespace-only changes wouldn't notice.

Similarly, a script author could include

git log -m --first-parent --format=%H -- README

to filter the first-parent history for commits that modified README.
The -m is a no-op but it reflects the script author's intent.
For example, until 1e20a40 (stash list: stop passing , 2021-05-21, Git v2.33.0-rc0 -- merge listed in batch #2) (stash list: stop passing "-m" to "git log", 2021-05-21), "git stash list"(man) did this.

As a result, we can't safely change "-m" to imply "-p" without fear of breaking such scripts.
Restore the previous behavior.

Noticed because Rust's src/bootstrap/bootstrap.py made use of this same construct: https://github.com/rust-lang/rust/pull/87513.
That script has been updated to omit the unnecessary "-m" option, but we can expect other scripts in the wild to have similar expectations.

diff-options现在包含在其手册页面中:

-m仅在同时给出-p时才会生成输出。


注意:gitk已经在Git 2.34中修复:https://github.com/git/git/commit/e8332242b74634ce34a37b0896b86b59848cf8cd - VonC

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