git没有冲突 但是提示有_git合并冲突说删除了,但事实并非如此

I can’t understand why git is suggesting the conflict as rename/delete conflict?

Git检测到了重命名.更确切地说,它检测到了一个,但没有检测到另一个.

我使用了您的示例脚本并获得了相同的结果:

CONFLICT (rename/delete): f/a deleted in hotfix and renamed in HEAD.

Version HEAD of f/a left in tree.

Automatic merge failed; fix conflicts and then commit the result.

这里有两个关键:git merge如何执行合并,以及git diff如何工作.让我们先从第一个开始.

如何合并(作为动词)

合并的目标是在两个不同的发展线上组合两组变化(通常由两个不同的人制作,但在我们的例子中,由一个人“戴两个不同的帽子”制作,一次一个,如它是).这些更改必须从一些常见的起点开始,Git称之为合并基础.

要执行此合并,Git必须找到合并基础.对于像这样的常规合并,合并基础是在HEAD(当前提交)和目标提交之间共享的提交.在我的特定情况下,名为hotfix的目标解析为提交哈希b45a155 ……:

$git rev-parse hotfix

b45a15547101d836d84dbdf4758d71dc91c93353

而HEAD是2ca7d2d ……:

$git rev-parse HEAD

2ca7d2d15d4d537edb828a7f3bfff3a2182630ec

这两个提交的合并基础是初始提交d763d32在主服务器上添加一个:

$git merge-base --all HEAD hotfix

d763d32af0cafdb0378b96b25e56fd70d63213d1

$git log --graph --decorate --oneline --all

* b45a155 (hotfix) move a to f on hotfix with different content

| * 2ca7d2d (HEAD -> master) move a to f on master

|/

* d763d32 add a on master

我们实际上并不需要所有这些哈希值,但有时候以具体形式看待它们会很高兴.关键是,我们有两组不同的变化:“我们做了什么”从d763d32到2ca7d2d,以及“他们做了什么”从d763d32到b45a155.

我们可以通过运行git diff找到第一个这样的东西:

$git diff d763d32 2ca7d2d # using raw IDs

$git diff hotfix...master # using the special "..." syntax

这就是“我们做了什么”.我马上就会展示一下.

接下来,我们(或Git)可以通过再次运行git diff找到第二个这样的东西:

$git diff d763d32 b45a155 # using raw IDs

$git diff master...hotfix # using the syntax again

git diff如何执行差异

这个解释在重要的时候会得到很长的细节和精细的细节,最终它确实非常重要.让我们把它外包给another StackOverflow answer.总之,Git会尝试检测重命名.是否可以检测到它们取决于许多细节.

但在我们的特定情况下,发生的事情是Git在从merge-base到tip-of-master时检测到重命名:

$git diff hotfix...master

diff --git a/a b/f/a

similarity index 100%

rename from a

rename to f/a

这里的三点语法告诉git diff找到两个指定提交的合并基础(修补程序的提示和master的提示),然后将第二个提交的diff合并基础,即master的提示.它检测到重命名:原始文件a与新文件f / a 100%相同.因此,我们有一个重命名.

第二个差异,虽然……啊,有一个问题:

$git diff master...hotfix

diff --git a/a b/a

deleted file mode 100644

index 81d07e3..0000000

--- a/a

+++ /dev/null

@@ -1 +0,0 @@

-a on master

diff --git a/f/a b/f/a

new file mode 100644

index 0000000..158795c

--- /dev/null

+++ b/f/a

@@ -0,0 +1 @@

+new content a on hotfix

合并基础中的旧内容与提示中的f / a的新内容有很大不同. Git不仅没有找到重命名,它永远不会找到重命名:文件太不同了.它丝毫不像原版.

重命名检测通常比这更好

实际上,当文件被重命名时,它们往往会保留很多甚至所有原始内容,就像你的merge-base-to-master-tip更改一样.但是,如果它们没有保留“足够”,Git将不会检测到重命名.

幸运的是,自从我在2012年1月写了this answer以来,Git已经存在了很长时间.它今天仍然适用 – 您可以使用-X rename-threshold = number来调整合并期间的重命名检测阈值级别 – 几乎每个人都有Git比1.7.4更新.但是,它的缺点仍然适用.您可能还想阅读我在2016年4月写的this other answer.

如果您有许多文件并需要自动重命名检测,您可能需要花哨.如果您只有一个文件,则可以手动合并文件,进行自己的“重命名检测”,使用git merge-file生成合并结果.只需将三个修订版(base,HEAD和其他版本)解压缩到临时文件中,然后使用git merge-file合并这三个版本以生成所需的结果.用正确的版本替换Git有点蹩脚的版本,git添加它,你很高兴.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值