(初步说明:我不使用任何这些工具。相反,我将merge.conflictStyle 设置为diff3,它在工作树文件中使用了稍微不同的标记格式。大多数时候我可以轻松直接在vim解决这个问题,如果太乱,我有时候会用git show直接提取三个输入,比如git show :1:<em>path</em>。不过每个人不一样,看Git: How configure KDiff3 as merge tool and diff tool。)
如何配置 git 以在在冲突发生之前打开我最喜欢的合并工具?
你不能。好吧,如果您编写自己的合并 strategy(相当于 git merge-recursive),则可以,但多年来没有人做过这种事情,因为它太难了。幸运的是,您不需要:
我想手动合并而不是手动解析:)
如果发生冲突,Git 会写入自己的尝试合并到工作树文件中。1这就是您在编辑器中看到的内容。但是 Git 将三个输入文件留在了 Git 调用的地方,分别是 index、staging area 和(现在很少)cache。这是同一事物的三个名称:staging area 指的是您使用它的方式,而 cache 指的是它的各种内部方面,而 index 是一种无意义的术语。在这种情况下,“索引”这个词可能是最好使用的,我将在这里使用它。
当您运行 git mergetool 时,Git 应该在所有三个输入文件上启动您选择的合并工具,以及第四个(带有冲突标记的 Git 尝试合并)工作树文件.然后,此工具可以向您显示部分或全部这些不同的输入。然后,您可以使用该工具,以工具本身的任何工作方式手动进行解析,完全忽略 Git 的合并尝试,如果您愿意的话。
请注意,git mergetool 为您的合并工具提供的三个输入文件——合并基础、左侧或本地 --ours、右侧或远程或 --theirs——只是临时文件。它们不会用作合并结果。 将用作合并结果的文件,当您的合并工具向 Git 指示它已完成合并时,它是主要的工作树文件:其中包含混乱的文件。所以你的工具必须用你的合并结果覆盖这个文件。
与 Mercurial 不同,核心 Git 没有内置的合并工具(嗯,除了它自己的默认值——它始终运行,作为您使用 -s 选择的合并策略的一部分)。因此,您或为您设置 Git 发行版的人必须告诉 Git如何 运行任何特定的外部合并工具。每个 Git 安装 通常都会有一些预配置的外部合并工具,这些工具可能包含也可能不包含您想要的工具。如果您需要配置自己的外部合并工具,请参阅Git on Windows: How do you set up a mergetool?(尽管有标题,但它的一些答案在非 Windows 系统上很好。请参阅CB Bailey's answer in particular。)
合并工具必须处理的四个名称作为环境变量提供:$BASE 命名合并基础文件(来自索引中的暂存槽#1),$LOCAL 命名--ours 文件(暂存槽#2 在索引中),$REMOTE 命名 --theirs 文件(暂存槽 #3),$MERGED 是 git mergetool 期望合并工具在合并工具发出成功信号之前更新的文件的名称或git mergetool 脚本失败。2
1请记住,Git 将文件的可用副本存储在工作树中,但实际上是从存储(间接)在索引中的特殊 Git 化格式文件构建提交。在冲突合并期间,Git 只是将所有三个输入文件保留在索引中,使用非零索引槽号。 Git 认为它自己解决的文件进入正常的零槽索引条目,清除非零槽,因此三个输入文件在这里不容易获得。 (在我看来,这是一个缺陷,但 Git 没有征求我的意见。从技术上讲,如果 Git 在处理文件时可以简单地合并它们,它甚至不会将文件的条目写入非零索引槽。这是可能是为了速度和/或懒惰。)
2您的工具应通过其操作系统级别的退出代码指示成功或失败。如果这样做了,并且您将此工具配置为将trustExitCode 设置为true,git mergetool 将知道是否自动将git add $MERGED 文件。如果将trustExitCode配置为false,git mergetool会使用一些启发式方法来猜测是否相信工具成功合并文件。