git notes merge: Manual conflict resolution, part 2/2

When the notes merge conflicts in .git/NOTES_MERGE_WORKTREE have been
resolved, we need to record a new notes commit on the appropriate notes
ref with the resolved notes.

This patch implements 'git notes merge --commit' which the user should
run after resolving conflicts in the notes merge worktree. This command
finalizes the notes merge by recombining the partial notes tree from
part 1 with the now-resolved conflicts in the notes merge worktree in a
merge commit, and updating the appropriate ref to this merge commit.

In order to correctly finalize the merge, we need to keep track of three
things:

- The partial merge result from part 1, containing the auto-merged notes.
  This is now stored into a ref called .git/NOTES_MERGE_PARTIAL.
- The unmerged notes. These are already stored in
  .git/NOTES_MERGE_WORKTREE, thanks to part 1.
- The notes ref to be updated by the finalized merge result. This is now
  stored in a symref called .git/NOTES_MERGE_REF.

In addition to "git notes merge --commit", which uses the above details
to create the finalized notes merge commit, this patch also implements
"git notes merge --reset", which aborts the ongoing notes merge by simply
removing the files/directory described above.

FTR, "git notes merge --commit" reuses "git notes merge --reset" to remove
the information described above (.git/NOTES_MERGE_*) after the notes merge
have been successfully finalized.

The patch also contains documentation and testcases for the two new options.

This patch has been improved by the following contributions:
- Ævar Arnfjörð Bjarmason: Fix nonsense sentence in --commit description
- Sverre Rabbelier: Rename --reset to --abort

Thanks-to: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Thanks-to: Sverre Rabbelier <srabbelier@gmail.com>
Signed-off-by: Johan Herland <johan@herland.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Johan Herland
2010-11-09 22:49:52 +01:00
committed by Junio C Hamano
parent 809f38c8ab
commit 6abb3655ef
5 changed files with 394 additions and 4 deletions

View File

