Raw
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 Carl D. Worth
4 #
5
6 test_description='Test of the various options to git rm.'
7
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10
11 . ./test-lib.sh
12
13 # Setup some files to be removed, some with funny characters
14 test_expect_success 'Initialize test directory' '
15 touch -- foo bar baz "space embedded" -q &&
16 git add -- foo bar baz "space embedded" -q &&
17 git commit -m "add normal files"
18 '
19
20 test_expect_success FUNNYNAMES 'add files with funny names' '
21 touch -- "tab embedded" "newline${LF}embedded" &&
22 git add -- "tab embedded" "newline${LF}embedded" &&
23 git commit -m "add files with tabs and newlines"
24 '
25
26 test_expect_success 'Pre-check that foo exists and is in index before git rm foo' '
27 test_path_is_file foo &&
28 git ls-files --error-unmatch foo
29 '
30
31 test_expect_success 'Test that git rm foo succeeds' '
32 git rm --cached foo
33 '
34
35 test_expect_success 'Test that git rm --cached foo succeeds if the index matches the file' '
36 echo content >foo &&
37 git add foo &&
38 git rm --cached foo
39 '
40
41 test_expect_success 'Test that git rm --cached foo succeeds if the index matches the file' '
42 echo content >foo &&
43 git add foo &&
44 git commit -m foo &&
45 echo "other content" >foo &&
46 git rm --cached foo
47 '
48
49 test_expect_success 'Test that git rm --cached foo fails if the index matches neither the file nor HEAD' '
50 echo content >foo &&
51 git add foo &&
52 git commit -m foo --allow-empty &&
53 echo "other content" >foo &&
54 git add foo &&
55 echo "yet another content" >foo &&
56 test_must_fail git rm --cached foo
57 '
58
59 test_expect_success 'Test that git rm --cached -f foo works in case where --cached only did not' '
60 echo content >foo &&
61 git add foo &&
62 git commit -m foo --allow-empty &&
63 echo "other content" >foo &&
64 git add foo &&
65 echo "yet another content" >foo &&
66 git rm --cached -f foo
67 '
68
69 test_expect_success 'Post-check that foo exists but is not in index after git rm foo' '
70 test_path_is_file foo &&
71 test_must_fail git ls-files --error-unmatch foo
72 '
73
74 test_expect_success 'Pre-check that bar exists and is in index before "git rm bar"' '
75 test_path_is_file bar &&
76 git ls-files --error-unmatch bar
77 '
78
79 test_expect_success 'Test that "git rm bar" succeeds' '
80 git rm bar
81 '
82
83 test_expect_success 'Post-check that bar does not exist and is not in index after "git rm -f bar"' '
84 test_path_is_missing bar &&
85 test_must_fail git ls-files --error-unmatch bar
86 '
87
88 test_expect_success 'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' '
89 git rm -- -q
90 '
91
92 test_expect_success FUNNYNAMES 'Test that "git rm -f" succeeds with embedded space, tab, or newline characters.' '
93 git rm -f "space embedded" "tab embedded" "newline${LF}embedded"
94 '
95
96 test_expect_success SANITY 'Test that "git rm -f" fails if its rm fails' '
97 test_when_finished "chmod 775 ." &&
98 chmod a-w . &&
99 test_must_fail git rm -f baz
100 '
101
102 test_expect_success 'When the rm in "git rm -f" fails, it should not remove the file from the index' '
103 git ls-files --error-unmatch baz
104 '
105
106 test_expect_success 'Remove nonexistent file with --ignore-unmatch' '
107 git rm --ignore-unmatch nonexistent
108 '
109
110 test_expect_success '"rm" command printed' '
111 echo frotz >test-file &&
112 git add test-file &&
113 git commit -m "add file for rm test" &&
114 git rm test-file >rm-output.raw &&
115 grep "^rm " rm-output.raw >rm-output &&
116 test_line_count = 1 rm-output &&
117 rm -f test-file rm-output.raw rm-output &&
118 git commit -m "remove file from rm test"
119 '
120
121 test_expect_success '"rm" command suppressed with --quiet' '
122 echo frotz >test-file &&
123 git add test-file &&
124 git commit -m "add file for rm --quiet test" &&
125 git rm --quiet test-file >rm-output &&
126 test_must_be_empty rm-output &&
127 rm -f test-file rm-output &&
128 git commit -m "remove file from rm --quiet test"
129 '
130
131 # Now, failure cases.
132 test_expect_success 'Re-add foo and baz' '
133 git add foo baz &&
134 git ls-files --error-unmatch foo baz
135 '
136
137 test_expect_success 'Modify foo -- rm should refuse' '
138 echo >>foo &&
139 test_must_fail git rm foo baz &&
140 test_path_is_file foo &&
141 test_path_is_file baz &&
142 git ls-files --error-unmatch foo baz
143 '
144
145 test_expect_success 'Modified foo -- rm -f should work' '
146 git rm -f foo baz &&
147 test_path_is_missing foo &&
148 test_path_is_missing baz &&
149 test_must_fail git ls-files --error-unmatch foo &&
150 test_must_fail git ls-files --error-unmatch bar
151 '
152
153 test_expect_success 'Re-add foo and baz for HEAD tests' '
154 echo frotz >foo &&
155 git checkout HEAD -- baz &&
156 git add foo baz &&
157 git ls-files --error-unmatch foo baz
158 '
159
160 test_expect_success 'foo is different in index from HEAD -- rm should refuse' '
161 test_must_fail git rm foo baz &&
162 test_path_is_file foo &&
163 test_path_is_file baz &&
164 git ls-files --error-unmatch foo baz
165 '
166
167 test_expect_success 'but with -f it should work.' '
168 git rm -f foo baz &&
169 test_path_is_missing foo &&
170 test_path_is_missing baz &&
171 test_must_fail git ls-files --error-unmatch foo &&
172 test_must_fail git ls-files --error-unmatch baz
173 '
174
175 test_expect_success 'refuse to remove cached empty file with modifications' '
176 >empty &&
177 git add empty &&
178 echo content >empty &&
179 test_must_fail git rm --cached empty
180 '
181
182 test_expect_success 'remove intent-to-add file without --force' '
183 echo content >intent-to-add &&
184 git add -N intent-to-add &&
185 git rm --cached intent-to-add
186 '
187
188 test_expect_success 'Recursive test setup' '
189 mkdir -p frotz &&
190 echo qfwfq >frotz/nitfol &&
191 git add frotz &&
192 git commit -m "subdir test"
193 '
194
195 test_expect_success 'Recursive without -r fails' '
196 test_must_fail git rm frotz &&
197 test_path_is_dir frotz &&
198 test_path_is_file frotz/nitfol
199 '
200
201 test_expect_success 'Recursive with -r but dirty' '
202 echo qfwfq >>frotz/nitfol &&
203 test_must_fail git rm -r frotz &&
204 test_path_is_dir frotz &&
205 test_path_is_file frotz/nitfol
206 '
207
208 test_expect_success 'Recursive with -r -f' '
209 git rm -f -r frotz &&
210 test_path_is_missing frotz/nitfol &&
211 test_path_is_missing frotz
212 '
213
214 test_expect_success 'Remove nonexistent file returns nonzero exit status' '
215 test_must_fail git rm nonexistent
216 '
217
218 test_expect_success 'Call "rm" from outside the work tree' '
219 mkdir repo &&
220 (
221 cd repo &&
222 git init &&
223 echo something >somefile &&
224 git add somefile &&
225 git commit -m "add a file" &&
226 (
227 cd .. &&
228 git --git-dir=repo/.git --work-tree=repo rm somefile
229 ) &&
230 test_must_fail git ls-files --error-unmatch somefile
231 )
232 '
233
234 test_expect_success 'refresh index before checking if it is up-to-date' '
235 git reset --hard &&
236 test-tool chmtime -86400 frotz/nitfol &&
237 git rm frotz/nitfol &&
238 test_path_is_missing frotz/nitfol
239 '
240
241 choke_git_rm_setup() {
242 git reset -q --hard &&
243 test_when_finished "rm -f .git/index.lock && git reset -q --hard" &&
244 i=0 &&
245 hash=$(test_oid deadbeef) &&
246 while test $i -lt 12000
247 do
248 echo "100644 $hash 0 some-file-$i"
249 i=$(( $i + 1 ))
250 done | git update-index --index-info
251 }
252
253 test_expect_success 'choking "git rm" should not let it die with cruft (induce SIGPIPE)' '
254 choke_git_rm_setup &&
255 # git command is intentionally placed upstream of pipe to induce SIGPIPE
256 git rm -n "some-file-*" | : &&
257 test_path_is_missing .git/index.lock
258 '
259
260
261 test_expect_success !MINGW 'choking "git rm" should not let it die with cruft (induce and check SIGPIPE)' '
262 choke_git_rm_setup &&
263 OUT=$( ((trap "" PIPE && git rm -n "some-file-*" && echo 0 1>&3 || echo $? 1>&3) | :) 3>&1 ) &&
264 test_match_signal 13 "$OUT" &&
265 test_path_is_missing .git/index.lock
266 '
267
268 test_expect_success 'Resolving by removal is not a warning-worthy event' '
269 git reset -q --hard &&
270 test_when_finished "rm -f .git/index.lock msg && git reset -q --hard" &&
271 blob=$(echo blob | git hash-object -w --stdin) &&
272 printf "100644 $blob %d\tblob\n" 1 2 3 | git update-index --index-info &&
273 git rm blob >msg 2>&1 &&
274 test_grep ! "needs merge" msg &&
275 test_must_fail git ls-files -s --error-unmatch blob
276 '
277
278 test_expect_success 'rm removes subdirectories recursively' '
279 mkdir -p dir/subdir/subsubdir &&
280 echo content >dir/subdir/subsubdir/file &&
281 git add dir/subdir/subsubdir/file &&
282 git rm -f dir/subdir/subsubdir/file &&
283 test_path_is_missing dir
284 '
285
286 cat >expect <<EOF
287 M .gitmodules
288 D submod
289 EOF
290
291 cat >expect.modified <<EOF
292 M submod
293 EOF
294
295 cat >expect.modified_inside <<EOF
296 m submod
297 EOF
298
299 cat >expect.modified_untracked <<EOF
300 ? submod
301 EOF
302
303 cat >expect.cached <<EOF
304 D submod
305 EOF
306
307 cat >expect.both_deleted<<EOF
308 D .gitmodules
309 D submod
310 EOF
311
312 test_expect_success 'rm removes empty submodules from work tree' '
313 mkdir submod &&
314 hash=$(git rev-parse HEAD) &&
315 git update-index --add --cacheinfo 160000 "$hash" submod &&
316 git config -f .gitmodules submodule.sub.url ./. &&
317 git config -f .gitmodules submodule.sub.path submod &&
318 git submodule init &&
319 git add .gitmodules &&
320 git commit -m "add submodule" &&
321 git rm submod &&
322 test_path_is_missing submod &&
323 git status -s -uno --ignore-submodules=none >actual &&
324 test_cmp expect actual &&
325 test_must_fail git config -f .gitmodules submodule.sub.url &&
326 test_must_fail git config -f .gitmodules submodule.sub.path
327 '
328
329 test_expect_success 'rm removes removed submodule from index and .gitmodules' '
330 git reset --hard &&
331 git -c protocol.file.allow=always submodule update &&
332 rm -rf submod &&
333 git rm submod &&
334 git status -s -uno --ignore-submodules=none >actual &&
335 test_cmp expect actual &&
336 test_must_fail git config -f .gitmodules submodule.sub.url &&
337 test_must_fail git config -f .gitmodules submodule.sub.path
338 '
339
340 test_expect_success 'rm removes work tree of unmodified submodules' '
341 git reset --hard &&
342 git submodule update &&
343 git rm submod &&
344 test_path_is_missing submod &&
345 git status -s -uno --ignore-submodules=none >actual &&
346 test_cmp expect actual &&
347 test_must_fail git config -f .gitmodules submodule.sub.url &&
348 test_must_fail git config -f .gitmodules submodule.sub.path
349 '
350
351 test_expect_success 'rm removes a submodule with a trailing /' '
352 git reset --hard &&
353 git submodule update &&
354 git rm submod/ &&
355 test_path_is_missing submod &&
356 git status -s -uno --ignore-submodules=none >actual &&
357 test_cmp expect actual
358 '
359
360 test_expect_success 'rm fails when given a file with a trailing /' '
361 test_must_fail git rm empty/
362 '
363
364 test_expect_success 'rm succeeds when given a directory with a trailing /' '
365 git rm -r frotz/
366 '
367
368 test_expect_success 'rm of a populated submodule with different HEAD fails unless forced' '
369 git reset --hard &&
370 git submodule update &&
371 git -C submod checkout HEAD^ &&
372 test_must_fail git rm submod &&
373 test_path_is_dir submod &&
374 test_path_is_file submod/.git &&
375 git status -s -uno --ignore-submodules=none >actual &&
376 test_cmp expect.modified actual &&
377 git rm -f submod &&
378 test_path_is_missing submod &&
379 git status -s -uno --ignore-submodules=none >actual &&
380 test_cmp expect actual &&
381 test_must_fail git config -f .gitmodules submodule.sub.url &&
382 test_must_fail git config -f .gitmodules submodule.sub.path
383 '
384
385 test_expect_success 'rm --cached leaves work tree of populated submodules and .gitmodules alone' '
386 git reset --hard &&
387 git submodule update &&
388 git rm --cached submod &&
389 test_path_is_dir submod &&
390 test_path_is_file submod/.git &&
391 git status -s -uno >actual &&
392 test_cmp expect.cached actual &&
393 git config -f .gitmodules submodule.sub.url &&
394 git config -f .gitmodules submodule.sub.path
395 '
396
397 test_expect_success 'rm --dry-run does not touch the submodule or .gitmodules' '
398 git reset --hard &&
399 git submodule update &&
400 git rm -n submod &&
401 test_path_is_file submod/.git &&
402 git diff-index --exit-code HEAD
403 '
404
405 test_expect_success 'rm does not complain when no .gitmodules file is found' '
406 git reset --hard &&
407 git submodule update &&
408 git rm .gitmodules &&
409 git rm submod >actual 2>actual.err &&
410 test_must_be_empty actual.err &&
411 test_path_is_missing submod &&
412 test_path_is_missing submod/.git &&
413 git status -s -uno >actual &&
414 test_cmp expect.both_deleted actual
415 '
416
417 test_expect_success 'rm will error out on a modified .gitmodules file unless staged' '
418 git reset --hard &&
419 git submodule update &&
420 git config -f .gitmodules foo.bar true &&
421 test_must_fail git rm submod >actual 2>actual.err &&
422 test_file_not_empty actual.err &&
423 test_path_is_dir submod &&
424 test_path_is_file submod/.git &&
425 git diff-files --quiet -- submod &&
426 git add .gitmodules &&
427 git rm submod >actual 2>actual.err &&
428 test_must_be_empty actual.err &&
429 test_path_is_missing submod &&
430 test_path_is_missing submod/.git &&
431 git status -s -uno >actual &&
432 test_cmp expect actual
433 '
434 test_expect_success 'rm will not error out on .gitmodules file with zero stat data' '
435 git reset --hard &&
436 git submodule update &&
437 git read-tree HEAD &&
438 git rm submod &&
439 test_path_is_missing submod
440 '
441
442 test_expect_success 'rm issues a warning when section is not found in .gitmodules' '
443 git reset --hard &&
444 git submodule update &&
445 git config -f .gitmodules --remove-section submodule.sub &&
446 git add .gitmodules &&
447 echo "warning: Could not find section in .gitmodules where path=submod" >expect.err &&
448 git rm submod >actual 2>actual.err &&
449 test_cmp expect.err actual.err &&
450 test_path_is_missing submod &&
451 test_path_is_missing submod/.git &&
452 git status -s -uno >actual &&
453 test_cmp expect actual
454 '
455
456 test_expect_success 'rm of a populated submodule with modifications fails unless forced' '
457 git reset --hard &&
458 git submodule update &&
459 echo X >submod/empty &&
460 test_must_fail git rm submod &&
461 test_path_is_dir submod &&
462 test_path_is_file submod/.git &&
463 git status -s -uno --ignore-submodules=none >actual &&
464 test_cmp expect.modified_inside actual &&
465 git rm -f submod &&
466 test_path_is_missing submod &&
467 git status -s -uno --ignore-submodules=none >actual &&
468 test_cmp expect actual
469 '
470
471 test_expect_success 'rm of a populated submodule with untracked files fails unless forced' '
472 git reset --hard &&
473 git submodule update &&
474 echo X >submod/untracked &&
475 test_must_fail git rm submod &&
476 test_path_is_dir submod &&
477 test_path_is_file submod/.git &&
478 git status -s -uno --ignore-submodules=none >actual &&
479 test_cmp expect.modified_untracked actual &&
480 git rm -f submod &&
481 test_path_is_missing submod &&
482 git status -s -uno --ignore-submodules=none >actual &&
483 test_cmp expect actual
484 '
485
486 test_expect_success 'setup submodule conflict' '
487 git reset --hard &&
488 git submodule update &&
489 git checkout -b branch1 &&
490 echo 1 >nitfol &&
491 git add nitfol &&
492 git commit -m "added nitfol 1" &&
493 git checkout -b branch2 main &&
494 echo 2 >nitfol &&
495 git add nitfol &&
496 git commit -m "added nitfol 2" &&
497 git checkout -b conflict1 main &&
498 git -C submod fetch &&
499 git -C submod checkout branch1 &&
500 git add submod &&
501 git commit -m "submod 1" &&
502 git checkout -b conflict2 main &&
503 git -C submod checkout branch2 &&
504 git add submod &&
505 git commit -m "submod 2"
506 '
507
508 cat >expect.conflict <<EOF
509 UU submod
510 EOF
511
512 test_expect_success 'rm removes work tree of unmodified conflicted submodule' '
513 git checkout conflict1 &&
514 git reset --hard &&
515 git submodule update &&
516 test_must_fail git merge conflict2 &&
517 git rm submod &&
518 test_path_is_missing submod &&
519 git status -s -uno --ignore-submodules=none >actual &&
520 test_cmp expect actual
521 '
522
523 test_expect_success 'rm of a conflicted populated submodule with different HEAD fails unless forced' '
524 git checkout conflict1 &&
525 git reset --hard &&
526 git submodule update &&
527 git -C submod checkout HEAD^ &&
528 test_must_fail git merge conflict2 &&
529 test_must_fail git rm submod &&
530 test_path_is_dir submod &&
531 test_path_is_file submod/.git &&
532 git status -s -uno --ignore-submodules=none >actual &&
533 test_cmp expect.conflict actual &&
534 git rm -f submod &&
535 test_path_is_missing submod &&
536 git status -s -uno --ignore-submodules=none >actual &&
537 test_cmp expect actual &&
538 test_must_fail git config -f .gitmodules submodule.sub.url &&
539 test_must_fail git config -f .gitmodules submodule.sub.path
540 '
541
542 test_expect_success 'rm of a conflicted populated submodule with modifications fails unless forced' '
543 git checkout conflict1 &&
544 git reset --hard &&
545 git submodule update &&
546 echo X >submod/empty &&
547 test_must_fail git merge conflict2 &&
548 test_must_fail git rm submod &&
549 test_path_is_dir submod &&
550 test_path_is_file submod/.git &&
551 git status -s -uno --ignore-submodules=none >actual &&
552 test_cmp expect.conflict actual &&
553 git rm -f submod &&
554 test_path_is_missing submod &&
555 git status -s -uno --ignore-submodules=none >actual &&
556 test_cmp expect actual &&
557 test_must_fail git config -f .gitmodules submodule.sub.url &&
558 test_must_fail git config -f .gitmodules submodule.sub.path
559 '
560
561 test_expect_success 'rm of a conflicted populated submodule with untracked files fails unless forced' '
562 git checkout conflict1 &&
563 git reset --hard &&
564 git submodule update &&
565 echo X >submod/untracked &&
566 test_must_fail git merge conflict2 &&
567 test_must_fail git rm submod &&
568 test_path_is_dir submod &&
569 test_path_is_file submod/.git &&
570 git status -s -uno --ignore-submodules=none >actual &&
571 test_cmp expect.conflict actual &&
572 git rm -f submod &&
573 test_path_is_missing submod &&
574 git status -s -uno --ignore-submodules=none >actual &&
575 test_cmp expect actual
576 '
577
578 test_expect_success 'rm of a conflicted populated submodule with a .git directory fails even when forced' '
579 git checkout conflict1 &&
580 git reset --hard &&
581 git submodule update &&
582 (
583 cd submod &&
584 rm .git &&
585 cp -R ../.git/modules/sub .git &&
586 GIT_WORK_TREE=. git config --unset core.worktree
587 ) &&
588 test_must_fail git merge conflict2 &&
589 test_must_fail git rm submod &&
590 test_path_is_dir submod &&
591 test_path_is_dir submod/.git &&
592 git status -s -uno --ignore-submodules=none >actual &&
593 test_cmp expect.conflict actual &&
594 test_must_fail git rm -f submod &&
595 test_path_is_dir submod &&
596 test_path_is_dir submod/.git &&
597 git status -s -uno --ignore-submodules=none >actual &&
598 test_cmp expect.conflict actual &&
599 git merge --abort &&
600 rm -rf submod
601 '
602
603 test_expect_success 'rm of a conflicted unpopulated submodule succeeds' '
604 git checkout conflict1 &&
605 git reset --hard &&
606 test_must_fail git merge conflict2 &&
607 git rm submod &&
608 test_path_is_missing submod &&
609 git status -s -uno --ignore-submodules=none >actual &&
610 test_cmp expect actual
611 '
612
613 test_expect_success 'rm of a populated submodule with a .git directory migrates git dir' '
614 git checkout -f main &&
615 git reset --hard &&
616 git submodule update &&
617 (
618 cd submod &&
619 rm .git &&
620 cp -R ../.git/modules/sub .git &&
621 GIT_WORK_TREE=. git config --unset core.worktree &&
622 rm -r ../.git/modules/sub
623 ) &&
624 git rm submod 2>output.err &&
625 test_path_is_missing submod &&
626 test_path_is_missing submod/.git &&
627 git status -s -uno --ignore-submodules=none >actual &&
628 test_file_not_empty actual &&
629 test_grep Migrating output.err
630 '
631
632 cat >expect.deepmodified <<EOF
633 M submod/subsubmod
634 EOF
635
636 test_expect_success 'setup subsubmodule' '
637 test_config_global protocol.file.allow always &&
638 git reset --hard &&
639 git submodule update &&
640 (
641 cd submod &&
642 hash=$(git rev-parse HEAD) &&
643 git update-index --add --cacheinfo 160000 "$hash" subsubmod &&
644 git config -f .gitmodules submodule.sub.url ../. &&
645 git config -f .gitmodules submodule.sub.path subsubmod &&
646 git submodule init &&
647 git add .gitmodules &&
648 git commit -m "add subsubmodule" &&
649 git submodule update subsubmod
650 ) &&
651 git commit -a -m "added deep submodule"
652 '
653
654 test_expect_success 'rm recursively removes work tree of unmodified submodules' '
655 git rm submod &&
656 test_path_is_missing submod &&
657 git status -s -uno --ignore-submodules=none >actual &&
658 test_cmp expect actual
659 '
660
661 test_expect_success 'rm of a populated nested submodule with different nested HEAD fails unless forced' '
662 git reset --hard &&
663 git submodule update --recursive &&
664 git -C submod/subsubmod checkout HEAD^ &&
665 test_must_fail git rm submod &&
666 test_path_is_dir submod &&
667 test_path_is_file submod/.git &&
668 git status -s -uno --ignore-submodules=none >actual &&
669 test_cmp expect.modified_inside actual &&
670 git rm -f submod &&
671 test_path_is_missing submod &&
672 git status -s -uno --ignore-submodules=none >actual &&
673 test_cmp expect actual
674 '
675
676 test_expect_success 'rm of a populated nested submodule with nested modifications fails unless forced' '
677 git reset --hard &&
678 git submodule update --recursive &&
679 echo X >submod/subsubmod/empty &&
680 test_must_fail git rm submod &&
681 test_path_is_dir submod &&
682 test_path_is_file submod/.git &&
683 git status -s -uno --ignore-submodules=none >actual &&
684 test_cmp expect.modified_inside actual &&
685 git rm -f submod &&
686 test_path_is_missing submod &&
687 git status -s -uno --ignore-submodules=none >actual &&
688 test_cmp expect actual
689 '
690
691 test_expect_success 'rm of a populated nested submodule with nested untracked files fails unless forced' '
692 git reset --hard &&
693 git submodule update --recursive &&
694 echo X >submod/subsubmod/untracked &&
695 test_must_fail git rm submod &&
696 test_path_is_dir submod &&
697 test_path_is_file submod/.git &&
698 git status -s -uno --ignore-submodules=none >actual &&
699 test_cmp expect.modified_untracked actual &&
700 git rm -f submod &&
701 test_path_is_missing submod &&
702 git status -s -uno --ignore-submodules=none >actual &&
703 test_cmp expect actual
704 '
705
706 test_expect_success "rm absorbs submodule's nested .git directory" '
707 git reset --hard &&
708 git submodule update --recursive &&
709 (
710 cd submod/subsubmod &&
711 rm .git &&
712 mv ../../.git/modules/sub/modules/sub .git &&
713 GIT_WORK_TREE=. git config --unset core.worktree
714 ) &&
715 git rm submod 2>output.err &&
716 test_path_is_missing submod &&
717 test_path_is_missing submod/subsubmod/.git &&
718 git status -s -uno --ignore-submodules=none >actual &&
719 test_file_not_empty actual &&
720 test_grep Migrating output.err
721 '
722
723 test_expect_success 'checking out a commit after submodule removal needs manual updates' '
724 git commit -m "submodule removal" submod .gitmodules &&
725 git checkout HEAD^ &&
726 git submodule update &&
727 git checkout -q HEAD^ &&
728 git checkout -q main 2>actual &&
729 test_grep "^warning: unable to rmdir '\''submod'\'':" actual &&
730 git status -s submod >actual &&
731 echo "?? submod/" >expected &&
732 test_cmp expected actual &&
733 rm -rf submod &&
734 git status -s -uno --ignore-submodules=none >actual &&
735 test_must_be_empty actual
736 '
737
738 test_expect_success 'rm of d/f when d has become a non-directory' '
739 rm -rf d &&
740 mkdir d &&
741 >d/f &&
742 git add d &&
743 rm -rf d &&
744 >d &&
745 git rm d/f &&
746 test_must_fail git rev-parse --verify :d/f &&
747 test_path_is_file d
748 '
749
750 test_expect_success SYMLINKS 'rm of d/f when d has become a dangling symlink' '
751 rm -rf d &&
752 mkdir d &&
753 >d/f &&
754 git add d &&
755 rm -rf d &&
756 ln -s nonexistent d &&
757 git rm d/f &&
758 test_must_fail git rev-parse --verify :d/f &&
759 test -h d &&
760 test_path_is_missing d
761 '
762
763 test_expect_success 'rm of file when it has become a directory' '
764 rm -rf d &&
765 >d &&
766 git add d &&
767 rm -f d &&
768 mkdir d &&
769 >d/f &&
770 test_must_fail git rm d &&
771 git rev-parse --verify :d &&
772 test_path_is_file d/f
773 '
774
775 test_expect_success SYMLINKS 'rm across a symlinked leading path (no index)' '
776 rm -rf d e &&
777 mkdir e &&
778 echo content >e/f &&
779 ln -s e d &&
780 git add -A e d &&
781 git commit -m "symlink d to e, e/f exists" &&
782 test_must_fail git rm d/f &&
783 git rev-parse --verify :d &&
784 git rev-parse --verify :e/f &&
785 test -h d &&
786 test_path_is_file e/f
787 '
788
789 test_expect_failure SYMLINKS 'rm across a symlinked leading path (w/ index)' '
790 rm -rf d e &&
791 mkdir d &&
792 echo content >d/f &&
793 git add -A e d &&
794 git commit -m "d/f exists" &&
795 mv d e &&
796 ln -s e d &&
797 test_must_fail git rm d/f &&
798 git rev-parse --verify :d/f &&
799 test -h d &&
800 test_path_is_file e/f
801 '
802
803 test_expect_success 'setup for testing rm messages' '
804 >bar.txt &&
805 >foo.txt &&
806 git add bar.txt foo.txt
807 '
808
809 test_expect_success 'rm files with different staged content' '
810 cat >expect <<-\EOF &&
811 error: the following files have staged content different from both the
812 file and the HEAD:
813 bar.txt
814 foo.txt
815 (use -f to force removal)
816 EOF
817 echo content1 >foo.txt &&
818 echo content1 >bar.txt &&
819 test_must_fail git rm foo.txt bar.txt 2>actual &&
820 test_cmp expect actual
821 '
822
823 test_expect_success 'rm files with different staged content without hints' '
824 cat >expect <<-\EOF &&
825 error: the following files have staged content different from both the
826 file and the HEAD:
827 bar.txt
828 foo.txt
829 EOF
830 echo content2 >foo.txt &&
831 echo content2 >bar.txt &&
832 test_must_fail git -c advice.rmhints=false rm foo.txt bar.txt 2>actual &&
833 test_cmp expect actual
834 '
835
836 test_expect_success 'rm file with local modification' '
837 cat >expect <<-\EOF &&
838 error: the following file has local modifications:
839 foo.txt
840 (use --cached to keep the file, or -f to force removal)
841 EOF
842 git commit -m "testing rm 3" &&
843 echo content3 >foo.txt &&
844 test_must_fail git rm foo.txt 2>actual &&
845 test_cmp expect actual
846 '
847
848 test_expect_success 'rm file with local modification without hints' '
849 cat >expect <<-\EOF &&
850 error: the following file has local modifications:
851 bar.txt
852 EOF
853 echo content4 >bar.txt &&
854 test_must_fail git -c advice.rmhints=false rm bar.txt 2>actual &&
855 test_cmp expect actual
856 '
857
858 test_expect_success 'rm file with changes in the index' '
859 cat >expect <<-\EOF &&
860 error: the following file has changes staged in the index:
861 foo.txt
862 (use --cached to keep the file, or -f to force removal)
863 EOF
864 git reset --hard &&
865 echo content5 >foo.txt &&
866 git add foo.txt &&
867 test_must_fail git rm foo.txt 2>actual &&
868 test_cmp expect actual
869 '
870
871 test_expect_success 'rm file with changes in the index without hints' '
872 cat >expect <<-\EOF &&
873 error: the following file has changes staged in the index:
874 foo.txt
875 EOF
876 test_must_fail git -c advice.rmhints=false rm foo.txt 2>actual &&
877 test_cmp expect actual
878 '
879
880 test_expect_success 'rm files with two different errors' '
881 cat >expect <<-\EOF &&
882 error: the following file has staged content different from both the
883 file and the HEAD:
884 foo1.txt
885 (use -f to force removal)
886 error: the following file has changes staged in the index:
887 bar1.txt
888 (use --cached to keep the file, or -f to force removal)
889 EOF
890 echo content >foo1.txt &&
891 git add foo1.txt &&
892 echo content6 >foo1.txt &&
893 echo content6 >bar1.txt &&
894 git add bar1.txt &&
895 test_must_fail git rm bar1.txt foo1.txt 2>actual &&
896 test_cmp expect actual
897 '
898
899 test_expect_success 'rm empty string should fail' '
900 test_must_fail git rm -rf ""
901 '
902
903 test_done