func syncBranchContinue()

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())
}