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

[PATCH 11/12] checkout --ours/--theirs

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 30, 2008, 00:42 UTC
Message-ID
<1220056963-2352-12-git-send-email-gitster@pobox.com>
In-Reply-To
<1220056963-2352-11-git-send-email-gitster@pobox.com>

This lets you to check out 'our' (or 'their') version of an unmerged path out of the index while resolving conflicts.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-checkout.c |   47 ++++++++++++++++++++++++++++++++++++++++++-----
 t/t7201-co.sh      |   25 +++++++++++++++++++++++++
 2 files changed, 67 insertions(+), 5 deletions(-)
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 49c43d9..bdfdb65 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -24,6 +24,7 @@ struct checkout_opts {
 	int quiet;
 	int merge;
 	int force;
+	int writeout_stage;
 	int writeout_error;
 
 	const char *new_branch;
@@ -95,6 +96,32 @@ static int skip_same_name(struct cache_entry *ce, int pos)
 	return pos;
 }
 
+static int check_stage(int stage, struct cache_entry *ce, int pos)
+{
+	while (pos < active_nr &&
+	       !strcmp(active_cache[pos]->name, ce->name)) {
+		if (ce_stage(active_cache[pos]) == stage)
+			return 0;
+		pos++;
+	}
+	return error("path '%s' does not have %s version",
+		     ce->name,
+		     (stage == 2) ? "our" : "their");
+}
+
+static int checkout_stage(int stage, struct cache_entry *ce, int pos,
+			  struct checkout *state)
+{
+	while (pos < active_nr &&
+	       !strcmp(active_cache[pos]->name, ce->name)) {
+		if (ce_stage(active_cache[pos]) == stage)
+			return checkout_entry(active_cache[pos], state, NULL);
+		pos++;
+	}
+	return error("path '%s' does not have %s version",
+		     ce->name,
+		     (stage == 2) ? "our" : "their");
+}
 
 static int checkout_paths(struct tree *source_tree, const char **pathspec,
 			  struct checkout_opts *opts)
@@ -106,6 +133,7 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
 	int flag;
 	struct commit *head;
 	int errs = 0;
+	int stage = opts->writeout_stage;
 
 	int newfd;
 	struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
@@ -131,13 +159,16 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
 	/* Any unmerged paths? */
 	for (pos = 0; pos < active_nr; pos++) {
 		struct cache_entry *ce = active_cache[pos];
-		if (pathspec_match(pathspec, NULL, ce->name, 0) &&
-		    ce_stage(ce)) {
-			if (!opts->force) {
+		if (pathspec_match(pathspec, NULL, ce->name, 0)) {
+			if (!ce_stage(ce))
+				continue;
+			if (stage) {
+				errs |= check_stage(stage, ce, pos);
+			} else if (opts->force) {
+				warning("path '%s' is unmerged", ce->name);
+			} else {
 				errs = 1;
 				error("path '%s' is unmerged", ce->name);
-			} else {
-				warning("path '%s' is unmerged", ce->name);
 			}
 			pos = skip_same_name(ce, pos) - 1;
 			continue;
@@ -154,6 +185,8 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
 		struct cache_entry *ce = active_cache[pos];
 		if (pathspec_match(pathspec, NULL, ce->name, 0)) {
 			if (ce_stage(ce)) {
+				if (stage)
+					errs |= checkout_stage(stage, ce, pos, &state);
 				pos = skip_same_name(ce, pos) - 1;
 				continue;
 			}
@@ -458,6 +491,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 		OPT_BOOLEAN('l', NULL, &opts.new_branch_log, "log for new branch"),
 		OPT_SET_INT('t', "track",  &opts.track, "track",
 			BRANCH_TRACK_EXPLICIT),
+		OPT_SET_INT('2', "ours", &opts.writeout_stage, "stage",
+			    2),
+		OPT_SET_INT('3', "theirs", &opts.writeout_stage, "stage",
+			    3),
 		OPT_BOOLEAN('f', NULL, &opts.force, "force"),
 		OPT_BOOLEAN('m', NULL, &opts.merge, "merge"),
 		OPT_END(),
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index b7274eb..85c792c 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -414,4 +414,29 @@ test_expect_success 'checkout with an unmerged path can be ignored' '
 	test_cmp sample file
 '
 
+test_expect_success 'checkout unmerged stage' '
+	rm -f .git/index &&
+	O=$(echo original | git hash-object -w --stdin) &&
+	A=$(echo ourside | git hash-object -w --stdin) &&
+	B=$(echo theirside | git hash-object -w --stdin) &&
+	(
+		echo "100644 $A 0	fild" &&
+		echo "100644 $O 1	file" &&
+		echo "100644 $A 2	file" &&
+		echo "100644 $B 3	file" &&
+		echo "100644 $A 0	filf"
+	) | git update-index --index-info &&
+	echo "none of the above" >sample &&
+	echo ourside >expect &&
+	cat sample >fild &&
+	cat sample >file &&
+	cat sample >filf &&
+	git checkout --ours . &&
+	test_cmp expect fild &&
+	test_cmp expect filf &&
+	test_cmp expect file &&
+	git checkout --theirs file &&
+	test ztheirside = "z$(cat file)"
+'
+
 test_done
-- 
1.6.0.1.149.ga4c44
Previous: Junio C HamanoNext: Junio C Hamano
Message 12 of 26 in “Towards a better merge resolution support”
  1. 00/12 Towards a better merge resolution supportJunio C Hamano, Aug 30, 2008
  2. 01/12 xdl_fill_merge_buffer(): separate out a too deeply nested functionJunio C Hamano, Aug 30, 2008
  3. 02/12 xdiff-merge: optionally show conflicts in "diff3 -m" styleJunio C Hamano, Aug 30, 2008
  4. 03/12 xmerge.c: minimum readability fixupsJunio C Hamano, Aug 30, 2008
  5. 04/12 xmerge.c: "diff3 -m" style clips merge reduction level to EAGER or lessJunio C Hamano, Aug 30, 2008
  6. 05/12 rerere.c: use symbolic constants to keep track of parsing statesJunio C Hamano, Aug 30, 2008
  7. 06/12 rerere: understand "diff3 -m" style conflicts with the originalJunio C Hamano, Aug 30, 2008
  8. 07/12 merge.conflictstyle: choose between "merge" and "diff3 -m" stylesJunio C Hamano, Aug 30, 2008
  9. 08/12 git-merge-recursive: learn to honor merge.conflictstyleJunio C Hamano, Aug 30, 2008
  10. 09/12 checkout: do not check out unmerged higher stages randomlyJunio C Hamano, Aug 30, 2008
  11. 10/12 checkout: allow ignoring unmerged paths when checking out of the indexJunio C Hamano, Aug 30, 2008
  12. 11/12 checkout --ours/--theirsJunio C Hamano, Aug 30, 2008
  13. 12/12 checkout -m: recreate merge when checking out of unmerged indexJunio C Hamano, Aug 30, 2008
  14. Johannes SchindelinAug 30, 2008
  15. Johannes SchindelinAug 30, 2008
  16. Johannes SchindelinAug 30, 2008
  17. Junio C HamanoAug 30, 2008
  18. Johannes SchindelinAug 30, 2008
  19. Johannes SchindelinAug 30, 2008
  20. Alex RiesenSep 1, 2008
  21. Alex RiesenSep 1, 2008
  22. Abhijit Menon-SenSep 1, 2008
  23. Thomas RastSep 1, 2008
  24. Junio C HamanoSep 1, 2008
  25. Alex RiesenSep 1, 2008
  26. Junio C HamanoSep 1, 2008

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.