在外部3向差异工具中查看已经提交的Git合并

时间:2012-06-12 14:26:15

标签: git merge commit difftool

有没有办法查看已在3-way diff中提交的合并?

如果3周前分支机构之间发生了巨大的合并,有没有什么方法可以在像BeyondCompare3这样的外部差异工具中看到它的3路差异?我正在寻找只是合并提交中更改的文件。奖金,如果我能得到它只显示冲突和任何手动更改,而不是看到两个分支之间的文件的完整差异。

如果左侧有<<<<<<<<<<<<<<<<<<<<< =====>>>>>冲突标记和右侧是承诺的结果。

我尝试查看 diff-tree diff-files diff difftool 显示和其他人,无法弄明白。我知道gitk会在合并提交中显示更改,但我不喜欢上下差异视图,当有大量更改时很难理解。

如果我能做git difftool --cc firstparent..secondparent..result

之类的事情

3 个答案:

答案 0 :(得分:6)

更新回答:我的原始版本的脚本存在缺陷,因为$conflicting_files实际上并不仅包含真正存在冲突的文件,而是所有已更改的文件在两个父分支中(但不一定有冲突)。此外,它没有使用理论中所宣传的“已配置的合并工具”,而是diffuse。我已在current version of the script中解决了这两个问题。

原始回答: 假设我们有一个主要开发的“主”分支,以及一个“主题”分支,它在一些(较旧的)master状态之上添加了一些功能。通过说你只是在寻找合并提交中更改的文件,我假设你只对在合并提交中引入“master”的更改“主题”(包括任何冲突解决方案)感兴趣,而不是非由于“主题”分支,在“主”中完成的冲突变化。进一步假设“master”是合并提交的第一个父级,“topic”是第二个,这可以通过

实现
git difftool <merge commit>^1 <merge commit>

请注意,在此处使用3向差异是没有意义的,因为我们正在查看包含任何冲突解决方案的状态。这也是GitHub为合并提交显示的内容,顺便说一下,参见例如我用于测试的this merge commit

要在三向差异工具中仅查看冲突的文件及其分辨率,我想出了这个脚本

#!/bin/sh

if [ $# -ne 1 ]; then
    echo "Rationale : Show the conflict resolution of a given merge commit in the configured merge tool."
    echo "Usage : $(basename $0) <merge commit>"
    exit -1
fi

# Test e.g. with https://github.com/git/git/commit/8cde60210dd01f23d89d9eb8b6f08fb9ef3a11b8
our=$1^1
their=$1^2
base=$(git merge-base $our $their)

conflicting_files=$(git merge-tree $base $our $their | grep -A 3 "changed in both" | grep "base" | grep -Po "[^\s]+$")
for f in $conflicting_files; do
    diffuse -r $our -r $base -r $their $f
done

我正在使用Diffuse而不是Beyond Compare,因为第一个可以直接在Git提交上工作而不是本地文件;根据自己的喜好改变参数的顺序。要使用BC,您可能需要进行临时检查;我也在考虑重做合并,应用已知的解决方案,并运行git mergetool配置的任何内容,但这两个想法都需要更多的工作,以免弄乱你的工作树并正确地进行清理。 / p>

答案 1 :(得分:2)

我不知道如何在没有hackery的情况下在git中进行三向diff,但对于双向diff我会使用meld。如果检查项目的三个不同版本,meld能够执行三向差异,请按目录执行新的差异并选择“三向比较”选项。

首先安装meld

sudo apt-get install meld

然后将meld设置为difftool

git config --global diff.tool meld

查找提交

git log | more

打开提交

git difftool <old-version>..HEAD

答案 2 :(得分:0)

和sschuberth一样,我编写了一个脚本,帮助我找到合并提交中的更改。它使用vimdiff一次在单个文件上工作,以显示父项和合并提交之间的差异。

#! /usr/bin/env ruby

require 'pp'
require 'tmpdir'

merge = ARGV[0] || abort("I need a merge commit as the first argument")
file = ARGV[1] || abort("I need a path as the second argument")
cmd = "vimdiff"

commits = `git log -n 1 #{merge} --format="%H %P"`.split(' ')
abort "expected three commits" unless commits.size == 3
commits[0], commits[1] = commits[1], commits[0]
tmpdir = Dir.mktmpdir
commits.each do |commit|
  tfile = "#{tmpdir}/#{commit[0..10]}"

  puts "git show #{commit}:./#{file} > #{tfile}"
  `git show #{commit}:./#{file} > #{tfile}`
  cmd += " #{tfile}"
end
puts cmd
exec(cmd)

它有点hacky但我发布了它帮助某人的机会。