2012-06-12 35 views
30

有没有任何方法可以查看已在3-way diff中提交的合并?在外部三维差异工具中查看已提交的Git合并

如果分支之间的巨大合并是在3周前提交的,有没有什么办法可以在像BeyondCompare3这样的外部diff工具中看到它的三向差异?我正在寻找只是在合并提交中更改的文件。如果我可以让它只显示冲突和手动更改的任何内容,而不是看到两个分支之间的文件的全部差异,那么奖金也是如此。

我不介意解决了2路差异,如果左侧有< < < < < ===== >>>>>冲突标志,右侧是承诺的结果。

我试图寻找DIFF树DIFF-文件DIFFdifftool显示,和其他人并不能弄明白。我知道gitk会在合并提交中显示更改,但我不喜欢over-under diff视图,并且很难理解何时发生大量更改。

如果只有我可以做类似git difftool --cc firstparent..secondparent..result

回答

2

我不知道该怎么做的混帐三路差异没有一些两轮牛车,但对于一个双向差异我会用meldmeld如果您签出项目的三个不同版本,按目录做一个新的差异并选择“三向比较”选项,则可以执行三向比较。

首先安装MELD

sudo apt-get install meld

然后设置MELD为difftool

git config --global diff.tool meld

查找提交

git log | more

打开提交

git difftool <old-version>..HEAD

6

更新答案:我原来下面的脚本是在意义上有缺陷是$conflicting_files其实并不只包含真的有冲突的文件的版本,但被更改的所有文件在两个分支机构(但不一定有冲突)。另外,它没有使用在原理中广告的“配置的合并工具”,但是diffuse。我已经在current version of the script中解决了这两个问题。

原来的答复: 比方说,我们与主要的发展事“主”分支,和“主题”分支,它增加了对大师的一些(旧的)状态顶部的一些功能。通过说你正在寻找合并提交中改变的文件,我假设你只对在合并提交(包括任何冲突解决方案)中引入“主”的更改“主题”感兴趣,自“主题”分支以来,在“主”中完成的相互冲突的更改。进一步假设“大师”是您的合并的第一父提交和“主题”是第二个,这可以用

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

注意,它并没有什么意义使用三路差异这里实现我们正在查看包含任何冲突解决方案的状态。这也是GitHub针对合并提交显示的内容,顺便说一下,请参阅我用于测试的this merge commit

要看到的仅仅是冲突的文件及其决议3方区别工具,我想出了这个脚本

#!/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,但这两个想法都需要更多的工作来避免混乱你的工作树并正确地进行清理。

+0

+1对于漫反射,它甚至可以用不同的提交做4路diff – Johan

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) 

它有点冒险,但我发布它的机会有助于某人。