即使每个更改的文件都与其中一个父文件一致,如何使用合并的diff输出来“ git show”合并提交?


185

在执行“简单”合并(一次没有冲突)后,git show通常只显示类似

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

这是因为,对于合并,git show使用组合的diff格式,该格式将忽略与任一父版本一致的文件。

有没有办法强制git在组合diff模式下仍然显示所有差异?

这样做git show -m会显示差异(分别使用新版本和所有父版本之间的成对差异),但我更希望在各个列中使用+/-标记差异,例如在组合模式下。


1
@ Tilman Vogel:请查看已接受的答案-看起来还有更好的答案
Jayan

1
@Jayan尽管其他答案因为包含有用的提示而更为流行,但它们实际上并没有像我做的双向差异那样接近我的问题。我正在寻找三向差异。
Tilman Vogel's

Answers:


-3

否,无法通过做到这一点git show。但这有时肯定会很好,并且在git源代码中实现起来可能相对容易(毕竟,您只需要告诉它不要删节它认为无关的输出即可),因此可以进行补丁可能会被git维护者接受。

但是要小心您的期望;将分支与三个月前分叉的单行更改合并将仍然与主线产生巨大差异,因此,这样的完整差异几乎完全无济于事。这就是为什么git不显示它。


12
请不要说“不可能做到这一点”,因为这显然是可能的-请参阅其他答案。这说起来很令人误解。
kgadek

1
git show HEAD ^ ... HEAD; #根据@hesham_EE的解决方案。
迈克尔·迪米特

git show HEAD〜1 ... HEAD〜0-仅名称; #更好的语法。对于迭代的公关。
Michael Dimmitt

255

查看提交消息:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

注意这一行:

Merge: fc17405 ee2de56

获取这两个提交ID并将其反转。因此,为了获得所需的差异,您可以执行以下操作:

git diff ee2de56..fc17405

仅显示更改文件的名称:

git diff --name-only ee2de56..fc17405

并提取它们,您可以将其添加到您的gitconfig中:

exportfiles = !sh -c 'git diff $0 --name-only | "while read files; do mkdir -p \"$1/$(dirname $files)\"; cp -vf $files $1/$(dirname $files); done"'

然后通过以下方式使用它:

git exportfiles ee2de56..fc17405 /c/temp/myproject

感谢您的建议,但我认为这不能解决我的问题。由于评论标记和格式的限制,我在评论中添加了评论。抱歉!需要得到同行评审,直到可见。
Tilman Vogel,

6
看来,我的编辑被拒绝了。总结:您的差异不显示哪个添加来自哪个分支。而且您无法区分是在第二个分支中添加了更改还是在第一个分支中删除了更改。
Tilman Vogel

45
更好的解决方案是git diff fc17405...ee2de56-这将显示ee2de56上的所有更改,这些更改可以通过fc17405上的提交实现,我相信这是您想要的。注意3点而不是2点。
Kris Nuttycombe

1
@KrisNuttycombe 3点和顺序。您的评论就是我一直在寻找的东西,我认为这更像是OP想要的。
2013年

@KrisNuttycombe某种程度上无法使用git log,它仍然显示所有提交,例如..变体。..并为...做相同的操作log,但因为diff它们不同!如何获取已合并到此分支的提交列表?
鲁迪

77

更好的解决方案(由@KrisNuttycombe提及):

git diff fc17405...ee2de56

对于合并提交:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

显示ee2de56从提交可以到达的所有更改fc17405。注意提交哈希的顺序-与合并信息中显示的顺序相同:Merge: fc17405 ee2de56

还要注意3点...而不是2

有关已更改文件的列表,可以使用:

git diff fc17405...ee2de56 --name-only

这正是我+1之后的情况。
geedoubleya

这实际上显示了合并冲突的结果,而其他答案则没有。
波德

12

您可以在合并之前将HEAD设置为一次提交来创建分支。然后,您可以执行以下操作:

git merge --squash testing

这将合并,但不会提交。然后:

git diff

5

好像在这里回答:https : //public-inbox.org/git/7vd392ezhx.fsf@alter.siamese.dyndns.org/

因此,以类似的方式运行

$ git diff --cc $ M $ M ^ 1 $ M ^ 2 $(基于git merge-base $ M ^ 1 $ M ^ 2)

应该显示一个组合补丁,该补丁说明相对于其父级和合并基础中记录的状态的$ M状态。


