mirror of
https://github.com/git/git
synced 2024-08-24 18:26:02 +00:00
![Varun Naik](/assets/img/avatar_default.png)
It is possible to delete a committed file from the index and then add it as intent-to-add. After `git checkout HEAD <pathspec>`, the file should be identical in the index and HEAD. The command already works correctly if the file has contents in HEAD. This patch provides the desired behavior even when the file is empty in HEAD. `git checkout HEAD <pathspec>` calls tree.c:read_tree_1(), with fn pointing to checkout.c:update_some(). update_some() creates a new cache entry but discards it when its mode and oid match those of the old entry. A cache entry for an ita file and a cache entry for an empty file have the same oid. Therefore, an empty deleted ita file previously passed both of these checks, and the new entry was discarded, so the file remained unchanged in the index. After this fix, if the file is marked as ita in the cache, then we avoid discarding the new entry and add the new entry to the cache instead. This change should not affect newly added ita files. For those, inside tree.c:read_tree_1(), tree_entry_interesting() returns entry_not_interesting, so fn is never called. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Varun Naik <vcnaik94@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
93 lines
2.4 KiB
Bash
Executable file
93 lines
2.4 KiB
Bash
Executable file
#!/bin/sh
|
|
|
|
test_description='checkout $tree -- $paths'
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success setup '
|
|
mkdir dir &&
|
|
>dir/master &&
|
|
echo common >dir/common &&
|
|
git add dir/master dir/common &&
|
|
test_tick && git commit -m "master has dir/master" &&
|
|
git checkout -b next &&
|
|
git mv dir/master dir/next0 &&
|
|
echo next >dir/next1 &&
|
|
git add dir &&
|
|
test_tick && git commit -m "next has dir/next but not dir/master"
|
|
'
|
|
|
|
test_expect_success 'checking out paths out of a tree does not clobber unrelated paths' '
|
|
git checkout next &&
|
|
git reset --hard &&
|
|
rm dir/next0 &&
|
|
cat dir/common >expect.common &&
|
|
echo modified >expect.next1 &&
|
|
cat expect.next1 >dir/next1 &&
|
|
echo untracked >expect.next2 &&
|
|
cat expect.next2 >dir/next2 &&
|
|
|
|
git checkout master dir &&
|
|
|
|
test_cmp expect.common dir/common &&
|
|
test_path_is_file dir/master &&
|
|
git diff --exit-code master dir/master &&
|
|
|
|
test_path_is_missing dir/next0 &&
|
|
test_cmp expect.next1 dir/next1 &&
|
|
test_path_is_file dir/next2 &&
|
|
test_must_fail git ls-files --error-unmatch dir/next2 &&
|
|
test_cmp expect.next2 dir/next2
|
|
'
|
|
|
|
test_expect_success 'do not touch unmerged entries matching $path but not in $tree' '
|
|
git checkout next &&
|
|
git reset --hard &&
|
|
|
|
cat dir/common >expect.common &&
|
|
EMPTY_SHA1=$(git hash-object -w --stdin </dev/null) &&
|
|
git rm dir/next0 &&
|
|
cat >expect.next0 <<-EOF &&
|
|
100644 $EMPTY_SHA1 1 dir/next0
|
|
100644 $EMPTY_SHA1 2 dir/next0
|
|
EOF
|
|
git update-index --index-info <expect.next0 &&
|
|
|
|
git checkout master dir &&
|
|
|
|
test_cmp expect.common dir/common &&
|
|
test_path_is_file dir/master &&
|
|
git diff --exit-code master dir/master &&
|
|
git ls-files -s dir/next0 >actual.next0 &&
|
|
test_cmp expect.next0 actual.next0
|
|
'
|
|
|
|
test_expect_success 'do not touch files that are already up-to-date' '
|
|
git reset --hard &&
|
|
echo one >file1 &&
|
|
echo two >file2 &&
|
|
git add file1 file2 &&
|
|
git commit -m base &&
|
|
echo modified >file1 &&
|
|
test-tool chmtime =1000000000 file2 &&
|
|
git update-index -q --refresh &&
|
|
git checkout HEAD -- file1 file2 &&
|
|
echo one >expect &&
|
|
test_cmp expect file1 &&
|
|
echo "1000000000" >expect &&
|
|
test-tool chmtime --get file2 >actual &&
|
|
test_cmp expect actual
|
|
'
|
|
|
|
test_expect_success 'checkout HEAD adds deleted intent-to-add file back to index' '
|
|
echo "nonempty" >nonempty &&
|
|
>empty &&
|
|
git add nonempty empty &&
|
|
git commit -m "create files to be deleted" &&
|
|
git rm --cached nonempty empty &&
|
|
git add -N nonempty empty &&
|
|
git checkout HEAD nonempty empty &&
|
|
git diff --cached --exit-code
|
|
'
|
|
|
|
test_done
|