I having one confusion about a particular git behavior:
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.txtbut forgot to dogit add src/b.txt
In master I do:git rm src/a.txtandgit commit -
In master, I edit the content of the file b.txt to “
New Content - In master I do
git add src/b.txtandgit commit - In master I do:
git merge XBranch
The file src/b.txt conflicts, which is perfectly understandable.
But the content is “Old Content“. Why?
Why not is 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
There is a conflict, but not about the file content. It is about the
tree content.
case2directory (in master), there is a new fileb.txta.txt => b.txtWhen 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:
This time, both trees (the case2 directory in branches
masterandXBranch)reference a new file
a.txt: its content get merged, with conflictresolution. Before, there was a conflict between a
a.txt(renamed as
b.txt) and a new b.txt: both files cannot exist in thesame branch, a choice (of file, not of file content) had to be made.
That means that:
XBranch(a.txtrenamed asb.txt) tomastercommitwith a new
b.txtfrom step 6 (conflict of tree),XBranch(a.txtrenamed asb.txt) with master from newstep 4 (
a.txtalso renamed asb.txt): same tree content, but differentblob content: conflict of lines.
That being said, the OP still thinks there must be a bug:
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).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“.This has been corrected with Git 2.27 (Q2 2020), so that the path from each side gets their original content.
See commit 95983da (13 May 2020) by Elijah Newren (
newren).(Merged by Junio C Hamano —
gitster— in commit abbd1d9, 20 May 2020)