git,用工具合并,而不是用工具解析

Posted

技术标签:

【中文标题】git,用工具合并,而不是用工具解析【英文标题】:git, merge with a tool, instead of resolve with a tool 【发布时间】:2020-03-20 12:36:50 【问题描述】:

我来自mercurial,有一个东西我不知道怎么用git。

在 mercurial 下,在合并期间,冲突文件的每个版本(基本、其他和本地)在我最喜欢的合并工具(kdiff3 或 meld)上并排显示。我合并它们,保存结果,每个人都很高兴。

使用 git,我 git merge,如果发生冲突,我 git mergetool ......我得到的文件充满了像这样混乱的混乱:

first line
<<<<<<< HEAD
local line
=======
other line
>>>>>>> other-branch
last line

如何配置 git 以在冲突发生之前打开我最喜欢的合并工具?我想手动合并而不是手动解决:)

【问题讨论】:

你在这里所说的恐怖似乎是我见过的最清晰和最好的冲突:'-) 我希望我的每个朋友都能像这样一团糟。不过,说真的,你可能只是从另一个(有点相似但不完全)范式进行调整。你有什么实际问题?因为这听起来更像是暂时的不适,而不是真正的问题。 如果我与 nano 或任何其他基于文本的合并合并,这将是一种很好的呈现方式......但我使用 kdiff3,对于每一次冲突,我都必须手动编辑而不是仅仅快速点击:这里选择本地,这里基地,这里其他......我们远远超过不适:D 有很多合并工具可以像您描述的那样通过单击来解决冲突(即使像我这样的一些怪人坚持基于文本的分辨率),我怀疑是一个简单的配置失误。你的操作系统是什么? 【参考方案1】:

(初步说明:我不使用任何这些工具。相反,我将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 调用的地方,分别是 indexstaging 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),$MERGEDgit mergetool 期望合并工具在合并工具发出成功信号之前更新的文件的名称或git mergetool 脚本失败。2


1请记住,Git 将文件的可用副本存储在工作树中,但实际上是从存储(间接)在索引中的特殊 Git 化格式文件构建提交。在冲突合并期间,Git 只是将所有三个输入文件保留在索引中,使用非零索引槽号。 Git 认为它自己解决的文件进入正常的零槽索引条目,清除非零槽,因此三个输入文件在这里不容易获得。 (在我看来,这是一个缺陷,但 Git 没有征求我的意见。从技术上讲,如果 Git 在处理文件时可以简单地合并它们,它甚至不会将文件的条目写入非零索引槽。这是可能是为了速度和/或懒惰。)

2您的工具应通过其操作系统级别的退出代码指示成功或失败。如果这样做了,并且您将此工具配置为将trustExitCode 设置为truegit mergetool 将知道是否自动将git add $MERGED 文件。如果将trustExitCode配置为falsegit mergetool会使用一些启发式方法来猜测是否相信工具成功合并文件。

【讨论】:

感谢您提供如此详细的回答!我认为这是不可能的,按设计...我将使用diff3 选项进行测试! (并为 bitbucket 上的 mercurial 丢失哀悼 † 阿门 :) 除了输入的命令外,您应该能够让您的系统提供相同的用户体验,即使 Git 的实际合并代码完全不同。 (我也在 Mercurial 中使用 vim 来解决问题,这只是我的首选方法。)

以上是关于git,用工具合并,而不是用工具解析的主要内容,如果未能解决你的问题,请参考以下文章

Kdiff3 不会用 mergetool 命令打开

JQuery源码解析-JQuery的工具方法

解决 Git 冲突的 14 个建议和工具

Git之深入解析48个经典操作场景的分析和处理,专治不会合并代码

手机上也可以用的快手和火山小视频提取工具

JSoup——用Java解析html网页内容