Skip to content

Commit bfda204

Browse files
rscharfegitster
authored andcommitted
checkout, restore: make pathspec recursive
The pathspec given to git checkout and git restore is used with both tree_entry_interesting (via read_tree_recursive) and match_pathspec (via ce_path_match). The latter effectively only supports recursive matching regardless of the value of the pathspec flag "recursive", which is unset here. That causes different match results for pathspecs with wildcards, and can lead checkout and restore in no-overlay mode to remove entries instead of modifying them. Enable recursive matching for both checkout and restore to make matching consistent. Setting the flag in checkout_main() technically also affects git switch, but since that command doesn't accept pathspecs at all this has no actual consequence. Reported-by: Sergii Shkarnikov <[email protected]> Initial-test-by: Sergii Shkarnikov <[email protected]> Helped-by: Jeff King <[email protected]> Signed-off-by: René Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 135365d commit bfda204

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

builtin/checkout.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1660,6 +1660,8 @@ static int checkout_main(int argc, const char **argv, const char *prefix,
16601660
die(_("--pathspec-file-nul requires --pathspec-from-file"));
16611661
}
16621662

1663+
opts->pathspec.recursive = 1;
1664+
16631665
if (opts->pathspec.nr) {
16641666
if (1 < !!opts->writeout_stage + !!opts->force + !!opts->merge)
16651667
die(_("git checkout: --ours/--theirs, --force and --merge are incompatible when\n"

t/t2025-checkout-no-overlay.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,16 @@ test_expect_success '--no-overlay --theirs with D/F conflict deletes file' '
4444
test_path_is_missing file1
4545
'
4646

47+
test_expect_success 'wildcard pathspec matches file in subdirectory' '
48+
git reset --hard &&
49+
mkdir subdir &&
50+
test_commit file3-1 subdir/file3 &&
51+
test_commit file3-2 subdir/file3 &&
52+
53+
git checkout --no-overlay file3-1 "*file3" &&
54+
echo file3-1 >expect &&
55+
test_path_is_file subdir/file3 &&
56+
test_cmp expect subdir/file3
57+
'
58+
4759
test_done

t/t2072-restore-pathspec-file.sh

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,21 @@ test_tick
99
test_expect_success setup '
1010
test_commit file0 &&
1111
12+
mkdir dir1 &&
13+
echo 1 >dir1/file &&
1214
echo 1 >fileA.t &&
1315
echo 1 >fileB.t &&
1416
echo 1 >fileC.t &&
1517
echo 1 >fileD.t &&
16-
git add fileA.t fileB.t fileC.t fileD.t &&
18+
git add dir1 fileA.t fileB.t fileC.t fileD.t &&
1719
git commit -m "files 1" &&
1820
21+
echo 2 >dir1/file &&
1922
echo 2 >fileA.t &&
2023
echo 2 >fileB.t &&
2124
echo 2 >fileC.t &&
2225
echo 2 >fileD.t &&
23-
git add fileA.t fileB.t fileC.t fileD.t &&
26+
git add dir1 fileA.t fileB.t fileC.t fileD.t &&
2427
git commit -m "files 2" &&
2528
2629
git tag checkpoint
@@ -31,7 +34,7 @@ restore_checkpoint () {
3134
}
3235

3336
verify_expect () {
34-
git status --porcelain --untracked-files=no -- fileA.t fileB.t fileC.t fileD.t >actual &&
37+
git status --porcelain --untracked-files=no -- dir1 fileA.t fileB.t fileC.t fileD.t >actual &&
3538
test_cmp expect actual
3639
}
3740

@@ -136,4 +139,14 @@ test_expect_success 'only touches what was listed' '
136139
verify_expect
137140
'
138141

142+
test_expect_success 'wildcard pathspec matches file in subdirectory' '
143+
restore_checkpoint &&
144+
145+
echo "*file" | git restore --pathspec-from-file=- --source=HEAD^1 &&
146+
cat >expect <<-\EOF &&
147+
M dir1/file
148+
EOF
149+
verify_expect
150+
'
151+
139152
test_done

0 commit comments

Comments
 (0)