@ -171,6 +171,7 @@ cp expect_notes_y expect_notes_m
cp expect_log_y expect_log_m
git rev-parse refs/notes/y > pre_merge_y
git rev-parse refs/notes/z > pre_merge_z
test_expect_success 'merge z into m (== y) with default ("manual") resolver => Conflicting 3-way merge' '
git update-ref refs/notes/m refs/notes/y &&
@ -289,4 +290,179 @@ test_expect_success 'can do merge without conflicts even if previous merge is un
verify_notes y
'
cat <<EOF | sort >expect_notes_m
021faa20e931fb48986ffc6282b4bb05553ac946 $commit_sha4
5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3
283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2
0a59e787e6d688aa6309e56e8c1b89431a0fc1c1 $commit_sha1
EOF
cat >expect_log_m <<EOF
$commit_sha5 5th
$commit_sha4 4th
y and z notes on 4th commit
$commit_sha3 3rd
y notes on 3rd commit
$commit_sha2 2nd
z notes on 2nd commit
$commit_sha1 1st
y and z notes on 1st commit
EOF
test_expect_success 'finalize conflicting merge (z => m)' '
# Resolve conflicts and finalize merge
cat >.git/NOTES_MERGE_WORKTREE/$commit_sha1 <<EOF &&
y and z notes on 1st commit
EOF
cat >.git/NOTES_MERGE_WORKTREE/$commit_sha4 <<EOF &&
y and z notes on 4th commit
EOF
git notes merge --commit &&
# No .git/NOTES_MERGE_* files left
test_must_fail ls .git/NOTES_MERGE_* >output 2>/dev/null &&
test_cmp /dev/null output &&
# Merge commit has pre-merge y and pre-merge z as parents
test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" &&
test "$(git rev-parse refs/notes/m^2)" = "$(cat pre_merge_z)" &&
# Merge commit mentions the notes refs merged
git log -1 --format=%B refs/notes/m > merge_commit_msg &&
grep -q refs/notes/m merge_commit_msg &&
grep -q refs/notes/z merge_commit_msg &&
# Verify contents of merge result
verify_notes m &&
# Verify that other notes refs has not changed (w, x, y and z)
verify_notes w &&
verify_notes x &&
verify_notes y &&
verify_notes z
'
cat >expect_conflict_$commit_sha4 <<EOF
<<<<<<< refs/notes/m
y notes on 4th commit
=======
z notes on 4th commit
More z notes on 4th commit
>>>>>>> refs/notes/z
EOF
cp expect_notes_y expect_notes_m
cp expect_log_y expect_log_m
git rev-parse refs/notes/y > pre_merge_y
git rev-parse refs/notes/z > pre_merge_z
test_expect_success 'redo merge of z into m (== y) with default ("manual") resolver => Conflicting 3-way merge' '
git update-ref refs/notes/m refs/notes/y &&
git config core.notesRef refs/notes/m &&
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
# Inspect merge conflicts
ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
( for f in $(cat expect_conflicts); do
test_cmp "expect_conflict_$f" ".git/NOTES_MERGE_WORKTREE/$f" ||
exit 1
done ) &&
# Verify that current notes tree (pre-merge) has not changed (m == y)
verify_notes y &&
verify_notes m &&
test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)"
'
test_expect_success 'abort notes merge' '
git notes merge --abort &&
# No .git/NOTES_MERGE_* files left
test_must_fail ls .git/NOTES_MERGE_* >output 2>/dev/null &&
test_cmp /dev/null output &&
# m has not moved (still == y)
test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)"
# Verify that other notes refs has not changed (w, x, y and z)
verify_notes w &&
verify_notes x &&
verify_notes y &&
verify_notes z
'
git rev-parse refs/notes/y > pre_merge_y
git rev-parse refs/notes/z > pre_merge_z
test_expect_success 'redo merge of z into m (== y) with default ("manual") resolver => Conflicting 3-way merge' '
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
# Inspect merge conflicts
ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
( for f in $(cat expect_conflicts); do
test_cmp "expect_conflict_$f" ".git/NOTES_MERGE_WORKTREE/$f" ||
exit 1
done ) &&
# Verify that current notes tree (pre-merge) has not changed (m == y)
verify_notes y &&
verify_notes m &&
test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)"
'
cat <<EOF | sort >expect_notes_m
304dfb4325cf243025b9957486eb605a9b51c199 $commit_sha5
283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2
0a59e787e6d688aa6309e56e8c1b89431a0fc1c1 $commit_sha1
EOF
cat >expect_log_m <<EOF
$commit_sha5 5th
new note on 5th commit
$commit_sha4 4th
$commit_sha3 3rd
$commit_sha2 2nd
z notes on 2nd commit
$commit_sha1 1st
y and z notes on 1st commit
EOF
test_expect_success 'add + remove notes in finalized merge (z => m)' '
# Resolve one conflict
cat >.git/NOTES_MERGE_WORKTREE/$commit_sha1 <<EOF &&
y and z notes on 1st commit
EOF
# Remove another conflict
rm .git/NOTES_MERGE_WORKTREE/$commit_sha4 &&
# Remove a D/F conflict
rm .git/NOTES_MERGE_WORKTREE/$commit_sha3 &&
# Add a new note
echo "new note on 5th commit" > .git/NOTES_MERGE_WORKTREE/$commit_sha5 &&
# Finalize merge
git notes merge --commit &&
# No .git/NOTES_MERGE_* files left
test_must_fail ls .git/NOTES_MERGE_* >output 2>/dev/null &&
test_cmp /dev/null output &&
# Merge commit has pre-merge y and pre-merge z as parents
test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" &&
test "$(git rev-parse refs/notes/m^2)" = "$(cat pre_merge_z)" &&
# Merge commit mentions the notes refs merged
git log -1 --format=%B refs/notes/m > merge_commit_msg &&
grep -q refs/notes/m merge_commit_msg &&
grep -q refs/notes/z merge_commit_msg &&
# Verify contents of merge result
verify_notes m &&
# Verify that other notes refs has not changed (w, x, y and z)
verify_notes w &&
verify_notes x &&
verify_notes y &&
verify_notes z
'
test_done