in git-codereview/sync.go [326:417]
func syncBranchContinue(flag string, b *Branch, status *syncBranchStatus) {
if h := gitHash("origin/" + status.Parent); h != status.ParentHash {
dief("cannot sync-branch%s: parent hash changed: %.7s -> %.7s", flag, status.ParentHash, h)
}
if h := gitHash("origin/" + status.Branch); h != status.BranchHash {
dief("cannot sync-branch%s: branch hash changed: %.7s -> %.7s", flag, status.BranchHash, h)
}
if b.Name != status.Local {
dief("cannot sync-branch%s: branch changed underfoot: %s -> %s", flag, status.Local, b.Name)
}
var (
dst = status.Branch
dstHash = status.BranchHash
src = status.Parent
srcHash = status.ParentHash
)
if flag == syncBranchMergeBackFlag {
// This is a reverse merge: commits are flowing
// in the opposite direction from normal.
dst, src = src, dst
dstHash, srcHash = srcHash, dstHash
}
prefix := prefixFor(dst)
op := "merge"
if flag == syncBranchMergeBackFlag {
op = "REVERSE MERGE"
}
msg := fmt.Sprintf("%sall: %s %s (%.7s) into %s", prefix, op, src, srcHash, dst)
if flag == syncBranchContinueFlag {
// Need to commit the merge.
// Check that the state of the client is the way we left it before any merge conflicts.
mergeHead, err := cmdOutputErr("git", "rev-parse", "MERGE_HEAD")
if err != nil {
dief("cannot sync-branch%s: no pending merge\n"+
"If you accidentally ran 'git merge --continue' or 'git commit',\n"+
"then use 'git reset --hard HEAD^' to undo.\n", flag)
}
mergeHead = trim(mergeHead)
if mergeHead != srcHash {
dief("cannot sync-branch%s: MERGE_HEAD is %.7s, but origin/%s is %.7s", flag, mergeHead, src, srcHash)
}
head := gitHash("HEAD")
if head != dstHash {
dief("cannot sync-branch%s: HEAD is %.7s, but origin/%s is %.7s", flag, head, dst, dstHash)
}
if HasUnstagedChanges() {
dief("cannot sync-branch%s: unstaged changes (unresolved conflicts)\n"+
"\tUse 'git status' to see them, 'git add' or 'git rm' to resolve them,\n"+
"\tand then run 'git sync-branch -continue' again.\n", flag)
}
run("git", "commit", "-m", msg)
}
// Amend the merge message, which may be auto-generated by git
// or may have been written by us during the post-conflict commit above,
// to use our standard format and list the incorporated CLs.
// Merge must never sync codereview.cfg,
// because it contains the src and dst config.
// Force the on-dst copy back while amending the commit.
cmdOutputDir(repoRoot(), "git", "checkout", "origin/"+dst, "--", "codereview.cfg")
conflictMsg := ""
if len(status.Conflicts) > 0 {
conflictMsg = "Conflicts:\n\n- " + strings.Join(status.Conflicts, "\n- ") + "\n\n"
}
if flag == syncBranchMergeBackFlag {
msg += fmt.Sprintf("\n\n"+
"This commit is a REVERSE MERGE.\n"+
"It merges %s back into its parent branch, %s.\n"+
"This marks the end of development on %s.\n",
status.Branch, status.Parent, status.Branch)
}
msg += fmt.Sprintf("\n\n%sMerge List:\n\n%s", conflictMsg,
cmdOutput("git", "log", "--format=format:+ %cd %h %s", "--date=short", "HEAD^1..HEAD^2"))
run("git", "commit", "--amend", "-m", msg)
fmt.Fprintf(stderr(), "\n")
cmdPending([]string{"-c", "-l"})
fmt.Fprintf(stderr(), "\n* Merge commit created.\nRun 'git codereview mail' to send for review.\n")
os.Remove(syncBranchStatusFile())
}