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>
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user