禁用Git重命名检测

13
  1. 我有一个名为foo.txt的文件。
  2. 创建并切换到分支 'branch_A'。
  3. git mv foo.txt bar.txt 然后执行 git add -A,接着 git commit -m "renamed foo.txt"
  4. 检出主分支 git checkout master
  5. 删除 foo.txt 并提交更改。
  6. 现在合并分支 branch_Agit merge branch_A

这样做会导致合并冲突 (重命名/删除)。

CONFLICT (rename/delete): Rename foo.txt->bar.txt in branch_A and deleted in HEAD

这听起来很合理,也是我期望的。但是,我想知道是否有一种方法可以让git merge不检测重命名,而是将它们视为添加/删除。在这种情况下,我期望git检测到foo.txt被删除,然后简单地添加bar.txt,避免产生冲突。

我尝试使用了-X rename-threshold,但它对我没有起作用。我已经尝试过阈值0和120(大于100的数字)。我错过了什么吗?

谢谢!

P.S. 我也遇到了"error: refusing to lose untracked file at..."错误。这是什么意思?


1
错误:拒绝丢失未跟踪的文件...可能是合并bar.txt的结果,该文件在branch_A中被跟踪但在master中未被跟踪,假设它存在于您的工作目录中。 - Chris Frederick
1
在git 2.8(2016年3月)中,您将有选择执行git merge --no-renames的选项。请参见下面的我的答案 - VonC
2
在 Git 2.18(2018 年第二季度)中,您可以选择 git config merge.renames false。请参见下面更新的答案 - VonC
2个回答

10

2021年9月更新:

下文提到的2016选项已经过时,被新的合并策略ORT(“Ostensibly Recursive's Twin”)所取代,它在处理重命名检测方面做得更好。

这里明显的主要区别是工作树和索引的更新不是与合并算法同时进行的,而是一个单独的后处理步骤。

新的API的设计使得可以进行重复的合并(例如在rebase或cherry-pick期间),并且只在最后一次更新索引和工作树,而不是在每个中间结果中都更新它们。

此外,可以在两个分支之间执行合并,而这两个分支都不匹配索引或工作树,而不会覆盖索引或工作树。

“ort”后端在内存中完成完整的合并,然后只将索引和工作副本作为后处理步骤进行更新。

从Git 2.34(2021年第四季度)开始,这将成为默认设置。
在此期间:

git merge -s ort MyBranch-to-merge
          ^^^^^^

2016年:

随着Git 2.8(2016年3月)的发布,你将有另一个选项(作为递归合并策略的选项)。

git merge -Srecursive -Xno-renames

请查看 提交44c74ec, 提交2307211, 提交63651e1 (2016年2月24日), 提交2307211, 提交63651e1 (2016年2月24日), 提交87892f6, 提交83837ec (2016年2月21日) 以及 提交1b47ad1, 提交d2b11ec (2016年2月17日),作者为 Felipe Gonçalves Assis (asiz)
(已由Junio C Hamano -- gitster --提交4ce064d中合并,于2016年2月26日)

merge-recursive:禁用重命名选项

递归策略默认启用重命名检测。
新增一个策略选项,即使对于完全相同的重命名也可以禁用重命名检测。

man git-merge将包括:

no-renames

Turn off rename detection.
See git diff --no-renames.

(注意,如 commit 1b47ad1 中所示,使用 git diff 接口的 find-renames 合并策略使得选项 rename-threshold 在 git 2.8 版本之后变得多余。)
在Git 2.18(2018年第二季度)中,您有一个额外的设置:如果将merge.renames配置设置为false,则可以告诉递归合并策略不要花费时间尝试查找重命名路径并相应地合并它们。

请查看提交 6f10a09, 提交 85b4603, 提交 a7152e9 (2018年5月2日) 由Ben Peart (benpeart)提交。
(由Junio C Hamano -- gitster --合并于提交 6e2ba77, 2018年5月30日)

merge: 添加merge.renames配置设置

通过配置设置添加控制合并时重命名检测的能力。
此设置与diff.renames相同且默认值相同,但仅适用于合并。


这个在2.9中被移除了吗?据我所知,git维护者的稳定版本ppa没有这个标志。 - ThorSummoner
1
@ThorSummoner 我同意。这实际上是一种合并策略的选项。我已经编辑了答案。 - VonC
@VonC:我可以提供两个微小的修改建议:在git-merge中添加连字符;在no-renames之前去掉双连字符。应该这样说:“git-merge命令将包括:no-renames”。 - chrisinmtown
@chrisinmtown 谢谢。我已经相应地编辑了答案。 - VonC

10

你可以尝试使用以下代码:

git merge -s resolve branch_A

这将启用 resolve 合并策略,该策略不尝试检测重命名:

resolve

此策略只能使用三方合并算法解决两个头指针(即当前分支和另一个你拉取的分支)。它会尝试仔细检测交叉合并的歧义。但它不处理重命名。

另外,你尝试过查看类似的问题吗:

git 重命名/删除 混淆

git 分叉重命名


5
这需要更多的解释。 - Liam
基本上我有一个 file.txt 文件,我对其进行修改并将其移动到 foo 子目录中,然后在历史记录中回溯并使用相同的 file.txt 作为修改的起点,将其移动到 bar 目录中。然后我尝试合并这两个分支,希望最终得到独立的 foobar 版本的文件,并且具有回溯到同一源头的历史记录。使用 @manojlds 指示的 -s resolve 很好地解决了这个问题,但正如 Liam 提到的那样,它确实需要更多的解释。但非常感谢 manojlds 的答案。 - Garret Wilson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接