lib-submodule-update.sh: do not use ./. as submodule remote
[git] / t / lib-submodule-update.sh
1 # Create a submodule layout used for all tests below.
2 #
3 # The following use cases are covered:
4 # - New submodule (no_submodule => add_sub1)
5 # - Removed submodule (add_sub1 => remove_sub1)
6 # - Updated submodule (add_sub1 => modify_sub1)
7 # - Submodule updated to invalid commit (add_sub1 => invalid_sub1)
8 # - Submodule updated from invalid commit (invalid_sub1 => valid_sub1)
9 # - Submodule replaced by tracked files in directory (add_sub1 =>
10 #   replace_sub1_with_directory)
11 # - Directory containing tracked files replaced by submodule
12 #   (replace_sub1_with_directory => replace_directory_with_sub1)
13 # - Submodule replaced by tracked file with the same name (add_sub1 =>
14 #   replace_sub1_with_file)
15 # - Tracked file replaced by submodule (replace_sub1_with_file =>
16 #   replace_file_with_sub1)
17 #
18 #                     ----O
19 #                    /    ^
20 #                   /     remove_sub1
21 #                  /
22 #       add_sub1  /-------O
23 #             |  /        ^
24 #             | /         modify_sub1
25 #             v/
26 #      O------O-----------O---------O
27 #      ^       \          ^         replace_directory_with_sub1
28 #      |        \         replace_sub1_with_directory
29 # no_submodule   \
30 #                 --------O---------O
31 #                  \      ^         replace_file_with_sub1
32 #                   \     replace_sub1_with_file
33 #                    \
34 #                     ----O---------O
35 #                         ^         valid_sub1
36 #                         invalid_sub1
37 #
38
39 create_lib_submodule_repo () {
40         git init submodule_update_sub1 &&
41         (
42                 cd submodule_update_sub1 &&
43                 echo "expect" >>.gitignore &&
44                 echo "actual" >>.gitignore &&
45                 echo "x" >file1 &&
46                 echo "y" >file2 &&
47                 git add .gitignore file1 file2 &&
48                 git commit -m "Base inside first submodule" &&
49                 git branch "no_submodule"
50         ) &&
51         git init submodule_update_repo &&
52         (
53                 cd submodule_update_repo &&
54                 echo "expect" >>.gitignore &&
55                 echo "actual" >>.gitignore &&
56                 echo "x" >file1 &&
57                 echo "y" >file2 &&
58                 git add .gitignore file1 file2 &&
59                 git commit -m "Base" &&
60                 git branch "no_submodule" &&
61
62                 git checkout -b "add_sub1" &&
63                 git submodule add ../submodule_update_sub1 sub1 &&
64                 git config -f .gitmodules submodule.sub1.ignore all &&
65                 git config submodule.sub1.ignore all &&
66                 git add .gitmodules &&
67                 git commit -m "Add sub1" &&
68
69                 git checkout -b remove_sub1 add_sub1 &&
70                 git revert HEAD &&
71
72                 git checkout -b modify_sub1 add_sub1 &&
73                 git submodule update &&
74                 (
75                         cd sub1 &&
76                         git fetch &&
77                         git checkout -b "modifications" &&
78                         echo "z" >file2 &&
79                         echo "x" >file3 &&
80                         git add file2 file3 &&
81                         git commit -m "modified file2 and added file3" &&
82                         git push origin modifications
83                 ) &&
84                 git add sub1 &&
85                 git commit -m "Modify sub1" &&
86
87                 git checkout -b replace_sub1_with_directory add_sub1 &&
88                 git submodule update &&
89                 git -C sub1 checkout modifications &&
90                 git rm --cached sub1 &&
91                 rm sub1/.git* &&
92                 git config -f .gitmodules --remove-section "submodule.sub1" &&
93                 git add .gitmodules sub1/* &&
94                 git commit -m "Replace sub1 with directory" &&
95
96                 git checkout -b replace_directory_with_sub1 &&
97                 git revert HEAD &&
98
99                 git checkout -b replace_sub1_with_file add_sub1 &&
100                 git rm sub1 &&
101                 echo "content" >sub1 &&
102                 git add sub1 &&
103                 git commit -m "Replace sub1 with file" &&
104
105                 git checkout -b replace_file_with_sub1 &&
106                 git revert HEAD &&
107
108                 git checkout -b invalid_sub1 add_sub1 &&
109                 git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 sub1 &&
110                 git commit -m "Invalid sub1 commit" &&
111                 git checkout -b valid_sub1 &&
112                 git revert HEAD &&
113
114                 git checkout master
115         )
116 }
117
118 # Helper function to replace gitfile with .git directory
119 replace_gitfile_with_git_dir () {
120         (
121                 cd "$1" &&
122                 git_dir="$(git rev-parse --git-dir)" &&
123                 rm -f .git &&
124                 cp -R "$git_dir" .git &&
125                 GIT_WORK_TREE=. git config --unset core.worktree
126         )
127 }
128
129 # Test that the .git directory in the submodule is unchanged (except for the
130 # core.worktree setting, which appears only in $GIT_DIR/modules/$1/config).
131 # Call this function before test_submodule_content as the latter might
132 # write the index file leading to false positive index differences.
133 #
134 # Note that this only supports submodules at the root level of the
135 # superproject, with the default name, i.e. same as its path.
136 test_git_directory_is_unchanged () {
137         (
138                 cd ".git/modules/$1" &&
139                 # does core.worktree point at the right place?
140                 test "$(git config core.worktree)" = "../../../$1" &&
141                 # remove it temporarily before comparing, as
142                 # "$1/.git/config" lacks it...
143                 git config --unset core.worktree
144         ) &&
145         diff -r ".git/modules/$1" "$1/.git" &&
146         (
147                 # ... and then restore.
148                 cd ".git/modules/$1" &&
149                 git config core.worktree "../../../$1"
150         )
151 }
152
153 # Helper function to be executed at the start of every test below, it sets up
154 # the submodule repo if it doesn't exist and configures the most problematic
155 # settings for diff.ignoreSubmodules.
156 prolog () {
157         (test -d submodule_update_repo || create_lib_submodule_repo) &&
158         test_config_global diff.ignoreSubmodules all &&
159         test_config diff.ignoreSubmodules all
160 }
161
162 # Helper function to bring work tree back into the state given by the
163 # commit. This includes trying to populate sub1 accordingly if it exists and
164 # should be updated to an existing commit.
165 reset_work_tree_to () {
166         rm -rf submodule_update &&
167         git clone submodule_update_repo submodule_update &&
168         (
169                 cd submodule_update &&
170                 rm -rf sub1 &&
171                 git checkout -f "$1" &&
172                 git status -u -s >actual &&
173                 test_must_be_empty actual &&
174                 sha1=$(git rev-parse --revs-only HEAD:sub1) &&
175                 if test -n "$sha1" &&
176                    test $(cd "../submodule_update_sub1" && git rev-parse --verify "$sha1^{commit}")
177                 then
178                         git submodule update --init --recursive "sub1"
179                 fi
180         )
181 }
182
183 # Test that the superproject contains the content according to commit "$1"
184 # (the work tree must match the index for everything but submodules but the
185 # index must exactly match the given commit including any submodule SHA-1s).
186 test_superproject_content () {
187         git diff-index --cached "$1" >actual &&
188         test_must_be_empty actual &&
189         git diff-files --ignore-submodules >actual &&
190         test_must_be_empty actual
191 }
192
193 # Test that the given submodule at path "$1" contains the content according
194 # to the submodule commit recorded in the superproject's commit "$2"
195 test_submodule_content () {
196         if test $# != 2
197         then
198                 echo "test_submodule_content needs two arguments"
199                 return 1
200         fi &&
201         submodule="$1" &&
202         commit="$2" &&
203         test -d "$submodule"/ &&
204         if ! test -f "$submodule"/.git && ! test -d "$submodule"/.git
205         then
206                 echo "Submodule $submodule is not populated"
207                 return 1
208         fi &&
209         sha1=$(git rev-parse --verify "$commit:$submodule") &&
210         if test -z "$sha1"
211         then
212                 echo "Couldn't retrieve SHA-1 of $submodule for $commit"
213                 return 1
214         fi &&
215         (
216                 cd "$submodule" &&
217                 git status -u -s >actual &&
218                 test_must_be_empty actual &&
219                 git diff "$sha1" >actual &&
220                 test_must_be_empty actual
221         )
222 }
223
224 # Test that the following transitions are correctly handled:
225 # - Updated submodule
226 # - New submodule
227 # - Removed submodule
228 # - Directory containing tracked files replaced by submodule
229 # - Submodule replaced by tracked files in directory
230 # - Submodule replaced by tracked file with the same name
231 # - tracked file replaced by submodule
232 #
233 # The default is that submodule contents aren't changed until "git submodule
234 # update" is run. And even then that command doesn't delete the work tree of
235 # a removed submodule.
236 #
237 # Removing a submodule containing a .git directory must fail even when forced
238 # to protect the history!
239 #
240
241 # Test that submodule contents are currently not updated when switching
242 # between commits that change a submodule.
243 test_submodule_switch () {
244         command="$1"
245         ######################### Appearing submodule #########################
246         # Switching to a commit letting a submodule appear creates empty dir ...
247         if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1
248         then
249                 # Restoring stash fails to restore submodule index entry
250                 RESULT="failure"
251         else
252                 RESULT="success"
253         fi
254         test_expect_$RESULT "$command: added submodule creates empty directory" '
255                 prolog &&
256                 reset_work_tree_to no_submodule &&
257                 (
258                         cd submodule_update &&
259                         git branch -t add_sub1 origin/add_sub1 &&
260                         $command add_sub1 &&
261                         test_superproject_content origin/add_sub1 &&
262                         test_dir_is_empty sub1 &&
263                         git submodule update --init --recursive &&
264                         test_submodule_content sub1 origin/add_sub1
265                 )
266         '
267         # ... and doesn't care if it already exists ...
268         test_expect_$RESULT "$command: added submodule leaves existing empty directory alone" '
269                 prolog &&
270                 reset_work_tree_to no_submodule &&
271                 (
272                         cd submodule_update &&
273                         mkdir sub1 &&
274                         git branch -t add_sub1 origin/add_sub1 &&
275                         $command add_sub1 &&
276                         test_superproject_content origin/add_sub1 &&
277                         test_dir_is_empty sub1 &&
278                         git submodule update --init --recursive &&
279                         test_submodule_content sub1 origin/add_sub1
280                 )
281         '
282         # ... unless there is an untracked file in its place.
283         test_expect_success "$command: added submodule doesn't remove untracked unignored file with same name" '
284                 prolog &&
285                 reset_work_tree_to no_submodule &&
286                 (
287                         cd submodule_update &&
288                         git branch -t add_sub1 origin/add_sub1 &&
289                         >sub1 &&
290                         test_must_fail $command add_sub1 &&
291                         test_superproject_content origin/no_submodule &&
292                         test_must_be_empty sub1
293                 )
294         '
295         # Replacing a tracked file with a submodule produces an empty
296         # directory ...
297         test_expect_$RESULT "$command: replace tracked file with submodule creates empty directory" '
298                 prolog &&
299                 reset_work_tree_to replace_sub1_with_file &&
300                 (
301                         cd submodule_update &&
302                         git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&
303                         $command replace_file_with_sub1 &&
304                         test_superproject_content origin/replace_file_with_sub1 &&
305                         test_dir_is_empty sub1 &&
306                         git submodule update --init --recursive &&
307                         test_submodule_content sub1 origin/replace_file_with_sub1
308                 )
309         '
310         # ... as does removing a directory with tracked files with a
311         # submodule.
312         if test "$KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR" = 1
313         then
314                 # Non fast-forward merges fail with "Directory sub1 doesn't
315                 # exist. sub1" because the empty submodule directory is not
316                 # created
317                 RESULT="failure"
318         else
319                 RESULT="success"
320         fi
321         test_expect_$RESULT "$command: replace directory with submodule" '
322                 prolog &&
323                 reset_work_tree_to replace_sub1_with_directory &&
324                 (
325                         cd submodule_update &&
326                         git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&
327                         $command replace_directory_with_sub1 &&
328                         test_superproject_content origin/replace_directory_with_sub1 &&
329                         test_dir_is_empty sub1 &&
330                         git submodule update --init --recursive &&
331                         test_submodule_content sub1 origin/replace_directory_with_sub1
332                 )
333         '
334
335         ######################## Disappearing submodule #######################
336         # Removing a submodule doesn't remove its work tree ...
337         if test "$KNOWN_FAILURE_STASH_DOES_IGNORE_SUBMODULE_CHANGES" = 1
338         then
339                 RESULT="failure"
340         else
341                 RESULT="success"
342         fi
343         test_expect_$RESULT "$command: removed submodule leaves submodule directory and its contents in place" '
344                 prolog &&
345                 reset_work_tree_to add_sub1 &&
346                 (
347                         cd submodule_update &&
348                         git branch -t remove_sub1 origin/remove_sub1 &&
349                         $command remove_sub1 &&
350                         test_superproject_content origin/remove_sub1 &&
351                         test_submodule_content sub1 origin/add_sub1
352                 )
353         '
354         # ... especially when it contains a .git directory.
355         test_expect_$RESULT "$command: removed submodule leaves submodule containing a .git directory alone" '
356                 prolog &&
357                 reset_work_tree_to add_sub1 &&
358                 (
359                         cd submodule_update &&
360                         git branch -t remove_sub1 origin/remove_sub1 &&
361                         replace_gitfile_with_git_dir sub1 &&
362                         $command remove_sub1 &&
363                         test_superproject_content origin/remove_sub1 &&
364                         test_git_directory_is_unchanged sub1 &&
365                         test_submodule_content sub1 origin/add_sub1
366                 )
367         '
368         # Replacing a submodule with files in a directory must fail as the
369         # submodule work tree isn't removed ...
370         if test "$KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES" = 1
371         then
372                 # Non fast-forward merges attempt to merge the former
373                 # submodule files with the newly checked out ones in the
374                 # directory of the same name while it shouldn't.
375                 RESULT="failure"
376         else
377                 RESULT="success"
378         fi
379         test_expect_$RESULT "$command: replace submodule with a directory must fail" '
380                 prolog &&
381                 reset_work_tree_to add_sub1 &&
382                 (
383                         cd submodule_update &&
384                         git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
385                         test_must_fail $command replace_sub1_with_directory &&
386                         test_superproject_content origin/add_sub1 &&
387                         test_submodule_content sub1 origin/add_sub1
388                 )
389         '
390         # ... especially when it contains a .git directory.
391         test_expect_$RESULT "$command: replace submodule containing a .git directory with a directory must fail" '
392                 prolog &&
393                 reset_work_tree_to add_sub1 &&
394                 (
395                         cd submodule_update &&
396                         git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
397                         replace_gitfile_with_git_dir sub1 &&
398                         test_must_fail $command replace_sub1_with_directory &&
399                         test_superproject_content origin/add_sub1 &&
400                         test_git_directory_is_unchanged sub1 &&
401                         test_submodule_content sub1 origin/add_sub1
402                 )
403         '
404         # Replacing it with a file must fail as it could throw away any local
405         # work tree changes ...
406         test_expect_failure "$command: replace submodule with a file must fail" '
407                 prolog &&
408                 reset_work_tree_to add_sub1 &&
409                 (
410                         cd submodule_update &&
411                         git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
412                         test_must_fail $command replace_sub1_with_file &&
413                         test_superproject_content origin/add_sub1 &&
414                         test_submodule_content sub1 origin/add_sub1
415                 )
416         '
417         # ... or even destroy unpushed parts of submodule history if that
418         # still uses a .git directory.
419         test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" '
420                 prolog &&
421                 reset_work_tree_to add_sub1 &&
422                 (
423                         cd submodule_update &&
424                         git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
425                         replace_gitfile_with_git_dir sub1 &&
426                         test_must_fail $command replace_sub1_with_file &&
427                         test_superproject_content origin/add_sub1 &&
428                         test_git_directory_is_unchanged sub1 &&
429                         test_submodule_content sub1 origin/add_sub1
430                 )
431         '
432
433         ########################## Modified submodule #########################
434         # Updating a submodule sha1 doesn't update the submodule's work tree
435         if test "$KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT" = 1
436         then
437                 # When cherry picking a SHA-1 update for an ignored submodule
438                 # the commit incorrectly fails with "The previous cherry-pick
439                 # is now empty, possibly due to conflict resolution."
440                 RESULT="failure"
441         else
442                 RESULT="success"
443         fi
444         test_expect_$RESULT "$command: modified submodule does not update submodule work tree" '
445                 prolog &&
446                 reset_work_tree_to add_sub1 &&
447                 (
448                         cd submodule_update &&
449                         git branch -t modify_sub1 origin/modify_sub1 &&
450                         $command modify_sub1 &&
451                         test_superproject_content origin/modify_sub1 &&
452                         test_submodule_content sub1 origin/add_sub1 &&
453                         git submodule update &&
454                         test_submodule_content sub1 origin/modify_sub1
455                 )
456         '
457
458         # Updating a submodule to an invalid sha1 doesn't update the
459         # submodule's work tree, subsequent update will fail
460         test_expect_$RESULT "$command: modified submodule does not update submodule work tree to invalid commit" '
461                 prolog &&
462                 reset_work_tree_to add_sub1 &&
463                 (
464                         cd submodule_update &&
465                         git branch -t invalid_sub1 origin/invalid_sub1 &&
466                         $command invalid_sub1 &&
467                         test_superproject_content origin/invalid_sub1 &&
468                         test_submodule_content sub1 origin/add_sub1 &&
469                         test_must_fail git submodule update &&
470                         test_submodule_content sub1 origin/add_sub1
471                 )
472         '
473         # Updating a submodule from an invalid sha1 doesn't update the
474         # submodule's work tree, subsequent update will succeed
475         test_expect_$RESULT "$command: modified submodule does not update submodule work tree from invalid commit" '
476                 prolog &&
477                 reset_work_tree_to invalid_sub1 &&
478                 (
479                         cd submodule_update &&
480                         git branch -t valid_sub1 origin/valid_sub1 &&
481                         $command valid_sub1 &&
482                         test_superproject_content origin/valid_sub1 &&
483                         test_dir_is_empty sub1 &&
484                         git submodule update --init --recursive &&
485                         test_submodule_content sub1 origin/valid_sub1
486                 )
487         '
488 }
489
490 # Test that submodule contents are currently not updated when switching
491 # between commits that change a submodule, but throwing away local changes in
492 # the superproject is allowed.
493 test_submodule_forced_switch () {
494         command="$1"
495         ######################### Appearing submodule #########################
496         # Switching to a commit letting a submodule appear creates empty dir ...
497         test_expect_success "$command: added submodule creates empty directory" '
498                 prolog &&
499                 reset_work_tree_to no_submodule &&
500                 (
501                         cd submodule_update &&
502                         git branch -t add_sub1 origin/add_sub1 &&
503                         $command add_sub1 &&
504                         test_superproject_content origin/add_sub1 &&
505                         test_dir_is_empty sub1 &&
506                         git submodule update --init --recursive &&
507                         test_submodule_content sub1 origin/add_sub1
508                 )
509         '
510         # ... and doesn't care if it already exists ...
511         test_expect_success "$command: added submodule leaves existing empty directory alone" '
512                 prolog &&
513                 reset_work_tree_to no_submodule &&
514                 (
515                         cd submodule_update &&
516                         git branch -t add_sub1 origin/add_sub1 &&
517                         mkdir sub1 &&
518                         $command add_sub1 &&
519                         test_superproject_content origin/add_sub1 &&
520                         test_dir_is_empty sub1 &&
521                         git submodule update --init --recursive &&
522                         test_submodule_content sub1 origin/add_sub1
523                 )
524         '
525         # ... unless there is an untracked file in its place.
526         test_expect_success "$command: added submodule does remove untracked unignored file with same name when forced" '
527                 prolog &&
528                 reset_work_tree_to no_submodule &&
529                 (
530                         cd submodule_update &&
531                         git branch -t add_sub1 origin/add_sub1 &&
532                         >sub1 &&
533                         $command add_sub1 &&
534                         test_superproject_content origin/add_sub1 &&
535                         test_dir_is_empty sub1
536                 )
537         '
538         # Replacing a tracked file with a submodule produces an empty
539         # directory ...
540         test_expect_success "$command: replace tracked file with submodule creates empty directory" '
541                 prolog &&
542                 reset_work_tree_to replace_sub1_with_file &&
543                 (
544                         cd submodule_update &&
545                         git branch -t replace_file_with_sub1 origin/replace_file_with_sub1 &&
546                         $command replace_file_with_sub1 &&
547                         test_superproject_content origin/replace_file_with_sub1 &&
548                         test_dir_is_empty sub1 &&
549                         git submodule update --init --recursive &&
550                         test_submodule_content sub1 origin/replace_file_with_sub1
551                 )
552         '
553         # ... as does removing a directory with tracked files with a
554         # submodule.
555         test_expect_success "$command: replace directory with submodule" '
556                 prolog &&
557                 reset_work_tree_to replace_sub1_with_directory &&
558                 (
559                         cd submodule_update &&
560                         git branch -t replace_directory_with_sub1 origin/replace_directory_with_sub1 &&
561                         $command replace_directory_with_sub1 &&
562                         test_superproject_content origin/replace_directory_with_sub1 &&
563                         test_dir_is_empty sub1 &&
564                         git submodule update --init --recursive &&
565                         test_submodule_content sub1 origin/replace_directory_with_sub1
566                 )
567         '
568
569         ######################## Disappearing submodule #######################
570         # Removing a submodule doesn't remove its work tree ...
571         test_expect_success "$command: removed submodule leaves submodule directory and its contents in place" '
572                 prolog &&
573                 reset_work_tree_to add_sub1 &&
574                 (
575                         cd submodule_update &&
576                         git branch -t remove_sub1 origin/remove_sub1 &&
577                         $command remove_sub1 &&
578                         test_superproject_content origin/remove_sub1 &&
579                         test_submodule_content sub1 origin/add_sub1
580                 )
581         '
582         # ... especially when it contains a .git directory.
583         test_expect_success "$command: removed submodule leaves submodule containing a .git directory alone" '
584                 prolog &&
585                 reset_work_tree_to add_sub1 &&
586                 (
587                         cd submodule_update &&
588                         git branch -t remove_sub1 origin/remove_sub1 &&
589                         replace_gitfile_with_git_dir sub1 &&
590                         $command remove_sub1 &&
591                         test_superproject_content origin/remove_sub1 &&
592                         test_git_directory_is_unchanged sub1 &&
593                         test_submodule_content sub1 origin/add_sub1
594                 )
595         '
596         # Replacing a submodule with files in a directory must fail as the
597         # submodule work tree isn't removed ...
598         test_expect_failure "$command: replace submodule with a directory must fail" '
599                 prolog &&
600                 reset_work_tree_to add_sub1 &&
601                 (
602                         cd submodule_update &&
603                         git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
604                         test_must_fail $command replace_sub1_with_directory &&
605                         test_superproject_content origin/add_sub1 &&
606                         test_submodule_content sub1 origin/add_sub1
607                 )
608         '
609         # ... especially when it contains a .git directory.
610         test_expect_failure "$command: replace submodule containing a .git directory with a directory must fail" '
611                 prolog &&
612                 reset_work_tree_to add_sub1 &&
613                 (
614                         cd submodule_update &&
615                         git branch -t replace_sub1_with_directory origin/replace_sub1_with_directory &&
616                         replace_gitfile_with_git_dir sub1 &&
617                         test_must_fail $command replace_sub1_with_directory &&
618                         test_superproject_content origin/add_sub1 &&
619                         test_git_directory_is_unchanged sub1 &&
620                         test_submodule_content sub1 origin/add_sub1
621                 )
622         '
623         # Replacing it with a file must fail as it could throw away any local
624         # work tree changes ...
625         test_expect_failure "$command: replace submodule with a file must fail" '
626                 prolog &&
627                 reset_work_tree_to add_sub1 &&
628                 (
629                         cd submodule_update &&
630                         git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
631                         test_must_fail $command replace_sub1_with_file &&
632                         test_superproject_content origin/add_sub1 &&
633                         test_submodule_content sub1 origin/add_sub1
634                 )
635         '
636         # ... or even destroy unpushed parts of submodule history if that
637         # still uses a .git directory.
638         test_expect_failure "$command: replace submodule containing a .git directory with a file must fail" '
639                 prolog &&
640                 reset_work_tree_to add_sub1 &&
641                 (
642                         cd submodule_update &&
643                         git branch -t replace_sub1_with_file origin/replace_sub1_with_file &&
644                         replace_gitfile_with_git_dir sub1 &&
645                         test_must_fail $command replace_sub1_with_file &&
646                         test_superproject_content origin/add_sub1 &&
647                         test_git_directory_is_unchanged sub1 &&
648                         test_submodule_content sub1 origin/add_sub1
649                 )
650         '
651
652         ########################## Modified submodule #########################
653         # Updating a submodule sha1 doesn't update the submodule's work tree
654         test_expect_success "$command: modified submodule does not update submodule work tree" '
655                 prolog &&
656                 reset_work_tree_to add_sub1 &&
657                 (
658                         cd submodule_update &&
659                         git branch -t modify_sub1 origin/modify_sub1 &&
660                         $command modify_sub1 &&
661                         test_superproject_content origin/modify_sub1 &&
662                         test_submodule_content sub1 origin/add_sub1 &&
663                         git submodule update &&
664                         test_submodule_content sub1 origin/modify_sub1
665                 )
666         '
667         # Updating a submodule to an invalid sha1 doesn't update the
668         # submodule's work tree, subsequent update will fail
669         test_expect_success "$command: modified submodule does not update submodule work tree to invalid commit" '
670                 prolog &&
671                 reset_work_tree_to add_sub1 &&
672                 (
673                         cd submodule_update &&
674                         git branch -t invalid_sub1 origin/invalid_sub1 &&
675                         $command invalid_sub1 &&
676                         test_superproject_content origin/invalid_sub1 &&
677                         test_submodule_content sub1 origin/add_sub1 &&
678                         test_must_fail git submodule update &&
679                         test_submodule_content sub1 origin/add_sub1
680                 )
681         '
682         # Updating a submodule from an invalid sha1 doesn't update the
683         # submodule's work tree, subsequent update will succeed
684         test_expect_success "$command: modified submodule does not update submodule work tree from invalid commit" '
685                 prolog &&
686                 reset_work_tree_to invalid_sub1 &&
687                 (
688                         cd submodule_update &&
689                         git branch -t valid_sub1 origin/valid_sub1 &&
690                         $command valid_sub1 &&
691                         test_superproject_content origin/valid_sub1 &&
692                         test_dir_is_empty sub1 &&
693                         git submodule update --init --recursive &&
694                         test_submodule_content sub1 origin/valid_sub1
695                 )
696         '
697 }