【问题标题】:What exactly does "* -merge" in gitattributes effect?gitattributes 中的 \"* -merge\" 到底有什么作用?
【发布时间】:2022-11-29 20:18:18
【问题描述】:
我对自动合并有点不信任,所以我想阻止 Git 尝试任何事物当我发出git merge 或git pull 时就是那种;相反,我想打开我的 mergetool。
因此,我已将 * -merge 放入我的 .gitattributes 文件中。据我了解文档,那应该做我想做的。来自https://git-scm.com/docs/gitattributes(在“执行三向合并”部分中,关于merge 属性):
取消设置
将当前分支的版本作为暂定的合并结果,声明合并有冲突。这适用于没有明确定义的合并语义的二进制文件。
但是,.gitattributes 文件中的该节似乎没有任何效果。在获取远程分支之后,git merge 仍然立即打开提交消息的编辑器,这意味着 Git 已经在后台执行了必要的操作。
也许我误解了 * -merge 的实际效果。有人可以详细说明一下吗?
这个问题涉及两种情况:
-
远程分支已从本地分支分叉,但更改的文件集是正交的;也就是说,远程更改的文件具有不是已在本地更改,反之亦然。
-
远程分支与本地分支分叉,至少有一个文件被远程修改和本地。
[旁注:它没有按预期工作的原因可能是我的.gitattributes 文件由于某种原因没有得到评估。但这是不同问题的不同主题。我首先想知道我对* -merge 有什么期望。 ]
【问题讨论】:
标签:
git
merge
gitattributes
【解决方案1】:
第一:这里的文档是正确的,只是误导。你的原因:
* -merge
指示似乎没有效果是 git merge 没有按照人们的想法去做。
误导的部分
...在“执行三向合并”部分中,关于合并属性...
关键是这一节讨论的是 Git 如何执行三向合并,缺少但隐含的短语在文件级别包括在这里。为了达到这一点,Git 必须决定,前我们到了这里,三个输入文件之间的三路合并是必需的.
当你运行时:
git merge <name-or-hash-ID>
你告诉 Git 去定位一些特定的合并基地犯罪B就其本身而言,通过为其提供当前或--ours或$LOCAL提交HEAD,我称之为L,和一些其他提交(--theirs或$REMOTE)R. Git 使用提交图:
o--o--L <-- our-branch (HEAD)
/
...--o--o--B
o--o--R <-- their-branch
寻找B.
三个承诺B,L, 和R都包含快照。对于每个文件(在进行任何重命名检测之后,以便我们可以在需要时识别重命名;为了讨论简单,我们假设没有重命名),可能有一些路径P存在于一个、两个或所有三个提交中。为了进一步简单起见,我们可以假设P实际上确实存在于所有三个提交中。所以现在有文件的“三个版本”P.
现在正好有三种情况:
- 所有三个版本完全匹配(
<em>P<sub>B</sub></em>、<em>P<sub>L</sub></em> 和<em>P<sub>R</sub></em> 的所有 blob 哈希 ID 都匹配)。没有什么可以合并Git 将这三个版本中的任何一个(实际上是--ours 或<em>P<sub>L</sub></em> 文件)作为最终的合并结果。
- 三个版本都不一样:需要三路合并, 和
* -merge 将立即生效。
- 两个版本匹配,一个不匹配。不需要三向合并而 Git 不这样做。
这里的案例三是咬你的那个。 Git 只是比较三个散列 ID。哪一个是奇怪的人?如果它是合并基础版本,Git 使用L或者R版本(这些是相同的)。如果是L版本,这是 Git 使用的版本。如果是R版本,这是 Git 使用的版本。在所有这三种情况下,Git 现在都有合并结果,它将合并结果放入其索引(暂存以供提交)并留在您的工作树中。
Git 只使用合并驱动程序当需要三向合并时。要使用合并驱动程序,Git 会查阅 merge 设置,现在您正在谈论的 .gitattribute 文档部分开始发挥作用。所以只有上面的情况 2 受到影响。
理想情况下,Git 至少应该有一种方法来覆盖其案例 3 操作,回退到案例 2 并使用定义的合并驱动程序。如果 Git 有这样的东西并且你使用了它,它会在正确的文件集上触发。但是 Git 没有那个。