您是否知道是否可以配置任何工具来并排显示这种差异(可能在几列中显示)(例如在IntelliJ合并冲突解决窗口中)?您的回答恰恰是我在寻找
Max

@Max不,我恐怕不会。谷歌搜索“ n向视觉差异”确实提供了一些链接,因此我尝试了这些链接。
max630

4

我认为您只需要'git show -c $ ref'。在a8e4a59上的git存储库上尝试此操作将显示组合的diff(2列之一中的正负字符)。就像git-show手册中提到的那样,它几乎代表了“ git diff-tree”,因此这些选项看起来很有用。


3
不,对于“简单”合并,git show -c $ref显示的输出与我引用的相同,即没有差异。-c选择与commit commit的默认模式非常相似的组合diff模式'--cc',请参见git help showgit help diff-tree。两者都完全省略了与该文件的父版本一致的文件。
Tilman Vogel

a8e4a59我的意思是确实不属于合并提交的类别。此合并提交确实包含一个与其两个父版本都不同的文件。Documentation/git-fast-import.txt从一个父母那里添加了一些东西,从另一个父母那里添加了一些东西。这导致的非空输出git diff-tree --cc。但是,仅显示此“冲突”情况下的更改。所有“干净的”合并结果(git show -m a8e4a59参见)都不会显示。
Tilman Vogel,

1
@TilmanVogel:感谢您指出“无趣的”文件合并被排除在git show -c输出之外。(man git-diff-tree确实说过“此外,它只列出了所有父母修改过的文件。”但我肯定没有发现这一点。)
Paul Whittaker 2014年

3

在您的情况下,您只需要

git diff HEAD^ HEAD^2

或者只是哈希为您提交:

git diff 0e1329e55^ 0e1329e55^2

4
不,这只是两个父母之间的简单双向差异。我问的是一个模式同时显示之间的差异git merge-base HEAD^ HEAD^2,并HEAD^HEAD^2在如对于合并有冲突的文件做了同样的风格。
Tilman Vogel 2013年

3

如果您的合并提交是如上所述的提交0e1329e5,则可以通过以下方式获取此合并中包含的差异:

git diff 0e1329e5^..0e1329e5

我希望这有帮助!


3

如果您坐在合并提交,则显示差异:

git diff HEAD~1..HEAD

如果您不在合并提交中,则只需将HEAD替换为合并提交即可。这种方法似乎是最简单,最直观的。


1
这不是“ combined diff”输出。在这里,每对父母与HEAD之间的差异都不是问题。
Tilman Vogel,

2

可以将diff-tree命令与-c标志一起使用。此命令显示您在合并提交中更改了哪些文件。

git diff-tree -c {merged_commit_sha}

我从Git-Scm得到了-c标志的描述:

该标志改变了合并提交的显示方式(这意味着仅在命令被赋予一个或--stdin时才有用)。它同时显示了每个父项与合并结果之间的差异,而不是一次显示父项与结果之间的成对差异(这是-m选项的作用)。此外,它仅列出从所有父级修改而来的文件。


2
看起来像是一篇关于该主题的好文章:haacked.com/archive/2014/02/21/reviewing-merge-commits,也许也是这样:longair.net/blog/2009/04/16/git-fetch-and-merge
Devin G Rhode

1

我构建了一种通用方法来对合并的提交执行各种操作。

第一步:通过编辑为git添加别名~/.gitconfig

[alias]
  range = "!. ~/.githelpers && run_on_merge_range"

第二步:在中~/.githelpers,定义一个bash函数:

run_on_merge_range() {
  cmd=$1; shift
  commit=$1; shift
  range=$(git show $commit | grep Merge: | awk '{print $2 "..." $3}')
  echo "git $cmd $range $@"
  if [ -z $range ]; then
    echo "No merge detected"
    exit 1
  fi
  git $cmd $range $@
}

第三步:获利!

git range log <merge SHA> --oneline
git range diff <merge SHA> --reverse -p
git range diff <merge SHA> --name-only

这里可能还有很多改进的余地,我只是凑在一起克服了令人讨厌的情况。随意模拟我的bash语法和/或逻辑。


请注意,您可能要改变“......”为“..”中的‘AWK’位,这取决于你需要什么,什么吩咐你正在运行:stackoverflow.com/questions/462974/...
Nerdmaster
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.