git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[WIP/RFC 12/13] git notes merge: Add automatic conflict resolvers (ours, theirs, union)

From
Johan Herland <johan@herland.net>
Date
Jul 23, 2010, 10:15 UTC
Message-ID
<1279880104-29796-13-git-send-email-johan@herland.net>
In-Reply-To
<1279880104-29796-1-git-send-email-johan@herland.net>

The new -X/--resolve command-line option to 'git notes merge' allow the user to choose how notes merge conflicts should be resolved. There are four valid resolvers to choose from:

1. "manual" (the default): This will let the user manually resolve conflicts.
   This option currently fails with an error message. It will be implemented
   properly in future patches.
2. "ours": This automatically chooses the local version of a conflict, and
   discards the remote version.
3. "theirs": This automatically chooses the remote version of a conflict, and
   discards the local version.
4. "union": This automatically resolves the conflict by appending the remote
   version to the local version.

The auto-resolvers are implement using the combine_notes_* functions from the notes.h API.

The patch also includes testcases verifying the correct implementation of these auto-resolvers.

Signed-off-by: Johan Herland <johan@herland.net>
---
 builtin/notes.c                     |   21 ++-
 notes-merge.c                       |   29 ++-
 notes-merge.h                       |    6 +
 t/t3309-notes-merge-auto-resolve.sh |  512 +++++++++++++++++++++++++++++++++++
 4 files changed, 566 insertions(+), 2 deletions(-)
 create mode 100755 t/t3309-notes-merge-auto-resolve.sh
