checkout: do not check out unmerged higher stages randomly
During a conflicted merge when you have unmerged stages for a
path F in the index, if you said:
$ git checkout F
we rewrote F as many times as we have stages for it, and the
last one (typically "theirs") was left in the work tree, without
resolving the conflict.
This fixes it by noticing that a specified pathspec pattern
matches an unmerged path, and by erroring out.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
@ -76,6 +76,15 @@ static int read_tree_some(struct tree *tree, const char **pathspec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skip_same_name(struct cache_entry *ce, int pos)
|
||||
{
|
||||
while (++pos < active_nr &&
|
||||
!strcmp(active_cache[pos]->name, ce->name))
|
||||
; /* skip */
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
static int checkout_paths(struct tree *source_tree, const char **pathspec)
|
||||
{
|
||||
int pos;
|
||||
@ -107,6 +116,20 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec)
|
||||
if (report_path_error(ps_matched, pathspec, 0))
|
||||
return 1;
|
||||
|
||||
/* 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)) {
|
||||
if (!ce_stage(ce))
|
||||
continue;
|
||||
errs = 1;
|
||||
error("path '%s' is unmerged", ce->name);
|
||||
pos = skip_same_name(ce, pos) - 1;
|
||||
}
|
||||
}
|
||||
if (errs)
|
||||
return 1;
|
||||
|
||||
/* Now we are committed to check them out */
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.force = 1;
|
||||
@ -114,7 +137,11 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec)
|
||||
for (pos = 0; pos < active_nr; pos++) {
|
||||
struct cache_entry *ce = active_cache[pos];
|
||||
if (pathspec_match(pathspec, NULL, ce->name, 0)) {
|
||||
errs |= checkout_entry(ce, &state, NULL);
|
||||
if (!ce_stage(ce)) {
|
||||
errs |= checkout_entry(ce, &state, NULL);
|
||||
continue;
|
||||
}
|
||||
pos = skip_same_name(ce, pos) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user