Git fork
1#!/bin/sh
2#
3# Copyright (c) 2006 Carl D. Worth
4#
5
6test_description='Test of the various options to git rm.'
7
8GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
9export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10
11. ./test-lib.sh
12
13# Setup some files to be removed, some with funny characters
14test_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
20test_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
26test_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
31test_expect_success 'Test that git rm foo succeeds' '
32 git rm --cached foo
33'
34
35test_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
41test_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
49test_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
59test_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
69test_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
74test_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
79test_expect_success 'Test that "git rm bar" succeeds' '
80 git rm bar
81'
82
83test_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
88test_expect_success 'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' '
89 git rm -- -q
90'
91
92test_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
96test_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
102test_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
106test_expect_success 'Remove nonexistent file with --ignore-unmatch' '
107 git rm --ignore-unmatch nonexistent
108'
109
110test_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
121test_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.
132test_expect_success 'Re-add foo and baz' '
133 git add foo baz &&
134 git ls-files --error-unmatch foo baz
135'
136
137test_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
145test_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
153test_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
160test_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
167test_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
175test_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
182test_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
188test_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
195test_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
201test_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
208test_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
214test_expect_success 'Remove nonexistent file returns nonzero exit status' '
215 test_must_fail git rm nonexistent
216'
217
218test_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
234test_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
241choke_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
253test_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
261test_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 $? 1>&3) | :) 3>&1 ) &&
264 test_match_signal 13 "$OUT" &&
265 test_path_is_missing .git/index.lock
266'
267
268test_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
278test_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
286cat >expect <<EOF
287M .gitmodules
288D submod
289EOF
290
291cat >expect.modified <<EOF
292 M submod
293EOF
294
295cat >expect.modified_inside <<EOF
296 m submod
297EOF
298
299cat >expect.modified_untracked <<EOF
300 ? submod
301EOF
302
303cat >expect.cached <<EOF
304D submod
305EOF
306
307cat >expect.both_deleted<<EOF
308D .gitmodules
309D submod
310EOF
311
312test_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
329test_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
340test_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
351test_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
360test_expect_success 'rm fails when given a file with a trailing /' '
361 test_must_fail git rm empty/
362'
363
364test_expect_success 'rm succeeds when given a directory with a trailing /' '
365 git rm -r frotz/
366'
367
368test_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
385test_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
397test_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
405test_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
417test_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'
434test_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
442test_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
456test_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
471test_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
486test_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
508cat >expect.conflict <<EOF
509UU submod
510EOF
511
512test_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
523test_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
542test_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
561test_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
578test_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
603test_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
613test_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
632cat >expect.deepmodified <<EOF
633 M submod/subsubmod
634EOF
635
636test_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
654test_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
661test_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
676test_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
691test_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
706test_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
723test_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
738test_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
750test_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
763test_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
775test_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
789test_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
803test_expect_success 'setup for testing rm messages' '
804 >bar.txt &&
805 >foo.txt &&
806 git add bar.txt foo.txt
807'
808
809test_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
823test_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
836test_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
848test_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
858test_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
871test_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
880test_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
899test_expect_success 'rm empty string should fail' '
900 test_must_fail git rm -rf ""
901'
902
903test_done