diff --git a/builtin/notes.c b/builtin/notes.c
index 1d22635..e14c6f2 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -26,7 +26,7 @@ static const char * const git_notes_usage[] = {
 	"git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
 	"git notes [--ref <notes_ref>] edit [<object>]",
 	"git notes [--ref <notes_ref>] show [<object>]",
-	"git notes [--ref <notes_ref>] merge [-v | -q] <notes_ref>",
+	"git notes [--ref <notes_ref>] merge [-v | -q] [-X <strategy> ] <notes_ref>",
 	"git notes [--ref <notes_ref>] remove [<object>]",
 	"git notes [--ref <notes_ref>] prune [-n | -v]",
 	NULL
@@ -770,8 +770,12 @@ static int merge(int argc, const char **argv, const char *prefix)
 	struct notes_tree *t;
 	struct notes_merge_options o;
 	int verbosity = 0, result;
+	const char *resolver = NULL;
 	struct option options[] = {
 		OPT__VERBOSITY(&verbosity),
+		OPT_STRING('X', "resolve", &resolver, "strategy",
+			   "resolve notes conflicts using the given "
+			   "strategy (manual/ours/theirs/union)"),
 		OPT_END()
 	};
 
@@ -793,6 +797,21 @@ static int merge(int argc, const char **argv, const char *prefix)
 	expand_notes_ref(&remote_ref);
 	o.remote_ref = remote_ref.buf;
 
+	if (resolver) {
+		if (!strcmp(resolver, "manual"))
+			o.resolve = NOTES_MERGE_RESOLVE_MANUAL;
+		else if (!strcmp(resolver, "ours"))
+			o.resolve = NOTES_MERGE_RESOLVE_OURS;
+		else if (!strcmp(resolver, "theirs"))
+			o.resolve = NOTES_MERGE_RESOLVE_THEIRS;
+		else if (!strcmp(resolver, "union"))
+			o.resolve = NOTES_MERGE_RESOLVE_UNION;
+		else {
+			error("Unknown -X/--resolve strategy: %s", resolver);
+			usage_with_options(git_notes_merge_usage, options);
+		}
+	}
+
 	t = init_notes_check("merge");
 
 	strbuf_addf(&msg, "notes: Merged notes from %s into %s",
diff --git a/notes-merge.c b/notes-merge.c
index ba9703a..c7db60a 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -262,6 +262,33 @@ static void diff_tree_local(struct notes_merge_options *o,
 	diff_tree_release_paths(&opt);
 }
 
+static int merge_one_change(struct notes_merge_options *o,
+			    struct notes_merge_pair *p, struct notes_tree *t)
+{
+	/*
+	 * Return 0 if change was resolved (and added to notes_tree),
+	 * 1 if conflict
+	 */
+	switch (o->resolve) {
+	case NOTES_MERGE_RESOLVE_MANUAL:
+		return 1;
+	case NOTES_MERGE_RESOLVE_OURS:
+		OUTPUT(o, 2, "Using local notes for %s", sha1_to_hex(p->obj));
+		/* nothing to do */
+		return 0;
+	case NOTES_MERGE_RESOLVE_THEIRS:
+		OUTPUT(o, 2, "Using remote notes for %s", sha1_to_hex(p->obj));
+		add_note(t, p->obj, p->remote, combine_notes_overwrite);
+		return 0;
+	case NOTES_MERGE_RESOLVE_UNION:
+		OUTPUT(o, 2, "Concatenating local and remote notes for %s",
+		       sha1_to_hex(p->obj));
+		add_note(t, p->obj, p->remote, combine_notes_concatenate);
+		return 0;
+	}
+	die("Unknown resolve method (%i).", o->resolve);
+}
+
 static int merge_changes(struct notes_merge_options *o,
 			 struct notes_merge_pair *changes, int *num_changes,
 			 struct notes_tree *t)
@@ -289,7 +316,7 @@ static int merge_changes(struct notes_merge_options *o,
 		} else {
 			/* need file-level merge between local and remote */
 			OUTPUT(o, 5, "\t\t\tneed content-level merge");
-			conflicts += 1; /* TODO */
+			conflicts += merge_one_change(o, p, t);
 		}
 	}
 
diff --git a/notes-merge.h b/notes-merge.h
index e42ce4b..bd808d0 100644
--- a/notes-merge.h
+++ b/notes-merge.h
@@ -6,6 +6,12 @@ struct notes_merge_options {
 	const char *remote_ref;
 	const char *commit_msg;
 	int verbosity;
+	enum {
+		NOTES_MERGE_RESOLVE_MANUAL = 0,
+		NOTES_MERGE_RESOLVE_OURS,
+		NOTES_MERGE_RESOLVE_THEIRS,
+		NOTES_MERGE_RESOLVE_UNION
+	} resolve;
 };
 
 void init_notes_merge_options(struct notes_merge_options *o);
diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh
new file mode 100755
index 0000000..171e795
--- /dev/null
+++ b/t/t3309-notes-merge-auto-resolve.sh
@@ -0,0 +1,512 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Johan Herland
+#
+
+test_description='Test notes merging with automatic resolvers'
+
+. ./test-lib.sh
+
+# Set up a notes merge scenario with all kinds of potential conflicts
+test_expect_success 'setup commits' '
+	# Create 15 commits with tags ("1st" through "15th")
+	: > a1 && git add a1 && test_tick && git commit -m 1st && git tag 1st &&
+	: > a2 && git add a2 && test_tick && git commit -m 2nd && git tag 2nd &&
+	: > a3 && git add a3 && test_tick && git commit -m 3rd && git tag 3rd &&
+	: > a4 && git add a4 && test_tick && git commit -m 4th && git tag 4th &&
+	: > a5 && git add a5 && test_tick && git commit -m 5th && git tag 5th &&
+	: > a6 && git add a6 && test_tick && git commit -m 6th && git tag 6th &&
+	: > a7 && git add a7 && test_tick && git commit -m 7th && git tag 7th &&
+	: > a8 && git add a8 && test_tick && git commit -m 8th && git tag 8th &&
+	: > a9 && git add a9 && test_tick && git commit -m 9th && git tag 9th &&
+	: > a10 && git add a10 && test_tick && git commit -m 10th && git tag 10th &&
+	: > a11 && git add a11 && test_tick && git commit -m 11th && git tag 11th &&
+	: > a12 && git add a12 && test_tick && git commit -m 12th && git tag 12th &&
+	: > a13 && git add a13 && test_tick && git commit -m 13th && git tag 13th &&
+	: > a14 && git add a14 && test_tick && git commit -m 14th && git tag 14th &&
+	: > a15 && git add a15 && test_tick && git commit -m 15th && git tag 15th
+'
+
+test_expect_success 'setup merge base (x)' '
+	git config core.notesRef refs/notes/x &&
+	git notes add -m "x notes on 6th commit" 6th &&
+	git notes add -m "x notes on 7th commit" 7th &&
+	git notes add -m "x notes on 8th commit" 8th &&
+	git notes add -m "x notes on 9th commit" 9th &&
+	git notes add -m "x notes on 10th commit" 10th &&
+	git notes add -m "x notes on 11th commit" 11th &&
+	git notes add -m "x notes on 12th commit" 12th &&
+	git notes add -m "x notes on 13th commit" 13th &&
+	git notes add -m "x notes on 14th commit" 14th &&
+	git notes add -m "x notes on 15th commit" 15th
+'
+
+cat >expect_notes_x <<EOF
+20c613c835011c48a5abe29170a2402ca6354910 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b
+897003322b53bc6ca098e9324ee508362347e734 2ede89468182a62d0bde2583c736089bcf7d7e92
+11d97fdebfa5ceee540a3da07bce6fa0222bc082 387a89921c73d7ed72cd94d179c1c7048ca47756
+457a85d6c814ea208550f15fcc48f804ac8dc023 516bb9cbbfaa1be722bcf97df393a12e1e7c944d
+7abbc45126d680336fb24294f013a7cdfa3ed545 6352c5e33dbcab725fe0579be16aa2ba8eb369be
+dd161bc149470fd890dd4ab52a4cbd79bbd18c36 7038787dfe22a14c3867ce816dbba39845359719
+a3daf8a1e4e5dc3409a303ad8481d57bfea7f5d6 80d796defacd5db327b7a4e50099663902fbdc5c
+5d30216a129eeffa97d9694ffe8c74317a560315 e5d4fb5698d564ab8c73551538ecaf2b0c666185
+b0c95b954301d69da2bc3723f4cb1680d355937c f42b4e95384566bc7b31d9d3bfcec2d1a8f3e2e8
+b8d03e173f67f6505a76f6e00cf93440200dd9be ffed603236bfa3891c49644257a83598afe8ae5a
+EOF
+
+cat >expect_log_x <<EOF
+516bb9c 15th
+x notes on 15th commit
+
+f42b4e9 14th
+x notes on 14th commit
+
+e5d4fb5 13th
+x notes on 13th commit
+
+7038787 12th
+x notes on 12th commit
+
+6352c5e 11th
+x notes on 11th commit
+
+ffed603 10th
+x notes on 10th commit
+
+016e982 9th
+x notes on 9th commit
+
+80d796d 8th
+x notes on 8th commit
+
+2ede894 7th
+x notes on 7th commit
+
+387a899 6th
+x notes on 6th commit
+
+bd17532 5th
+
+1502353 4th
+
+1584215 3rd
+
+268048b 2nd
+
+34b09d6 1st
+
+EOF
+
+test_expect_success 'verify state of merge base (x)' '
+	git notes >output_notes_x &&
+	test_cmp expect_notes_x output_notes_x &&
+	git log --format="%h %s%n%N" >output_log_x &&
+	test_cmp expect_log_x output_log_x
+'
+
+test_expect_success 'setup local branch (y)' '
+	git update-ref refs/notes/y refs/notes/x &&
+	git config core.notesRef refs/notes/y &&
+	git notes add -f -m "y notes on 3rd commit" 3rd &&
+	git notes add -f -m "y notes on 4th commit" 4th &&
+	git notes add -f -m "y notes on 5th commit" 5th &&
+	git notes remove 6th &&
+	git notes remove 7th &&
+	git notes remove 8th &&
+	git notes add -f -m "y notes on 12th commit" 12th &&
+	git notes add -f -m "y notes on 13th commit" 13th &&
+	git notes add -f -m "y notes on 14th commit" 14th &&
+	git notes add -f -m "y notes on 15th commit" 15th
+'
+
+cat >expect_notes_y <<EOF
+20c613c835011c48a5abe29170a2402ca6354910 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b
+e2bfd06a37dd2031684a59a6e2b033e212239c78 15023535574ded8b1a89052b32673f84cf9582b8
+5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 1584215f1d29c65e99c6c6848626553fdd07fd75
+68b8630d25516028bed862719855b3d6768d7833 516bb9cbbfaa1be722bcf97df393a12e1e7c944d
+7abbc45126d680336fb24294f013a7cdfa3ed545 6352c5e33dbcab725fe0579be16aa2ba8eb369be
+a66055fa82f7a03fe0c02a6aba3287a85abf7c62 7038787dfe22a14c3867ce816dbba39845359719
+154508c7a0bcad82b6fe4b472bc4c26b3bf0825b bd1753200303d0a0344be813e504253b3d98e74d
+3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc e5d4fb5698d564ab8c73551538ecaf2b0c666185
+5de7ea7ad4f47e7ff91989fb82234634730f75df f42b4e95384566bc7b31d9d3bfcec2d1a8f3e2e8
+b8d03e173f67f6505a76f6e00cf93440200dd9be ffed603236bfa3891c49644257a83598afe8ae5a
+EOF
+
+cat >expect_log_y <<EOF
+516bb9c 15th
+y notes on 15th commit
+
+f42b4e9 14th
+y notes on 14th commit
+
+e5d4fb5 13th
+y notes on 13th commit
+
+7038787 12th
+y notes on 12th commit
+
+6352c5e 11th
+x notes on 11th commit
+
+ffed603 10th
+x notes on 10th commit
+
+016e982 9th
+x notes on 9th commit
+
+80d796d 8th
+
+2ede894 7th
+
+387a899 6th
+
+bd17532 5th
+y notes on 5th commit
+
+1502353 4th
+y notes on 4th commit
+
+1584215 3rd
+y notes on 3rd commit
+
+268048b 2nd
+
+34b09d6 1st
+
+EOF
+
+test_expect_success 'verify state of local branch (y)' '
+	git notes >output_notes_y &&
+	test_cmp expect_notes_y output_notes_y &&
+	git log --format="%h %s%n%N" >output_log_y &&
+	test_cmp expect_log_y output_log_y
+'
+
+test_expect_success 'setup remote branch (z)' '
+	git update-ref refs/notes/z refs/notes/x &&
+	git config core.notesRef refs/notes/z &&
+	git notes add -f -m "z notes on 2nd commit" 2nd &&
+	git notes add -f -m "y notes on 4th commit" 4th &&
+	git notes add -f -m "z notes on 5th commit" 5th &&
+	git notes remove 6th &&
+	git notes add -f -m "z notes on 8th commit" 8th &&
+	git notes remove 9th &&
+	git notes add -f -m "z notes on 11th commit" 11th &&
+	git notes remove 12th &&
+	git notes add -f -m "y notes on 14th commit" 14th &&
+	git notes add -f -m "z notes on 15th commit" 15th
+'
+
+cat >expect_notes_z <<EOF
+e2bfd06a37dd2031684a59a6e2b033e212239c78 15023535574ded8b1a89052b32673f84cf9582b8
+283b48219aee9a4105f6cab337e789065c82c2b9 268048bfb8a1fb38e703baceb8ab235421bf80c5
+897003322b53bc6ca098e9324ee508362347e734 2ede89468182a62d0bde2583c736089bcf7d7e92
+9b4b2c61f0615412da3c10f98ff85b57c04ec765 516bb9cbbfaa1be722bcf97df393a12e1e7c944d
+7e3c53503a3db8dd996cb62e37c66e070b44b54d 6352c5e33dbcab725fe0579be16aa2ba8eb369be
+851e1638784a884c7dd26c5d41f3340f6387413a 80d796defacd5db327b7a4e50099663902fbdc5c
+99fc34adfc400b95c67b013115e37e31aa9a6d23 bd1753200303d0a0344be813e504253b3d98e74d
+5d30216a129eeffa97d9694ffe8c74317a560315 e5d4fb5698d564ab8c73551538ecaf2b0c666185
+5de7ea7ad4f47e7ff91989fb82234634730f75df f42b4e95384566bc7b31d9d3bfcec2d1a8f3e2e8
+b8d03e173f67f6505a76f6e00cf93440200dd9be ffed603236bfa3891c49644257a83598afe8ae5a
+EOF
+
+cat >expect_log_z <<EOF
+516bb9c 15th
+z notes on 15th commit
+
+f42b4e9 14th
+y notes on 14th commit
+
+e5d4fb5 13th
+x notes on 13th commit
+
+7038787 12th
+
+6352c5e 11th
+z notes on 11th commit
+
+ffed603 10th
+x notes on 10th commit
+
+016e982 9th
+
+80d796d 8th
+z notes on 8th commit
+
+2ede894 7th
+x notes on 7th commit
+
+387a899 6th
+
+bd17532 5th
+z notes on 5th commit
+
+1502353 4th
+y notes on 4th commit
+
+1584215 3rd
+
+268048b 2nd
+z notes on 2nd commit
+
+34b09d6 1st
+
+EOF
+
+test_expect_success 'verify state of remote branch (z)' '
+	git notes >output_notes_z &&
+	test_cmp expect_notes_z output_notes_z &&
+	git log --format="%h %s%n%N" >output_log_z &&
+	test_cmp expect_log_z output_log_z
+'
+
+# At this point, before merging z into y, we have the following status:
+#
+# commit | object  | base/x  | local/y | remote/z |? diff from x to y/z
+# -------|---------|---------|---------|----------||---------------------------
+# 1st    | 34b09d6 | [none]  | [none]  | [none]   || unchanged / unchanged
+# 2nd    | 268048b | [none]  | [none]  | 283b482  || unchanged / added
+# 3rd    | 1584215 | [none]  | 5772f42 | [none]   || added     / unchanged
+# 4th    | 1502353 | [none]  | e2bfd06 | e2bfd06  || added     / added (same)
+# 5th    | bd17532 | [none]  | 154508c | 99fc34a  |+ added     / added (diff)
+# 6th    | 387a899 | 11d97fd | [none]  | [none]   || removed   / removed
+# 7th    | 2ede894 | 8970033 | [none]  | 8970033  || removed   / unchanged
+# 8th    | 80d796d | a3daf8a | [none]  | 851e163  |+ removed   / changed
+# 9th    | 016e982 | 20c613c | 20c613c | [none]   || unchanged / removed
+# 10th   | ffed603 | b8d03e1 | b8d03e1 | b8d03e1  || unchanged / unchanged
+# 11th   | 6352c5e | 7abbc45 | 7abbc45 | 7e3c535  || unchanged / changed
+# 12th   | 7038787 | dd161bc | a66055f | [none]   |+ changed   / removed
+# 13th   | e5d4fb5 | 5d30216 | 3a631fd | 5d30216  || changed   / unchanged
+# 14th   | f42b4e9 | b0c95b9 | 5de7ea7 | 5de7ea7  || changed   / changed (same)
+# 15th   | 516bb9c | 457a85d | 68b8630 | 9b4b2c6  |+ changed   / changed (diff)
+
+test_expect_success 'merge z into y with invalid resolver => Fail/No changes' '
+	git config core.notesRef refs/notes/y &&
+	test_must_fail git notes merge --resolve=foo z &&
+	# Verify no changes (y)
+	git notes >output_notes_y &&
+	test_cmp expect_notes_y output_notes_y &&
+	git log --format="%h %s%n%N" >output_log_y &&
+	test_cmp expect_log_y output_log_y
+'
+
+cat >expect_notes_ours <<EOF
+e2bfd06a37dd2031684a59a6e2b033e212239c78 15023535574ded8b1a89052b32673f84cf9582b8
+5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 1584215f1d29c65e99c6c6848626553fdd07fd75
+283b48219aee9a4105f6cab337e789065c82c2b9 268048bfb8a1fb38e703baceb8ab235421bf80c5
+68b8630d25516028bed862719855b3d6768d7833 516bb9cbbfaa1be722bcf97df393a12e1e7c944d
+7e3c53503a3db8dd996cb62e37c66e070b44b54d 6352c5e33dbcab725fe0579be16aa2ba8eb369be
+a66055fa82f7a03fe0c02a6aba3287a85abf7c62 7038787dfe22a14c3867ce816dbba39845359719
+154508c7a0bcad82b6fe4b472bc4c26b3bf0825b bd1753200303d0a0344be813e504253b3d98e74d
+3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc e5d4fb5698d564ab8c73551538ecaf2b0c666185
+5de7ea7ad4f47e7ff91989fb82234634730f75df f42b4e95384566bc7b31d9d3bfcec2d1a8f3e2e8
+b8d03e173f67f6505a76f6e00cf93440200dd9be ffed603236bfa3891c49644257a83598afe8ae5a
+EOF
+
+cat >expect_log_ours <<EOF
+516bb9c 15th
+y notes on 15th commit
+
+f42b4e9 14th
+y notes on 14th commit
+
+e5d4fb5 13th
+y notes on 13th commit
+
+7038787 12th
+y notes on 12th commit
+
+6352c5e 11th
+z notes on 11th commit
+
+ffed603 10th
+x notes on 10th commit
+
+016e982 9th
+
+80d796d 8th
+
+2ede894 7th
+
+387a899 6th
+
+bd17532 5th
+y notes on 5th commit
+
+1502353 4th
+y notes on 4th commit
+
+1584215 3rd
+y notes on 3rd commit
+
+268048b 2nd
+z notes on 2nd commit
+
+34b09d6 1st
+
+EOF
+
+test_expect_success 'merge z into y with "ours" resolver => Non-conflicting 3-way merge' '
+	git notes merge --resolve=ours z &&
+	# Verify merge result
+	git notes >output_notes_ours &&
+	test_cmp expect_notes_ours output_notes_ours &&
+	git log --format="%h %s%n%N" >output_log_ours &&
+	test_cmp expect_log_ours output_log_ours
+'
+
+test_expect_success 'reset to pre-merge state (y)' '
+	git update-ref refs/notes/y refs/notes/y^1 &&
+	# Verify pre-merge state
+	git notes >output_notes_y &&
+	test_cmp expect_notes_y output_notes_y &&
+	git log --format="%h %s%n%N" >output_log_y &&
+	test_cmp expect_log_y output_log_y
+'
+
+cat >expect_notes_theirs <<EOF
+e2bfd06a37dd2031684a59a6e2b033e212239c78 15023535574ded8b1a89052b32673f84cf9582b8
+5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 1584215f1d29c65e99c6c6848626553fdd07fd75
+283b48219aee9a4105f6cab337e789065c82c2b9 268048bfb8a1fb38e703baceb8ab235421bf80c5
+9b4b2c61f0615412da3c10f98ff85b57c04ec765 516bb9cbbfaa1be722bcf97df393a12e1e7c944d
+7e3c53503a3db8dd996cb62e37c66e070b44b54d 6352c5e33dbcab725fe0579be16aa2ba8eb369be
+851e1638784a884c7dd26c5d41f3340f6387413a 80d796defacd5db327b7a4e50099663902fbdc5c
+99fc34adfc400b95c67b013115e37e31aa9a6d23 bd1753200303d0a0344be813e504253b3d98e74d
+3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc e5d4fb5698d564ab8c73551538ecaf2b0c666185
+5de7ea7ad4f47e7ff91989fb82234634730f75df f42b4e95384566bc7b31d9d3bfcec2d1a8f3e2e8
+b8d03e173f67f6505a76f6e00cf93440200dd9be ffed603236bfa3891c49644257a83598afe8ae5a
+EOF
+
+cat >expect_log_theirs <<EOF
+516bb9c 15th
+z notes on 15th commit
+
+f42b4e9 14th
+y notes on 14th commit
+
+e5d4fb5 13th
+y notes on 13th commit
+
+7038787 12th
+
+6352c5e 11th
+z notes on 11th commit
+
+ffed603 10th
+x notes on 10th commit
+
+016e982 9th
+
+80d796d 8th
+z notes on 8th commit
+
+2ede894 7th
+
+387a899 6th
+
+bd17532 5th
+z notes on 5th commit
+
+1502353 4th
+y notes on 4th commit
+
+1584215 3rd
+y notes on 3rd commit
+
+268048b 2nd
+z notes on 2nd commit
+
+34b09d6 1st
+
+EOF
+
+test_expect_success 'merge z into y with "theirs" resolver => Non-conflicting 3-way merge' '
+	git notes merge --resolve=theirs z &&
+	# Verify merge result
+	git notes >output_notes_theirs &&
+	test_cmp expect_notes_theirs output_notes_theirs &&
+	git log --format="%h %s%n%N" >output_log_theirs &&
+	test_cmp expect_log_theirs output_log_theirs
+'
+
+test_expect_success 'reset to pre-merge state (y)' '
+	git update-ref refs/notes/y refs/notes/y^1 &&
+	# Verify pre-merge state
+	git notes >output_notes_y &&
+	test_cmp expect_notes_y output_notes_y &&
+	git log --format="%h %s%n%N" >output_log_y &&
+	test_cmp expect_log_y output_log_y
+'
+
+cat >expect_notes_union <<EOF
+e2bfd06a37dd2031684a59a6e2b033e212239c78 15023535574ded8b1a89052b32673f84cf9582b8
+5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 1584215f1d29c65e99c6c6848626553fdd07fd75
+283b48219aee9a4105f6cab337e789065c82c2b9 268048bfb8a1fb38e703baceb8ab235421bf80c5
+7c4e546efd0fe939f876beb262ece02797880b54 516bb9cbbfaa1be722bcf97df393a12e1e7c944d
+7e3c53503a3db8dd996cb62e37c66e070b44b54d 6352c5e33dbcab725fe0579be16aa2ba8eb369be
+a66055fa82f7a03fe0c02a6aba3287a85abf7c62 7038787dfe22a14c3867ce816dbba39845359719
+851e1638784a884c7dd26c5d41f3340f6387413a 80d796defacd5db327b7a4e50099663902fbdc5c
+6c841cc36ea496027290967ca96bd2bef54dbb47 bd1753200303d0a0344be813e504253b3d98e74d
+3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc e5d4fb5698d564ab8c73551538ecaf2b0c666185
+5de7ea7ad4f47e7ff91989fb82234634730f75df f42b4e95384566bc7b31d9d3bfcec2d1a8f3e2e8
+b8d03e173f67f6505a76f6e00cf93440200dd9be ffed603236bfa3891c49644257a83598afe8ae5a
+EOF
+
+cat >expect_log_union <<EOF
+516bb9c 15th
+y notes on 15th commit
+
+z notes on 15th commit
+
+f42b4e9 14th
+y notes on 14th commit
+
+e5d4fb5 13th
+y notes on 13th commit
+
+7038787 12th
+y notes on 12th commit
+
+6352c5e 11th
+z notes on 11th commit
+
+ffed603 10th
+x notes on 10th commit
+
+016e982 9th
+
+80d796d 8th
+z notes on 8th commit
+
+2ede894 7th
+
+387a899 6th
+
+bd17532 5th
+y notes on 5th commit
+
+z notes on 5th commit
+
+1502353 4th
+y notes on 4th commit
+
+1584215 3rd
+y notes on 3rd commit
+
+268048b 2nd
+z notes on 2nd commit
+
+34b09d6 1st
+
+EOF
+
+test_expect_success 'merge z into y with "union" resolver => Non-conflicting 3-way merge' '
+	git notes merge --resolve=union z &&
+	# Verify merge result
+	git notes >output_notes_union &&
+	test_cmp expect_notes_union output_notes_union &&
+	git log --format="%h %s%n%N" >output_log_union &&
+	test_cmp expect_log_union output_log_union
+'
+
+test_done
-- 
1.7.2.220.gea1d3
Previous: Johan HerlandNext: Stephen Boyd
Message 17 of 24 in “[WIP/RFC 00/13] git notes merge”
  1. Johan HerlandJul 23, 2010
  2. 01/13 (trivial) notes.h: Minor documentation fixes to copy_notes()Johan Herland, Jul 23, 2010
  3. 02/13 notes.h: Make default_notes_ref() available in notes APIJohan Herland, Jul 23, 2010
  4. 03/13 notes.h/c: Clarify the handling of notes objects that are == null_sha1Johan Herland, Jul 23, 2010
  5. 04/13 notes.h/c: Propagate combine_notes_fn return value to add_note() and beyondJohan Herland, Jul 23, 2010
  6. Jonathan NiederJul 23, 2010
  7. Johan HerlandJul 23, 2010
  8. 05/13 (trivial) t3303: Indent with tabs instead of spaces for consistencyJohan Herland, Jul 23, 2010
  9. 06/13 notes.c: Use two newlines (instead of one) when concatenating notesJohan Herland, Jul 23, 2010
  10. 07/13 (trivial) git notes prune: Accept --verbose in addition to -vJohan Herland, Jul 23, 2010
  11. 08/13 builtin/notes.c: Split notes ref DWIMmery into a separate functionJohan Herland, Jul 23, 2010
  12. 09/13 git notes merge: Initial implementation handling trivial merges onlyJohan Herland, Jul 23, 2010
  13. Stephen BoydJul 24, 2010
  14. Johan HerlandJul 25, 2010
  15. 10/13 builtin/notes.c: Refactor creation of notes commits.Johan Herland, Jul 23, 2010
  16. 11/13 git notes merge: Handle real, non-conflicting notes mergesJohan Herland, Jul 23, 2010
  17. 12/13 git notes merge: Add automatic conflict resolvers (ours, theirs, union)Johan Herland, Jul 23, 2010
  18. Stephen BoydJul 24, 2010
  19. Johan HerlandJul 25, 2010
  20. 13/13 Documentation: Preliminary docs on 'git notes merge'Johan Herland, Jul 23, 2010
  21. Stephen BoydJul 24, 2010
  22. Johan HerlandJul 25, 2010
  23. Sam VilainJul 25, 2010
  24. Johan HerlandJul 25, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.