7

我对特定的 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

命令列表:

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
4

1 回答 1

6

存在冲突,但与文件内容无关。这是关于 的内容。

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

当您解决冲突时,您实际上是在选择一个文件或另一个(不是文件中的一行)。因此,结果文件中的“旧内容”。


OP在评论中添加:

但是从逻辑上讲,它与以下情况有何不同:

  1. 我添加了一个带有“旧内容”的文件a.txtmaster提交它。
  2. a.txt我用“新内容”添加一个文件XBranch并提交它。
  3. 我合并XBranchmaster. 这次它显示了该文件中的两个内容!

这一次,两棵树(分支master和中的 case2 目录XBranch)都引用了一个文件a.txt:它的内容被合并,并解决了冲突。以前, a a.txt (重命名b.txt) 和 b.txt之间存在冲突:两个文件不能存在于同一个分支中,必须做出选择(文件,而不是文件内容)。

在我的问题的第 4 步中,如果我在一次提交中执行“ git rm”和“ ”,它会按我的预期工作!git add我现在无法理解。我如何预测文件何时会同时包含这两个内容?什么时候只有 的内容,什么XBranch时候只有 的内容master

这意味着:

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

话虽如此,OP仍然认为一定有一个错误:


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

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

如果历史记录一侧的文件被重命名,而另一侧仅被修改,那么将目录重命名应用于修改的一侧会给我们带来rename/rename(1to2)冲突。
我们应该只将目录重命名应用于表示添加或重命名的对。

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


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

这已在 Git 2.27(2020 年第二季度)中得到纠正,因此来自每一侧的路径都得到了它们的原始内容。

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

merge-recursive:修复重命名/重命名(1to2)的工作树与二进制

报告人
:张春林 签字人:Elijah Newren

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

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

于 2010-06-23T10:41:43.833 回答