summaryrefslogtreecommitdiff
path: root/builtin-checkout.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2008-08-30 14:48:18 (GMT)
committerJunio C Hamano <gitster@pobox.com>2008-08-31 02:28:45 (GMT)
commit38901a48375952ab6c02f22bddfa19ac2bec2c36 (patch)
treee92bde1bc110e1456cd9980bce0ea80f49dae902 /builtin-checkout.c
parentdb9410990ee41f2b253763621c0023c782ec86e2 (diff)
downloadgit-38901a48375952ab6c02f22bddfa19ac2bec2c36.zip
git-38901a48375952ab6c02f22bddfa19ac2bec2c36.tar.gz
git-38901a48375952ab6c02f22bddfa19ac2bec2c36.tar.bz2
checkout --ours/--theirs: allow checking out one side of a conflicting merge
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>
Diffstat (limited to 'builtin-checkout.c')
-rw-r--r--builtin-checkout.c39
1 files changed, 38 insertions, 1 deletions
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 1303f3b..16bfbb6 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,7 +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));
@@ -136,6 +163,8 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
continue;
if (opts->force) {
warning("path '%s' is unmerged", ce->name);
+ } else if (stage) {
+ errs |= check_stage(stage, ce, pos);
} else {
errs = 1;
error("path '%s' is unmerged", ce->name);
@@ -157,6 +186,8 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
errs |= checkout_entry(ce, &state, NULL);
continue;
}
+ if (stage)
+ errs |= checkout_stage(stage, ce, pos, &state);
pos = skip_same_name(ce, pos) - 1;
}
}
@@ -458,6 +489,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(),
@@ -573,6 +608,8 @@ no_reference:
if (new.name && !new.commit) {
die("Cannot switch branch to a non-commit.");
}
+ if (opts.writeout_stage)
+ die("--ours/--theirs is incompatible with switching branches.");
return switch_branches(&opts, &new);
}