summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 53d1589)
raw | patch | inline | side by side (parent: 53d1589)
author | Junio C Hamano <gitster@pobox.com> | |
Fri, 29 Aug 2008 20:40:36 +0000 (13:40 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Sat, 30 Aug 2008 23:46:25 +0000 (16:46 -0700) |
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>
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>
builtin-checkout.c | patch | blob | history | |
t/t7201-co.sh | patch | blob | history |
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 411cc513c65ba854221ad52dd6aeaaac7d213c9d..854401099410d5eeb590caf2ef56d4679ba77926 100644 (file)
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
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;
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;
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;
}
}
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 9ad5d635a2881c920fff8e524aea0ed931f68e6c..83a366f1e7dcbe1d1678cadd87b9862713e82b97 100755 (executable)
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
test_must_fail git checkout --track -b track'
+test_expect_success 'checkout an unmerged path should fail' '
+ 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 &&
+ cat sample >fild &&
+ cat sample >file &&
+ cat sample >filf &&
+ test_must_fail git checkout fild file filf &&
+ test_cmp sample fild &&
+ test_cmp sample filf &&
+ test_cmp sample file
+'
+
test_done