Browse Source

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>
maint
Junio C Hamano 19 years ago
parent
commit
28e77a8164
  1. 54
      git-merge-recursive.py

54
git-merge-recursive.py

@ -280,6 +280,22 @@ def updateFileExt(sha, mode, path, updateCache, updateWd):
runProgram(['git-update-index', '--add', '--cacheinfo', runProgram(['git-update-index', '--add', '--cacheinfo',
'0%o' % mode, sha, path]) '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): def removeFile(clean, path):
updateCache = cacheOnly or clean updateCache = cacheOnly or clean
updateWd = not cacheOnly updateWd = not cacheOnly
@ -590,6 +606,8 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
else: else:
dstName2 = ren1.dstName 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, ren1.dstSha, ren1.dstMode, dstName1)
updateFile(False, ren2.dstSha, ren2.dstMode, dstName2) updateFile(False, ren2.dstSha, ren2.dstMode, dstName2)
else: else:
@ -611,8 +629,11 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
cleanMerge = False cleanMerge = False


if not cacheOnly: if not cacheOnly:
updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName, setIndexStages(ren1.dstName,
updateCache=True, updateWd=False) ren1.srcSha, ren1.srcMode,
ren1.dstSha, ren1.dstMode,
ren2.dstSha, ren2.dstMode)

updateFile(clean, resSha, resMode, ren1.dstName) updateFile(clean, resSha, resMode, ren1.dstName)
else: else:
# Renamed in 1, maybe changed in 2 # Renamed in 1, maybe changed in 2
@ -672,11 +693,24 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
tryMerge = True tryMerge = True


if tryMerge: 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] = \ [resSha, resMode, clean, merge] = \
mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode, mergeFile(oName, oSHA1, oMode,
ren1.dstName, ren1.dstSha, ren1.dstMode, aName, aSHA1, aMode,
ren1.srcName, srcShaOtherBranch, srcModeOtherBranch, bName, bSHA1, bMode,
branchName1, branchName2) aBranch, bBranch);


if merge or not clean: if merge or not clean:
output('Renaming', fmtRename(ren1.srcName, ren1.dstName)) output('Renaming', fmtRename(ren1.srcName, ren1.dstName))
@ -690,8 +724,12 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
cleanMerge = False cleanMerge = False


if not cacheOnly: if not cacheOnly:
updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName, # Stuff stage1/2/3
updateCache=True, updateWd=False) setIndexStages(ren1.dstName,
oSHA1, oMode,
aSHA1, aMode,
bSHA1, bMode)

updateFile(clean, resSha, resMode, ren1.dstName) updateFile(clean, resSha, resMode, ren1.dstName)


return cleanMerge return cleanMerge

Loading…
Cancel
Save