Skip to content

Commit 4582fa5

Browse files
dschoGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
stash: handle staged changes in skip-worktree files correctly
When calling `git stash` while changes were staged for files that are marked with the `skip-worktree` bit (e.g. files that are excluded in a sparse checkout), the files are recorded as _deleted_ instead. The reason is that `git stash` tries to construct the tree reflecting the worktree essentially by copying the index to a temporary one and then updating the files from the worktree. Crucially, it calls `git diff-index` to update also those files that are in the HEAD but have been unstaged in the index. However, when the temporary index is updated via `git update-index --add --remove`, skip-worktree entries mark the files as deleted by mistake. Let's use the newly-introduced `--ignore-skip-worktree-entries` option of `git update-index` to prevent exactly this from happening. Note that the regression test case deliberately avoids replicating the scenario described above and instead tries to recreate just the symptom. Reported by Dan Thompson. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 40c28df commit 4582fa5

File tree

3 files changed

+16
-3
lines changed

3 files changed

+16
-3
lines changed

builtin/stash.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,8 +1088,9 @@ static int stash_working_tree(struct stash_info *info, const struct pathspec *ps
10881088
}
10891089

10901090
cp_upd_index.git_cmd = 1;
1091-
argv_array_pushl(&cp_upd_index.args, "update-index", "-z", "--add",
1092-
"--remove", "--stdin", NULL);
1091+
argv_array_pushl(&cp_upd_index.args, "update-index",
1092+
"--ignore-skip-worktree-entries",
1093+
"-z", "--add", "--remove", "--stdin", NULL);
10931094
argv_array_pushf(&cp_upd_index.env_array, "GIT_INDEX_FILE=%s",
10941095
stash_index_path.buf);
10951096

git-legacy-stash.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ create_stash () {
193193
GIT_INDEX_FILE="$TMPindex" &&
194194
export GIT_INDEX_FILE &&
195195
git diff-index --name-only -z HEAD -- "$@" >"$TMP-stagenames" &&
196-
git update-index -z --add --remove --stdin <"$TMP-stagenames" &&
196+
git update-index --ignore-skip-worktree-entries \
197+
-z --add --remove --stdin <"$TMP-stagenames" &&
197198
git write-tree &&
198199
rm -f "$TMPindex"
199200
) ) ||

t/t3903-stash.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,4 +1269,15 @@ test_expect_success 'stash apply should succeed with unmodified file' '
12691269
git stash apply
12701270
'
12711271

1272+
test_expect_success 'stash handles skip-worktree entries nicely' '
1273+
test_commit A &&
1274+
echo changed >A.t &&
1275+
git add A.t &&
1276+
git update-index --skip-worktree A.t &&
1277+
rm A.t &&
1278+
git stash &&
1279+
1280+
git rev-parse --verify refs/stash:A.t
1281+
'
1282+
12721283
test_done

0 commit comments

Comments
 (0)