Git 合并添加新文件而不是冲突标记 - CONFLICT(重命名/添加)

adm*_*ajn 3 git git-merge-conflict

git merge origin master在命令行上运行时,我没有得到通常的冲突标记<<<<<<,而是将冲突的文件复制到我的本地环境中。

这可能与更改文件夹名称有关吗?

例子:

git fetch origin master && git merge origin master
CONFLICT (rename/add): Rename javascript/main.js->js/main.js in HEAD. js/main.js added in %commit-hash%
Adding as js/main.js~%commit-hash% instead
Run Code Online (Sandbox Code Playgroud)

然后我本地有 2x 个文件:js/main.js&js/main.js~%commit-hash%

如何让 git 为我提供冲突标记而不是新文件?

&任何人都可以解释为什么会发生这种情况吗?

  • 注意:%commit-hash%为了举例,只是实际提交哈希的占位符。

tor*_*rek 5

长话短说

尝试使用-X find-renames=<value>不同的重命名检测。或者,如果这不起作用或者您不喜欢该方法,请在必要时从存储在索引中的多个阶段中提取所有文件,然后用于git merge-file“手动”创建冲突。

长的

这是一种高级别的冲突:由于多个不同文件的名称发生变化而发生的冲突,而不是单个文件内发生的冲突。

Git 已经准确地告诉你问题是什么:

重命名javascript/main.js->js/main.jsHEAD...

因此,当将当前或HEAD提交与您和他们开始的公共合并基础进行比较时,Git 发现将该javascript/main.js文件重命名为js/main.js.

...js/main.js添加到hash

他们,无论他们是谁,将文件留javascript/main.js在 中javascript/main.js,但随后创建了一个名为js/main.js.

因为只能有一个名为 的文件js/main.js,所以 Git 必须做一些特殊的事情。它不能将您的 js/main.js(您从 中重命名的javascript/main.js)放入js/main.js 并将它们新创建的但不同的放入js/main.jsjs/main.js。所以它已经把他们js/main.js放进去了。js/main.js~hash

如何让 git 为我提供冲突标记而不是新文件?

也许你可以简单地做到这一点,也许不能。

首先,你要判断Git对情况的分析是否正确。 您重命名为?而且,他们做什么:他们保留原来的并添加一个新的不同的,还是他们实际上重命名了他们的,只是 Git 没有意识到这一点,并认为他们创建了一个与原来无关的全新的?javascript/main.jsjs/main.jsjavascript/main.jsjs/main.jsjavascript/main.jsjs/main.jsjavascript/main.js

如果问题是 Git 错误检测到了这两个重命名,您可以尝试调整设置-X find-renames=<value>(在旧版本的 Git 中命名-X rename-threshold=<value>)。降低该数字使 Git 更愿意将明显不同的文件视为“相同”文件。使数字更高会使 Git 不太愿意将此类文件视为“相同”,以至于如果将其设置为 100%,则文件的内容必须完全匹配。

如果情况确实如此,并且该过程进展顺利,您可能会得到您想要的东西,并且不需要任何其他棘手的部分。如果没有,那么:

手工做

如果 Git 是正确的,并且您的文件js/main.js命名,而它们js/main.js是新,则合并文件可能是不可取的。但是,您可以使用 来执行此操作git merge-file,它适用于工作树中的普通文件。首先,您需要将所有三个文件放入您的工作树中:

  • 合并基础版本,最初javascript/main.js在合并基础提交中命名(无论其哈希 ID 是什么)。
  • 或版本,在当前提交中命名--oursHEADjs/main.js
  • --theirs版本也被命名js/main.js,但在他们的提交中。

这三个版本中的两个已经在您的工作树中可用,使用 Git 宣布的两个名称。

索引中还应该有每个文件的副本:合并基础作为 stage-1 条目,或--ours版本HEAD作为 stage-2 条目,版本--theirs作为 stage-3 条目。这意味着您可以使用git showgit checkout-index来访问每个。(事实上​​,您可能可以git checkout-idnex --stage=all一次性将所有这些文件作为临时文件获取,但我还没有尝试过这一点。)由于您仍然需要的是基本版本,因此您可以使用:

git show :1:js/main.js > main.js.base
Run Code Online (Sandbox Code Playgroud)

例如(假设是 Unix 风格的 shell)。

一旦工作树中包含所有三个文件,您就可以运行:

git merge-file <head-version> <base-version> <their-version>
Run Code Online (Sandbox Code Playgroud)

生成<head-version>文件的冲突标记版本。假设您到目前为止显示的名称,并将 stage-1 文件写入js/main.js.base,则为:

git merge-file js/main.js js/main.js.base js/main.js.~<hash>
Run Code Online (Sandbox Code Playgroud)