Skip to content

Commit 909d5b6

Browse files
committed
Merge branch 'vd/mv-refresh-stat'
"git mv" failed to refresh the cached stat information for the entry it moved. * vd/mv-refresh-stat: mv: refresh stat info for moved entry
2 parents 439c1e6 + b7f9130 commit 909d5b6

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

read-cache.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache
134134

135135
void rename_index_entry_at(struct index_state *istate, int nr, const char *new_name)
136136
{
137-
struct cache_entry *old_entry = istate->cache[nr], *new_entry;
137+
struct cache_entry *old_entry = istate->cache[nr], *new_entry, *refreshed;
138138
int namelen = strlen(new_name);
139139

140140
new_entry = make_empty_cache_entry(istate, namelen);
@@ -147,7 +147,20 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
147147
cache_tree_invalidate_path(istate, old_entry->name);
148148
untracked_cache_remove_from_index(istate, old_entry->name);
149149
remove_index_entry_at(istate, nr);
150-
add_index_entry(istate, new_entry, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
150+
151+
/*
152+
* Refresh the new index entry. Using 'refresh_cache_entry' ensures
153+
* we only update stat info if the entry is otherwise up-to-date (i.e.,
154+
* the contents/mode haven't changed). This ensures that we reflect the
155+
* 'ctime' of the rename in the index without (incorrectly) updating
156+
* the cached stat info to reflect unstaged changes on disk.
157+
*/
158+
refreshed = refresh_cache_entry(istate, new_entry, CE_MATCH_REFRESH);
159+
if (refreshed && refreshed != new_entry) {
160+
add_index_entry(istate, refreshed, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
161+
discard_cache_entry(new_entry);
162+
} else
163+
add_index_entry(istate, new_entry, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
151164
}
152165

153166
void fill_stat_data(struct stat_data *sd, struct stat *st)

t/t7001-mv.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,25 @@ test_description='git mv in subdirs'
44
. ./test-lib.sh
55
. "$TEST_DIRECTORY"/lib-diff-data.sh
66

7+
test_expect_success 'mv -f refreshes updated index entry' '
8+
echo test >bar &&
9+
git add bar &&
10+
git commit -m test &&
11+
12+
echo foo >foo &&
13+
git add foo &&
14+
15+
# Wait one second to ensure ctime of rename will differ from original
16+
# file creation ctime.
17+
sleep 1 &&
18+
git mv -f foo bar &&
19+
git reset --merge HEAD &&
20+
21+
# Verify the index has been reset
22+
git diff-files >out &&
23+
test_must_be_empty out
24+
'
25+
726
test_expect_success 'prepare reference tree' '
827
mkdir path0 path1 &&
928
COPYING_test_data >path0/COPYING &&

0 commit comments

Comments
 (0)