Git Auto Merge Issue:
When there is Same code committed in two different branches file with one of this branch code having extra CRLF/LF at start. While merging it auto merges the file creates duplicates without any conflict. Please advise earliest.
Below image shows all the possible symbols in text file. Note: Branch A does not have Line Feed(Line: 245). And Automated Merging below creates duplicates without showing conflict.
(Note: line endings are not the culprit here.)
This case is interesting. The problem seems to be that the two sets of added lines are, in git's algorithm anyway, added at two different places. Git has no understanding of the code and simply decides that since the two (somewhat different) changes add lines to different sections of the original, it is OK to just add both of those differing changes.
One of the lessons you should take away from this is that git is not smart. It is simply following a bunch of simple rules that usually work, but just because it thinks it merged two sets of diffs successfully, does not mean that the result is correct. This is yet another reason why automated testing is a good idea, for instance.
Note: complete steps, via a script, to re-create the problem appear at the bottom of this answer.
Let's take a look at the state of BranchA and BranchB just before we ask git to merge. The crucial part is what we get with
git diff
when we compare the merge base (the tip of branchcommon
, in this particular setup) with the two actual tip commits. To see these diffs, I use the three-dot form ofgit diff
:The first command,
git diff BranchB...BranchA
, tells git:Find the commits identified by
BranchB
andBranchA
. (These are the two tip-most commits onBranchB
andBranchA
respectively. In this case, they are also the only commits on those two branches that are not already on the common branch, since we made only the one commit exclusively onBranchA
and one commit exclusively onBranchB
. In many real-word situations, there might be 10, 20, or more commits on one branch and 2, 5, or even 50 or more commits on the other, but git just finds the two tip-most commits, for this step.)Find the merge base for these two commits. The merge base is a place where the two branches rejoin in history. In this case, the merge base is quite obvious: it's the commit at the tip of branch
common
, which is where the two branchesBranchA
andBranchB
emerge as separate branches. The commit at the tip ofcommon
is on all three branches (and any other branches, such as the defaultmaster
branch).Diff the merge-base against the second commit, i.e., the tip of
BranchA
.The second command,
git diff BranchA...BranchB
, works very similarly. The only change is that the two input commits are selected in the other order. Git finds the same merge base, but now diffs that commit against the tip commit ofBranchB
.Take another look at the diffs quoted above. There are two different diff results.
The first diff shows that git should modify a block beginning with context at line 11. There are three "above" lines of context (lines 11, 12, and 13, these being the get, set, and close brace lines), then we added the comment and function declaration lines, and then there are three lines of "below" context.
The second diff shows that git should add three lines of text in a block beginning at line 12 (not line 11). The three "above" lines of context are the set, close-brace, and blank lines, and those lines are not themselves going to be changed by the first diff (though they will have some text inserted between them). Then we added three lines (comment, function declaration, and blank line) and then we have the trailing context.
Note that git has decided that our newly added initial blank line was already present and that we, instead, added a subsequent blank line, with our additions happening at line 14, not line 13. This explains why the two additions do not conflict: as far as git is concerned, the
BranchA
change is "add two lines at line 11+3" and theBranchB
change is "add three lines at old-line-12+3 (which is now line 14+3 after adding two lines)".The result is that git adds both blocks of text, even though they are very similar.
Script to reproduce problem is below.