mirror of
https://github.com/git/git.git
synced 2024-11-24 02:17:02 +08:00
reset --hard/read-tree --reset -u: remove unmerged new paths
When aborting a failed merge that has brought in a new path using "git reset --hard" or "git read-tree --reset -u", we used to first forget about the new path (via read_cache_unmerged) and then matched the working tree to what is recorded in the index, thus ending up leaving the new path in the work tree. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
c82efafcfa
commit
d1a43f2aa4
31
read-cache.c
31
read-cache.c
@ -1460,23 +1460,28 @@ int write_index(const struct index_state *istate, int newfd)
|
||||
int read_index_unmerged(struct index_state *istate)
|
||||
{
|
||||
int i;
|
||||
struct cache_entry **dst;
|
||||
struct cache_entry *last = NULL;
|
||||
int unmerged = 0;
|
||||
|
||||
read_index(istate);
|
||||
dst = istate->cache;
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
struct cache_entry *ce = istate->cache[i];
|
||||
if (ce_stage(ce)) {
|
||||
remove_name_hash(ce);
|
||||
if (last && !strcmp(ce->name, last->name))
|
||||
continue;
|
||||
cache_tree_invalidate_path(istate->cache_tree, ce->name);
|
||||
last = ce;
|
||||
struct cache_entry *new_ce;
|
||||
int size, len;
|
||||
|
||||
if (!ce_stage(ce))
|
||||
continue;
|
||||
}
|
||||
*dst++ = ce;
|
||||
unmerged = 1;
|
||||
len = strlen(ce->name);
|
||||
size = cache_entry_size(len);
|
||||
new_ce = xcalloc(1, size);
|
||||
hashcpy(new_ce->sha1, ce->sha1);
|
||||
memcpy(new_ce->name, ce->name, len);
|
||||
new_ce->ce_flags = create_ce_flags(len, 0);
|
||||
new_ce->ce_mode = ce->ce_mode;
|
||||
if (add_index_entry(istate, new_ce, 0))
|
||||
return error("%s: cannot drop to stage #0",
|
||||
ce->name);
|
||||
i = index_name_pos(istate, new_ce->name, len);
|
||||
}
|
||||
istate->cache_nr = dst - istate->cache;
|
||||
return !!last;
|
||||
return unmerged;
|
||||
}
|
||||
|
@ -27,4 +27,64 @@ test_expect_success 'reset should work' '
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'reset should remove remnants from a failed merge' '
|
||||
git read-tree --reset -u HEAD &&
|
||||
git ls-files -s >expect &&
|
||||
sha1=$(git rev-parse :new) &&
|
||||
(
|
||||
echo "100644 $sha1 1 old"
|
||||
echo "100644 $sha1 3 old"
|
||||
) | git update-index --index-info &&
|
||||
>old &&
|
||||
git ls-files -s &&
|
||||
git read-tree --reset -u HEAD &&
|
||||
git ls-files -s >actual &&
|
||||
! test -f old
|
||||
'
|
||||
|
||||
test_expect_success 'Porcelain reset should remove remnants too' '
|
||||
git read-tree --reset -u HEAD &&
|
||||
git ls-files -s >expect &&
|
||||
sha1=$(git rev-parse :new) &&
|
||||
(
|
||||
echo "100644 $sha1 1 old"
|
||||
echo "100644 $sha1 3 old"
|
||||
) | git update-index --index-info &&
|
||||
>old &&
|
||||
git ls-files -s &&
|
||||
git reset --hard &&
|
||||
git ls-files -s >actual &&
|
||||
! test -f old
|
||||
'
|
||||
|
||||
test_expect_success 'Porcelain checkout -f should remove remnants too' '
|
||||
git read-tree --reset -u HEAD &&
|
||||
git ls-files -s >expect &&
|
||||
sha1=$(git rev-parse :new) &&
|
||||
(
|
||||
echo "100644 $sha1 1 old"
|
||||
echo "100644 $sha1 3 old"
|
||||
) | git update-index --index-info &&
|
||||
>old &&
|
||||
git ls-files -s &&
|
||||
git checkout -f &&
|
||||
git ls-files -s >actual &&
|
||||
! test -f old
|
||||
'
|
||||
|
||||
test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' '
|
||||
git read-tree --reset -u HEAD &&
|
||||
git ls-files -s >expect &&
|
||||
sha1=$(git rev-parse :new) &&
|
||||
(
|
||||
echo "100644 $sha1 1 old"
|
||||
echo "100644 $sha1 3 old"
|
||||
) | git update-index --index-info &&
|
||||
>old &&
|
||||
git ls-files -s &&
|
||||
git checkout -f HEAD &&
|
||||
git ls-files -s >actual &&
|
||||
! test -f old
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user