git git重命名/删除混淆
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3100032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
git rename/delete confusion
提问by Sabya
I having one confusion about a particular git behavior:
我对特定的 git 行为感到困惑:
Following are the steps and situation (the list of commands are also given later):
以下是步骤和情况(命令列表也在后面给出):
- I have two branches: master and XBranch
- There is a file src/a.txt in both of them. It's content is "Old Content"
- In XBranch I rename src/a.txt to src/b.txt, using:
mv
,git rm
,git add
. In master rename the file a.txt. During commit I did
git rm src/a.txt
but forgot to dogit add src/b.txt
In master I do:git rm src/a.txt
andgit commit
In master, I edit the content of the file b.txt to "
New Content
- In master I do
git add src/b.txt
andgit commit
- In master I do:
git merge XBranch
- 我有两个分支:master 和 XBranch
- 它们中都有一个文件 src/a.txt。它的内容是“旧内容”
- 在 XBranch 中,我将 src/a.txt 重命名为 src/b.txt,使用:
mv
,git rm
,git add
。 在 master 中重命名文件 a.txt。在提交期间我做了
git rm src/a.txt
但忘了做git add src/b.txt
在 master 我做:git rm src/a.txt
和git commit
在 master 中,我将文件 b.txt 的内容编辑为“
New Content
- 在主人我做
git add src/b.txt
和git commit
- 在主人我做:
git merge XBranch
The file src/b.txt conflicts, which is perfectly understandable.
But the content is "Old Content
". Why?
文件 src/b.txt 冲突,这完全可以理解。但内容是“ Old Content
”。为什么?
Why notis it something like:
为什么不是这样的:
<<<<<<< HEAD
New Content
=======
Old content
>>>>>>> XBranch
List of Commands:
命令列表:
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
采纳答案by VonC
There is a conflict, but not about the filecontent. It is about the treecontent.
存在冲突,但与文件内容无关。这是关于 树的内容。
- In one tree, the
case2
directory (in master), there is a newfileb.txt
- in the same directory (in XBranch), there is a renamedfile
a.txt => b.txt
- 在一棵树中,
case2
目录(在 master 中),有一个新文件b.txt
- 在同一个目录中(在 XBranch 中),有一个重命名的文件
a.txt => b.txt
When you are resolving the conflict, you are in effect choosing one file or the other (not one line within the file). Hence the "Old Content" in the resulting file.
当您解决冲突时,您实际上是在选择一个文件或另一个文件(而不是文件中的一行)。因此,结果文件中的“旧内容”。
The OP adds in the comments:
OP 在评论中添加:
But then how logically is it different from the following situation:
- I add a file
a.txt
inmaster
with "Old Content" and commit it.- I add a file
a.txt
inXBranch
with "New Content" and commit it.- I merge
XBranch
intomaster
. This time it is showing both contents in that file!
但是,它与以下情况在逻辑上有何不同:
- 我想补充文件
a.txt
中master
与“老内容”并提交。- 我想补充文件
a.txt
中XBranch
与“新内容”并提交。- 我合并
XBranch
到master
. 这次它显示了该文件中的两个内容!
This time, both trees (the case2 directory in branches master
and XBranch
)
reference a newfile a.txt
: its content get merged, with conflict
resolution. Before, there was a conflict between a a.txt
(renamedas b.txt
) and a newb.txt: both files cannot exist in the
same branch, a choice (of file, not of file content) had to be made.
这一次,两个树(分支中的 case2 目录master
和XBranch
)都引用了一个新文件a.txt
:它的内容被合并,并解决了冲突。之前, a a.txt
(重命名为b.txt
)和新的b.txt之间存在冲突:两个文件不能存在于同一分支中,必须做出选择(文件,而不是文件内容)。
In step 4 of my question, if I do "
git rm
" and "git add
" in a single commit, it works as I expect! I fail to understand that now. How can I predict when the file will have both contents? When it will just have the content ofXBranch
and when will it have just the content ofmaster
?
在我的问题的第 4 步中,如果我在一次提交中执行“
git rm
”和“git add
”,它会按我的预期工作!我现在不明白。我如何预测文件何时将同时包含这两个内容?什么XBranch
时候只有 的内容,master
什么时候只有 的内容?
That means that:
这意味着:
- instead of merging
XBranch
(a.txt
renamed asb.txt
) tomaster
commit with a newb.txt
from step 6 (conflict of tree), - you would merge
XBranch
(a.txt
renamed asb.txt
) with master from new step 4 (a.txt
also renamedasb.txt
): same tree content, but different blob content: conflict of lines.
- 而不是合并
XBranch
(a.txt
重命名为b.txt
)以master
提交b.txt
第 6 步中的新内容(树冲突), - 您将与新步骤 4 中的 master合并
XBranch
(a.txt
重命名为b.txt
)(a.txt
也重命名为b.txt
):相同的树内容,但不同的 blob 内容:行冲突。
That being said, the OP still thinks there must be a bug:
话虽如此,OP 仍然认为一定存在错误:
Note: Git 2.18 (Q2 2018) changes that conflict detection report with a merge recursive.
See commit 6e7e027(19 Apr 2018) by Elijah Newren (newren
).
注意:Git 2.18(2018 年第二季度)使用合并递归更改了冲突检测报告。
请参阅Elijah Newren ( ) 的commit 6e7e027(2018 年 4 月 19 日)。 newren
merge-recursive
: avoid spurious rename/rename conflict from dir renamesIf a file on one side of history was renamed, and merely modified on the other side, then applying a directory rename to the modified side gives us a
rename/rename(1to2)
conflict.
We should only apply directory renames to pairs representing either adds or renames.Making this change means that a directory rename testcase that was previously reported as a
rename/delete
conflict will now be reported as amodify/delete
conflict.
merge-recursive
: 避免目录重命名的虚假重命名/重命名冲突如果历史记录一侧的文件被重命名,而只是在另一侧进行了修改,那么将目录重命名应用于修改后的一侧会给我们带来
rename/rename(1to2)
冲突。
我们应该只将目录重命名应用于表示添加或重命名的对。进行此更改意味着以前报告为
rename/delete
冲突modify/delete
的目录重命名测试用例 现在将报告为 冲突。
When a binary file gets modified and renamed on both sides of history to different locations, both files would be written to the working tree but both would have the contents from "ours
".
当一个二进制文件在历史记录的两边被修改和重命名到不同的位置时,两个文件都将被写入工作树,但都将包含来自“ ours
”的内容。
This has been corrected with Git 2.27 (Q2 2020), so that the path from each side gets their original content.
这已在 Git 2.27(2020 年第二季度)中得到纠正,以便每一方的路径都获得其原始内容。
See commit 95983da(13 May 2020) by Elijah Newren (newren
).
(Merged by Junio C Hamano -- gitster
--in commit abbd1d9, 20 May 2020)
请参阅Elijah Newren ( ) 的提交 95983da(2020 年 5 月 13 日)。(由Junio C Hamano合并-- --在abbd1d9 提交中,2020 年 5 月 20 日)newren
gitster
merge-recursive
: fix rename/rename(1to2) for working tree with a binaryReported-by: Chunlin Zhang
Signed-off-by: Elijah NewrenWith a rename/rename(1to2) conflict, we attempt to do a three-way merge of the file contents, so that the correct contents can be placed in the working tree at both paths.
If the file is a binary, however, no content merging is possible and we should just use the original version of the file at each of the paths.
merge-recursive
:使用二进制修复工作树的重命名/重命名(1to2)报告人
:张春林 签字人:Elijah Newren由于重命名/重命名(1to2)冲突,我们尝试对文件内容进行三向合并,以便将正确的内容放置在两个路径的工作树中。
但是,如果文件是二进制文件,则无法合并内容,我们应该只在每个路径上使用文件的原始版本。