#!/usr/bin/env bashset -eu -o pipefail git init -q module1(cd module1 touch this mkdir subdir touch subdir/that git add . git commit -q -m c1 echo hello >> this git commit -q -am c2 touch untracked) git init submodule-head-changed(cd submodule-head-changed git submodule add ../module1 m1 git commit -m "add submodule" cd m1 && git checkout @~1) git init submodule-index-changed(cd submodule-index-changed git submodule add ../module1 m1 git commit -m "add submodule" (cd m1 git mv subdir subdir-renamed git mv this that )) git init submodule-head-changed-no-worktree(cd submodule-head-changed-no-worktree git submodule add ../module1 m1 git commit -m "add submodule" (cd m1 && git checkout @~1) rm -Rf m1 && mkdir m1) git init modified-and-untracked(cd modified-and-untracked git submodule add ../module1 m1 git commit -m "add submodule" (cd m1 echo change >> this touch new )) git init submodule-head-changed-and-modified(cd submodule-head-changed-and-modified git submodule add ../module1 m1 git commit -m "add submodule" (cd m1 git checkout @~1 echo change >> this )) git init submodule-head-changed-and-modified-with-untracked-in-nested-dir(cd submodule-head-changed-and-modified-with-untracked-in-nested-dir git submodule add ../module1 m1 git commit -m "add submodule" mkdir -p a/b touch a/b/untracked (cd m1 git checkout @~1 echo change >> this )) ln -s submodule-head-changed-and-modified-with-untracked-in-nested-dir/a/b link-to-dir-in-changed-parent-repo git init modified-untracked-and-submodule-head-changed-and-modified(cd modified-untracked-and-submodule-head-changed-and-modified git submodule add ../module1 m1 git commit -m "add submodule" (cd m1 git checkout @~1 echo change >> this ) touch this git add this && git commit -m "this" echo change >> this touch untracked) cp -Rv modified-untracked-and-submodule-head-changed-and-modified git-mv-and-untracked-and-submodule-head-changed-and-modified(cd git-mv-and-untracked-and-submodule-head-changed-and-modified git checkout this git mv this that) cp -Rv git-mv-and-untracked-and-submodule-head-changed-and-modified git-mv-and-untracked-and-submodule-head-changed-and-modified-ignore-all(cd git-mv-and-untracked-and-submodule-head-changed-and-modified-ignore-all echo $'\tignore = all' >>.gitmodules git add .gitmodules && git commit -m "ignore all submodule changes") git init with-submodules(cd with-submodules mkdir dir touch dir/file git add dir git commit -m "init" git submodule add ../module1 m1 git commit -m "add module 1" git submodule add ../module1 dir/m1) # Git permits absolute-looking submodule names because it appends them textually below# `.git/modules/` instead of joining them as paths. Keep committed gitlinks for both Unix and# Windows spellings so consumers can verify that these are ordinary submodules made by Git.git init absolute-looking-submodule-names(cd absolute-looking-submodule-names # Use portable names while cloning, then change only the committed configuration. Passing a # leading slash through Git Bash on Windows would be translated to its installation directory. git submodule add ../module1 unix git submodule add ../module1 windows git config -f .gitmodules --rename-section submodule.unix submodule./absolute/unix git config -f .gitmodules --rename-section submodule.windows 'submodule.\absolute\windows' git commit -m "add submodules with absolute-looking names" # A backslash is a filename character on Unix but a separator on Windows. The test only needs # Git's committed configuration and gitlinks, so omit the cloned repositories from the fixture # to keep its generated representation portable. rm -rf .git/modules) git init submodule-with-divergent-gitlink(cd submodule-with-divergent-gitlink git submodule add ../module1 outer/inner git commit -m "add nested submodule" mv .git/modules/outer/inner .git/modules/inner rmdir .git/modules/outer git config --file .git/modules/inner/config core.worktree ../../../outer/inner printf 'gitdir: ../../.git/modules/inner\n' >outer/inner/.git git clone --bare ../module1 .git/modules/outer/inner git -C .git/modules/outer/inner update-ref HEAD "$(git -C ../module1 rev-parse @~1)") mkdir linked-git-dir-detached-worktree(cd linked-git-dir-detached-worktree mkdir -p home store git init store/dots ln -s ../store/dots/.git home/.git git -C store/dots config core.worktree ../../../home git -C home submodule add ../../module1 .config/awesome/lain git -C home commit -m "add detached-worktree submodule" echo "Git resolves the symlinked top-level .git to the real git dir before applying relative core.worktree." \ >baseline.note git -C home status --porcelain=v1 >status.baseline git -C home/.config/awesome/lain rev-parse --show-toplevel >submodule-worktree.baseline) git init submodule-with-missing-gitlink-target(cd submodule-with-missing-gitlink-target git submodule add ../module1 m1 git commit -m "add submodule" printf 'gitdir: ../missing\n' >m1/.git) git init submodule-with-malformed-gitlink(cd submodule-with-malformed-gitlink git submodule add ../module1 m1 git commit -m "add submodule" printf 'bogus\n' >m1/.git) cp -R with-submodules with-submodules-in-index(cd with-submodules-in-index git add . rm .gitmodules) cp -R with-submodules with-submodules-in-tree(cd with-submodules-in-tree rm .gitmodules rm .git/index) git init old-form-invalid-worktree-path(cd old-form-invalid-worktree-path mkdir dir git submodule add --name old ../module1 dir/old-form rm dir/old-form/.git # the config file contains a worktree path that points to the wrong place now mv .git/modules/old dir/old-form/.git) cp -R old-form-invalid-worktree-path old-form(cd old-form cd dir/old-form git config --unset core.worktree) git clone with-submodules with-submodules-after-clone(cd with-submodules-after-clone git submodule init m1)git clone --bare with-submodules with-submodules-after-clone.git(cd with-submodules-after-clone.git # manually create a clone and see if we can handle it despite being bare git clone --bare ../module1 modules/m1) git init with-submodule-uninitialized-checkout(cd with-submodule-uninitialized-checkout git submodule add ../module1 m1 git submodule add ../module1 m2 git commit -m "add modules" # The module clones in `.git/modules` remain, but the checkouts don't exist yet, # like just before a fresh worktree checkout. rm m1/.git rm -rf m2) git clone with-submodules not-a-submodule(cd not-a-submodule git submodule update --init cp .gitmodules modules.bak git rm m1 echo fake > m1 mv modules.bak .gitmodules git add m1 && git commit -m "no submodule in index and commit, but in configuration") git init unborn # Opening repositories through this symlink exercises preservation of the# caller's path namespace when only an ancestor of the Git directory is linked.ln -s . symlinked-ancestor
#!/usr/bin/env bash
set -eu -o pipefail
git init -q module1
(cd module1
touch this
mkdir subdir
touch subdir/that
git add .
git commit -q -m c1
echo hello >> this
git commit -q -am c2
touch untracked
)
git init submodule-head-changed
(cd submodule-head-changed
git submodule add ../module1 m1
git commit -m "add submodule"
cd m1 && git checkout @~1
)
git init submodule-index-changed
(cd submodule-index-changed
git submodule add ../module1 m1
git commit -m "add submodule"
(cd m1
git mv subdir subdir-renamed
git mv this that
)
)
git init submodule-head-changed-no-worktree
(cd submodule-head-changed-no-worktree
git submodule add ../module1 m1
git commit -m "add submodule"
(cd m1 && git checkout @~1)
rm -Rf m1 && mkdir m1
)
git init modified-and-untracked
(cd modified-and-untracked
git submodule add ../module1 m1
git commit -m "add submodule"
(cd m1
echo change >> this
touch new
)
)
git init submodule-head-changed-and-modified
(cd submodule-head-changed-and-modified
git submodule add ../module1 m1
git commit -m "add submodule"
(cd m1
git checkout @~1
echo change >> this
)
)
git init submodule-head-changed-and-modified-with-untracked-in-nested-dir
(cd submodule-head-changed-and-modified-with-untracked-in-nested-dir
git submodule add ../module1 m1
git commit -m "add submodule"
mkdir -p a/b
touch a/b/untracked
(cd m1
git checkout @~1
echo change >> this
)
)
ln -s submodule-head-changed-and-modified-with-untracked-in-nested-dir/a/b link-to-dir-in-changed-parent-repo
git init modified-untracked-and-submodule-head-changed-and-modified
(cd modified-untracked-and-submodule-head-changed-and-modified
git submodule add ../module1 m1
git commit -m "add submodule"
(cd m1
git checkout @~1
echo change >> this
)
touch this
git add this && git commit -m "this"
echo change >> this
touch untracked
)
cp -Rv modified-untracked-and-submodule-head-changed-and-modified git-mv-and-untracked-and-submodule-head-changed-and-modified
(cd git-mv-and-untracked-and-submodule-head-changed-and-modified
git checkout this
git mv this that
)
cp -Rv git-mv-and-untracked-and-submodule-head-changed-and-modified git-mv-and-untracked-and-submodule-head-changed-and-modified-ignore-all
(cd git-mv-and-untracked-and-submodule-head-changed-and-modified-ignore-all
echo $'\tignore = all' >>.gitmodules
git add .gitmodules && git commit -m "ignore all submodule changes"
)
git init with-submodules
(cd with-submodules
mkdir dir
touch dir/file
git add dir
git commit -m "init"
git submodule add ../module1 m1
git commit -m "add module 1"
git submodule add ../module1 dir/m1
)
# Git permits absolute-looking submodule names because it appends them textually below
# `.git/modules/` instead of joining them as paths. Keep committed gitlinks for both Unix and
# Windows spellings so consumers can verify that these are ordinary submodules made by Git.
git init absolute-looking-submodule-names
(cd absolute-looking-submodule-names
# Use portable names while cloning, then change only the committed configuration. Passing a
# leading slash through Git Bash on Windows would be translated to its installation directory.
git submodule add ../module1 unix
git submodule add ../module1 windows
git config -f .gitmodules --rename-section submodule.unix submodule./absolute/unix
git config -f .gitmodules --rename-section submodule.windows 'submodule.\absolute\windows'
git commit -m "add submodules with absolute-looking names"
# A backslash is a filename character on Unix but a separator on Windows. The test only needs
# Git's committed configuration and gitlinks, so omit the cloned repositories from the fixture
# to keep its generated representation portable.
rm -rf .git/modules
)
git init submodule-with-divergent-gitlink
(cd submodule-with-divergent-gitlink
git submodule add ../module1 outer/inner
git commit -m "add nested submodule"
mv .git/modules/outer/inner .git/modules/inner
rmdir .git/modules/outer
git config --file .git/modules/inner/config core.worktree ../../../outer/inner
printf 'gitdir: ../../.git/modules/inner\n' >outer/inner/.git
git clone --bare ../module1 .git/modules/outer/inner
git -C .git/modules/outer/inner update-ref HEAD "$(git -C ../module1 rev-parse @~1)"
)
mkdir linked-git-dir-detached-worktree
(cd linked-git-dir-detached-worktree
mkdir -p home store
git init store/dots
ln -s ../store/dots/.git home/.git
git -C store/dots config core.worktree ../../../home
git -C home submodule add ../../module1 .config/awesome/lain
git -C home commit -m "add detached-worktree submodule"
echo "Git resolves the symlinked top-level .git to the real git dir before applying relative core.worktree." \
>baseline.note
git -C home status --porcelain=v1 >status.baseline
git -C home/.config/awesome/lain rev-parse --show-toplevel >submodule-worktree.baseline
)
git init submodule-with-missing-gitlink-target
(cd submodule-with-missing-gitlink-target
git submodule add ../module1 m1
git commit -m "add submodule"
printf 'gitdir: ../missing\n' >m1/.git
)
git init submodule-with-malformed-gitlink
(cd submodule-with-malformed-gitlink
git submodule add ../module1 m1
git commit -m "add submodule"
printf 'bogus\n' >m1/.git
)
cp -R with-submodules with-submodules-in-index
(cd with-submodules-in-index
git add .
rm .gitmodules
)
cp -R with-submodules with-submodules-in-tree
(cd with-submodules-in-tree
rm .gitmodules
rm .git/index
)
git init old-form-invalid-worktree-path
(cd old-form-invalid-worktree-path
mkdir dir
git submodule add --name old ../module1 dir/old-form
rm dir/old-form/.git
# the config file contains a worktree path that points to the wrong place now
mv .git/modules/old dir/old-form/.git
)
cp -R old-form-invalid-worktree-path old-form
(cd old-form
cd dir/old-form
git config --unset core.worktree
)
git clone with-submodules with-submodules-after-clone
(cd with-submodules-after-clone
git submodule init m1
)
git clone --bare with-submodules with-submodules-after-clone.git
(cd with-submodules-after-clone.git
# manually create a clone and see if we can handle it despite being bare
git clone --bare ../module1 modules/m1
)
git init with-submodule-uninitialized-checkout
(cd with-submodule-uninitialized-checkout
git submodule add ../module1 m1
git submodule add ../module1 m2
git commit -m "add modules"
# The module clones in `.git/modules` remain, but the checkouts don't exist yet,
# like just before a fresh worktree checkout.
rm m1/.git
rm -rf m2
)
git clone with-submodules not-a-submodule
(cd not-a-submodule
git submodule update --init
cp .gitmodules modules.bak
git rm m1
echo fake > m1
mv modules.bak .gitmodules
git add m1 && git commit -m "no submodule in index and commit, but in configuration"
)
git init unborn
# Opening repositories through this symlink exercises preservation of the
# caller's path namespace when only an ancestor of the Git directory is linked.
ln -s . symlinked-ancestor