git重命名/删除混淆

Sab*_*bya 7 git git-merge

我对一个特定的git行为有一个困惑:

以下是步骤和情况(稍后还会给出命令列表):

  1. 我有两个分支:master和XBranch
  2. 两者都有一个文件src/a.txt.它的内容是"旧内容"
  3. 在XBranch我重新命名的src/A.TXT为src/b.txt,使用:mv,git rm,git add.
  4. 在master中重命名文件a.txt.在提交期间,我做了git rm src/a.txt但忘了做git add src/b.txt 我在做的主人:git rm src/a.txtgit commit

  5. 在master中,我将文件b.txt的内容编辑为"New Content

  6. 掌握我做git add src/b.txtgit commit
  7. 在大师我做: git merge XBranch

文件src/b.txt冲突,这是完全可以理解的.但内容是" Old Content".为什么?

为什么不是这样的:

<<<<<<< HEAD
New Content
=======
Old content
>>>>>>> XBranch
Run Code Online (Sandbox Code Playgroud)

命令列表:

sabya@SABYA-PC d:/merge_temp/test/case2
$ mkdir source

sabya@SABYA-PC d:/merge_temp/test/case2
$ git init
Initialized empty Git repository in d:/merge_temp/test/case2/.git/

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ mkdir src

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ vi src/a.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ cat src/a.txt
Old Content

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git add src/

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git commit
[master (root-commit) 148500e] added src/a.txt
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 src/a.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git branch XBranch

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git checkout XBranch
Switched to branch 'XBranch'

sabya@SABYA-PC d:/merge_temp/test/case2 (XBranch)
$ mv src/a.txt src/b.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (XBranch)
$ git rm src/a.txt
rm 'src/a.txt'

sabya@SABYA-PC d:/merge_temp/test/case2 (XBranch)
$ git add src/b.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (XBranch)
$ git commit
[XBranch b3ff8fa] changed a.txt to b.txt in XBranch
 1 files changed, 0 insertions(+), 0 deletions(-)
 rename src/{a.txt => b.txt} (100%)

sabya@SABYA-PC d:/merge_temp/test/case2 (XBranch)
$ git checkout master
Switched to branch 'master'

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ mv src/a.txt src/b.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git rm src/a.txt
rm 'src/a.txt'

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git commit
[master bfeaecb] removed src/a.txt
 1 files changed, 0 insertions(+), 1 deletions(-)
 delete mode 100644 src/a.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ vi src/b.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ cat src/b.txt
New Content

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git add src/b.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git commit
[master 2361d5e] changed content of b.txt
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 src/b.txt

sabya@SABYA-PC d:/merge_temp/test/case2 (master)
$ git merge XBranch
CONFLICT (rename/delete): Rename src/a.txt->src/b.txt in XBranch and deleted in HEAD
Automatic merge failed; fix conflicts and then commit the result.

sabya@SABYA-PC d:/merge_temp/test/case2 (master|MERGING)
$ cat src/b.txt
Old Content
Run Code Online (Sandbox Code Playgroud)

Von*_*onC 6

存在冲突,但与文件内容无关.它是关于 树的内容.

  • 在一棵树中,case2目录(在master中)有一个文件b.txt
  • 在同一目录中(在XBranch中),有一个重命名的文件a.txt => b.txt

解决冲突时,实际上是选择一个文件或另一个文件(文件中不是一行).因此,结果文件中的"旧内容".


OP在评论中添加:

但那么它在逻辑上与以下情况有何不同:

  1. 我想补充文件a.txtmaster与"老内容"并提交.
  2. 我想补充文件a.txtXBranch与"新内容"并提交.
  3. 我融入XBranchmaster.这次它显示该文件中的两个内容!

这一次,两个目录树(在树枝的情况2目录masterXBranch)引用新的文件a.txt:其内容得到合并,以解决冲突.之前,a a.txt (重命名b.txt)和 b.txt之间存在冲突:两个文件不能存在于同一分支中,必须选择(文件,而不是文件内容).

在我的问题的第4步中,如果我在一次提交中执行" git rm"和" git add",它就像我期望的那样工作!我现在不明白.如何预测文件何时包含两个内容?什么时候才会有内容,XBranch何时只有内容master

这意味着:

  • 而不是合并XBranch(a.txt重命名为b.txt)以master使用b.txt步骤6中的新提交(树的冲突),
  • 您将从新步骤4(也重命名为)合并XBranch(a.txt重命名为b.txt)master :相同的树内容,但不同的blob内容:行冲突.a.txt b.txt

话虽如此,OP仍然认为必定存在错误:


注意:Git 2.18(2018年第二季度)使用合并递归更改冲突检测报告.
Elijah Newren()提交6e7e027(2018年4月19日). newren

merge-recursive:避免虚假重命名/重命名dir重命名冲突

如果历史记录一侧的文件已重命名,并且仅在另一侧修改,则将目录重命名应用于修改的一方会给我们带来rename/rename(1to2)冲突.
我们只应将目录重命名应用于表示添加或重命名的对.

进行此更改意味着以前报告为rename/delete冲突modify/delete的目录重命名测试用例 现在将报告为 冲突.