git重命名/删除混淆

7
我有一个git行为方面的困惑:
以下是步骤和情况(命令列表也在后面给出):
1.我有两个分支:master和XBranch 2.这两个分支中都有一个src / a.txt文件。 它的内容是“旧内容” 3.在XBranch中,我使用“移动”,“git rm”和“git add”将src / a.txt重命名为src / b.txt。 4.在master中重命名a.txt。 在提交期间,我执行了“git rm src / a.txt”,但忘记执行“git add src / b.txt” 在主分支上,我进行以下操作: git rm src/a.txt 和 git commit 5.在master中,我编辑了文件b.txt的内容为“New Content” 6.在主分支中,我执行git add src / b.txt和git commit 7.在主分支中,我执行: git merge XBranch
src / b.txt文件冲突,这是可以理解的。 但是它的内容是“旧内容”。 为什么呢?
为什么不是像这样的东西:
<<<<<<< HEAD
New Content
=======
Old content
>>>>>>> XBranch

命令列表:

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
1个回答

6
有一个冲突,但不是关于文件内容的。它是关于树内容的。
在一个树中,case2目录(在主分支中)有一个新文件b.txt;在同一个目录(在XBranch中)中,有一个重命名的文件a.txt => b.txt
当你解决冲突时,实际上是选择其中一个文件而不是文件中的一行。因此,会出现结果文件中的“旧内容”。
OP在评论中补充说:
但这与下面的情况有何逻辑上的不同:
1. 我在主分支中添加文件a.txt并提交它。 2. 我在XBranch中添加文件a.txt并提交它,并修改了其内容。 3. 我将XBranch合并到master中。这次它显示文件中的所有内容!
这一次,两个树(分支master和XBranch中的case2目录)都引用了一个新文件a.txt:它的内容被合并,进行了冲突解决。之前,在a.txt(重命名为b.txt)和一个新的b.txt之间存在冲突:两个文件不能同时存在于同一个分支中,必须选择(文件而非文件内容)。
在我的问题的第4步中,如果我使用“git rm”和“git add”在单个提交中完成,它会按照我所期望的方式工作!我不明白现在是怎么回事。我怎样才能预测文件什么时候会有两个内容?什么时候它只会有XBranch的内容,什么时候它只会有master的内容?
这意味着:
1. 不要将XBranch(a.txt重命名为b.txt)与来自步骤6(树冲突)的新b.txt合并到master提交中。 2. 要将XBranch(a.txt重命名为b.txt)与来自新步骤4(a.txt也重命名为b.txt)的master合并:相同的树内容,但不同的blob内容:行冲突。

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


注意:Git 2.18(2018年第二季度)通过递归合并更改了冲突检测报告。
请参见提交6e7e027(由Elijah Newren(newren于2018年4月19日进行)。

merge-recursive:避免来自目录重命名的虚假重命名/重命名冲突

如果在历史的一侧将文件重命名,并且仅在另一侧进行了修改,则将目录重命名应用于修改的侧面会给我们 一个rename/rename(1to2)冲突。
我们应该只将目录重命名应用于表示添加或重命名的对。

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


当二进制文件在历史的两侧被修改并重命名到不同的位置时,两个文件都将写入工作树,但是两个文件都具有"ours"的内容。

Git 2.27(2020年第二季度)已经纠正了这一点,因此每个侧面的路径都会获得其原始内容。

请参见提交95983da(由Elijah Newren(newren于2020年5月13日进行)。
(由Junio C Hamano -- gitster --提交abbd1d9中合并,2020年5月20日)

merge-recursive:修复了在带有二进制文件的工作树中重命名/重命名(1to2)的问题

报告人:张春林
签署者:Elijah Newren

对于重命名/重命名(1to2)冲突,我们尝试进行文件内容的三方合并,以便将正确的内容放置在两个路径的工作树中。

然而,如果该文件是二进制文件,则无法进行内容合并,我们应该只使用每个路径上的原始版本。


但是,从逻辑上讲,它与以下情况有什么不同呢:
  1. 我在主分支中添加了一个名为a.txt的文件,并提交了“旧内容”。
  2. 我在XBranch中添加了一个名为a.txt的文件,并提交了“新内容”。
  3. 将XBranch合并到主分支中。
这次它会显示该文件中的两个内容!
- Sabya
@Sabya:这次,两个树(主分支和X分支中的case2目录)都引用了一个新的文件a.txt:它们的内容被合并,冲突得到解决。在此之前,a.txt(重命名为b.txt)和一个新的b.txt之间存在冲突:这两个文件不能同时存在于同一个分支中,必须做出选择(选择文件而不是文件内容)。 - VonC
在我的问题的第4步中,如果我在一个提交中执行“git rm”和“git add”,它会按照我的预期工作! 我现在无法理解这一点。我如何预测文件何时会具有两个内容?它什么时候只有XBranch的内容,什么时候只有master的内容? - Sabya
这意味着,与其将XBranch(其中a.txt被重命名为b.txt)与步骤6中的 b.txt (树冲突)合并到主分支提交中,你应该将XBranch(其中a.txt被重命名为b.txt)与新的步骤4中的主分支合并(a.txt也被重命名为b.txt):相同的树内容,但不同的blob内容:行冲突。 - VonC
在这个答案中,也最好包括如何解决冲突的方法。我该如何查看新内容?我甚至不确定我正在查看哪个版本。我认为我不想添加文件,因为我想要新的内容。但是我无法检出文件(以擦除更改),因为我会收到“路径未合并”的错误。我绝对不想删除它。如果我使用 git reset -- <path>,那么就没有更改可以提交,我被迫使用 git rebase --skip。但是这只是突然结束了变基!(我还有更多的提交要应用!它们被丢弃了!) - Neil Traft
显示剩余3条评论

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