Commits

Junio C Hamano  committed 28e77a8

merge-recursive: leave unmerged entries in the index.

This does two things.

- When one branch renamed and the other branch did not, the
resulting half-merged file in the working tree used to swap
branches around and showed as if renaming side was "ours".
This was confusing and inconsistent (even though the conflict
markers were marked with branch names, it was not a good
enough excuse). This changes the order of arguments to
mergeFile in such a case to make sure we always see "our"
change between <<< and ===, and "their" change between ===
and >>>.

- When both branches renamed to the same path, and when one
branch renamed and the other branch did not, we attempt
mergeFile. When this automerge conflicted, we used to
collapse the index. Now we use update-index --index-info
to inject higher stage entries to leave the index in unmerged
state for these two cases.

What this still does _not_ do is to inject unmerged state into
the index when the structural changes conflict. I have not
thought things through what to do in each case yet, but the
cases this commit cover are the most common ones, so this would
be a good start.

Signed-off-by: Junio C Hamano <junkio@cox.net>

  • Participants
  • Parent commits 7564577

Comments (0)

Files changed (1)

File git-merge-recursive.py

         runProgram(['git-update-index', '--add', '--cacheinfo',
                     '0%o' % mode, sha, path])
 
+def setIndexStages(path,
+                   oSHA1, oMode,
+                   aSHA1, aMode,
+                   bSHA1, bMode):
+    prog = ['git-update-index', '-z', '--index-info']
+    proc = subprocess.Popen(prog, stdin=subprocess.PIPE)
+    pipe = proc.stdin
+    # Clear stages first.
+    pipe.write("0 " + ("0" * 40) + "\t" + path + "\0")
+    # Set stages
+    pipe.write("%o %s %d\t%s\0" % (oMode, oSHA1, 1, path))
+    pipe.write("%o %s %d\t%s\0" % (aMode, aSHA1, 2, path))
+    pipe.write("%o %s %d\t%s\0" % (bMode, bSHA1, 3, path))
+    pipe.close()
+    proc.wait()
+
 def removeFile(clean, path):
     updateCache = cacheOnly or clean
     updateWd = not cacheOnly
                 else:
                     dstName2 = ren1.dstName
 
+                # NEEDSWORK: place dstNameA at stage 2 and dstNameB at stage 3
+                # What about other stages???
                 updateFile(False, ren1.dstSha, ren1.dstMode, dstName1)
                 updateFile(False, ren2.dstSha, ren2.dstMode, dstName2)
             else:
                     cleanMerge = False
 
                     if not cacheOnly:
-                        updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName,
-                                      updateCache=True, updateWd=False)
+                        setIndexStages(ren1.dstName,
+                                       ren1.srcSha, ren1.srcMode,
+                                       ren1.dstSha, ren1.dstMode,
+                                       ren2.dstSha, ren2.dstMode)
+
                 updateFile(clean, resSha, resMode, ren1.dstName)
         else:
             # Renamed in 1, maybe changed in 2
                 tryMerge = True
 
             if tryMerge:
+
+                oName, oSHA1, oMode = ren1.srcName, ren1.srcSha, ren1.srcMode
+                aName, bName = ren1.dstName, ren1.srcName
+                aSHA1, bSHA1 = ren1.dstSha, srcShaOtherBranch
+                aMode, bMode = ren1.dstMode, srcModeOtherBranch
+                aBranch, bBranch = branchName1, branchName2
+
+                if renamesA != renames1:
+                    aName, bName = bName, aName
+                    aSHA1, bSHA1 = bSHA1, aSHA1
+                    aMode, bMode = bMode, aMode
+                    aBranch, bBranch = bBranch, aBranch
+
                 [resSha, resMode, clean, merge] = \
-                         mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode,
-                                   ren1.dstName, ren1.dstSha, ren1.dstMode,
-                                   ren1.srcName, srcShaOtherBranch, srcModeOtherBranch,
-                                   branchName1, branchName2)
+                         mergeFile(oName, oSHA1, oMode,
+                                   aName, aSHA1, aMode,
+                                   bName, bSHA1, bMode,
+                                   aBranch, bBranch);
 
                 if merge or not clean:
                     output('Renaming', fmtRename(ren1.srcName, ren1.dstName))
                     cleanMerge = False
 
                     if not cacheOnly:
-                        updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName,
-                                      updateCache=True, updateWd=False)
+                        # Stuff stage1/2/3
+                        setIndexStages(ren1.dstName,
+                                       oSHA1, oMode,
+                                       aSHA1, aMode,
+                                       bSHA1, bMode)
+
                 updateFile(clean, resSha, resMode, ren1.dstName)
 
     return cleanMerge