承诺Git在外部合并3
有什么方法可以查看已经在3-way diff中提交的合并?
如果3周前分支之间的巨大合并,是否有任何方法可以在BeyondCompare3这样的外部diff工具中看到它的三维差异 ? 我正在查找合并提交中更改的文件 。 如果我可以让它只显示冲突和手动更改的任何内容,而不是看到两个分支之间的文件的全部差异,那么奖金也是如此。
如果左边有<<<<< ===== >>>>>冲突标记,右边是承诺结果,我不介意解决双向差异问题。
我试着查看diff-tree,diff-files,diff,difftool,show和其他,但无法弄清楚。 我知道gitk会在合并提交中显示更改,但我不喜欢over-under diff视图,并且很难理解何时发生大量更改。
如果只有我可以做一些像git difftool --cc firstparent..secondparent..result
更新回答:我的原始版本的脚本是有缺陷的,因为$conflicting_files
实际上并不包含真正有冲突的文件,而是在两个父分支中都更改过的所有文件(但不一定有冲突)。 另外,它没有使用在原理中广告的“配置的合并工具”,而是使用diffuse
。 我已经在当前版本的脚本中解决了这两个问题。
原始答案:比方说,我们有一个“主”分支,主要开发进行中,还有一个“主题”分支,它在一些(较旧的)主状态顶部添加了一些功能。 通过说你正在寻找合并提交中改变的文件,我假设你只对在合并提交(包括任何冲突解决方案)中引入“主”的更改“主题”感兴趣,自“主题”分支以来,在“主”中完成的相互冲突的更改。 进一步假设“master”是合并提交的第一个父代,“topic”是第二个,这可以通过
git difftool <merge commit>^1 <merge commit>
请注意,在我们查看包含任何冲突解决方案的状态时,在此处使用3-way diff是没有意义的。 这也是GitHub针对合并提交显示的内容,顺便说一句,请参阅我用于测试的合并提交。
为了在三方差异工具中查看冲突文件及其分辨率,我想出了这个脚本
#!/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
,但这两个想法都需要更多的工作来避免混乱你的工作树并正确地进行清理。
我不知道如何在没有hackery的情况下在git中执行三向差异,但是对于双向差异我会使用meld
。 meld
是能够做一个三路差异的,如果你签了三个不同版本的项目,由目录做一个新的差异,并选择“三路比较”选项。
首先安装meld
sudo apt-get install meld
然后将混合物设置为difftool
git config --global diff.tool meld
找到提交
git log | more
打开提交
git difftool <old-version>..HEAD
像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)
它有点冒险,但我发布它的机会有助于某人。
链接地址: http://www.djcxy.com/p/3869.html