问题在于“git checkout”将从任一分支获取整个文件。文件的某些部分可能已经成功地合并,我们不想删除这些部分。
对于处于冲突状态的文件,有没有一种方法可以优先选择“我们”的或“他们”的方式来移除冲突标记,而不需要将此策略应用于整个合并或从“我们”的或“他们”的获取整个文件?
这绝对可以通过一个简单的脚本来实现,但我想知道是否存在我没有找到的现有解决方案。
如果您想解决文件中所有未解决的冲突并采用我们或他们的代码,可以使用简单的sed
命令,具体取决于您想要采用哪一方和您的冲突风格。
对于大多数代码文件而言,冲突标记通常非常明显,因此您不必担心识别它们,在这种情况下,您只需轻松输入命令即可:
sed -si '/^<<</,/^>>>/ {/^<<</,/^===/d;/^>>>/d}' thefile # keep theirs
sed -si '/^<<</,/^>>>/ {/^<<</d;/^===/,/^>>>/d}' thefile # keep ours
为了做到这一点,
sed -si $yourpattern $(git ls-files -m | uniq)
为了更加小心处理冲突标记,最好制作你提到的简单脚本,并且diff3冲突报告样式也需要进行一些更改。通常,冲突符号计数为7,为了最大安全性,请将sed范围设置为/^<<<<<<< ours$/,/^>>>>>>> theirs$/
,并且使用diff3报告时,“保留ours”删除范围以^||||||| base$
开头,而不是^=======$
。
在Mac上使用sed
会被破坏,拒绝进行内联编辑而不创建备份文件。你需要使用例如-si.bak
,然后再删除备份。
grep -lr '<<<<<<<' . | xargs sed -si $yourpattern
?因为$(git ls-files -m | uniq)
并没有涵盖所有有冲突的文件。 - alpergit ls-files -m
确实包含了所有有冲突的文件,它没有找到的标记可能被添加为测试、玩笑或者错误的正确解决方案,而不一定是为了这个合并。 - jthill正如马库斯在评论中提到的那样,git mergetool
可以针对单个文件进行调用。通过正确的merge.tool
或-t
参数和mergetool.<tool>.cmd
设置,您可以使其调用一个小脚本,该脚本:
--ours
版本放入工作树副本中,然后--theirs
版本作为参数来运行git merge-file --ours
或git merge-file --theirs
。这个“编辑器”的退出代码是可信的(请参见merge.<tool>.trustExitCode
),这允许git mergetool
为您运行git add
。因此,您可能可以缩短脚本。
我从不这样做,实际上我从不使用git mergetool
。如果我真的在使用git mergetool
,我会想要亲自检查结果,就像Marcus在他的答案中建议的那样。
虽然应该有一行命令可以做到这一点,但目前还没有,您可以自己编写脚本。
可以完成此任务的命令是git merge-file
。但在运行git merge-file
之前,需要 git merge
所看到的三个输入文件。
这三个文件确实存在;问题在于如何提取它们。 git mergetool
命令解决了这个问题,但不幸的是,它的解决方式对您来说并不特别有用。 您想为一个文件解决此问题,但git mergetool
会将其重复应用于所有未合并的文件(然后在这些文件上运行您选择的合并工具,通常是某种三向编辑器,逐个进行处理)。
git mergetool
的作用是使用带有 --stage
选项的 git checkout-index
。某个文件 file.ext
的三个版本都在索引中,作为第一阶段(合并基础版本)、第二阶段(--ours
版本)和第三阶段(--theirs
版本)。使用 git mergetool
时,脚本将它们分别提取到 file.ext.BASE
、file.ext.LOCAL
和 file.ext.REMOTE
中。你必须做更多或更少相同的事情,尽管你可能想选择不同的名称。有关代码,请参见 git mergetool 脚本(如果您喜欢,还有其主要 助手脚本,但这里只需要主要的脚本——我已经直接链接到提取文件的行,而实现该功能的函数在主文件的其他位置)。git merge-file
即可。请参阅git merge-file
文档以查看这些参数是什么。检查结果,如果需要,可以将其放入原有的冲突标记工作树文件的位置,并使用git add
消除三个高级别文件并将合并后的文件写入第零阶段,准备提交。
您可以按照自己的方式解决剩余未解决的文件。
1嗯,也就是说,这解决了大多数情况。对于重命名/重命名冲突,git mergetool
会感到困惑:这里索引中的信息有点不足。
git mergetool
为您运行git merge-file
! - torekgit mergetool
(它会遍历冲突文件并运行已安装的合并编辑器),并手动审查更改。git merge -Xours ...
不要将其与选择整个合并策略的 -s ours
混淆,该策略只是从我们自己选择所有东西,而不尝试进行合并。
如果你想在每次合并时将这种策略应用于某些特定文件,可以定义一个自定义合并驱动程序(在 .gitconfig 中)并将其应用于那些文件(在 .gitattributes 中)。这听起来比实际更加复杂。定义合并驱动程序仅意味着定义一个命令行,它需要三个输入文件并创建一个输出文件,例如,您可以像 Torek 所解释的那样使用 git merge-file。一旦定义,您可以通过在存储库根目录中创建 .gitattributes 文件并提交它来将此类合并驱动程序分配给任何文件或模式。了解有关此的详细信息,请参阅gitattributes。
git merge-index
和git-merge-one-file
吗? - jthill