How can I do the reverse of git submodule absorbgitdirs
? I.e. move a submodule's .git
information out of superproject/.git/modules/<module>
and back to the superproject/path/to/<module>/.git
directory?
I still want <module>
to be a submodule of superproject
, I just don't want <module>
's .git
directory info in superproject
's .git/modules
directory.
Once you have set up the submodules you can update the repository with fetch/pull like you would normally do. To pull everything including the submodules, use the --recurse-submodules and the --remote parameter in the git pull command .
You can set the submodule to track a particular branch (requires git 1.8. 2+), which is what we are doing with Komodo, or you can reference a particular repository commit (the later requires updating the main repository whenever you want to pull in new changes from the module – i.e. updating the commit hash reference).
Git submodules may look powerful or cool upfront, but for all the reasons above it is a bad idea to share code using submodules, especially when the code changes frequently. It will be much worse when you have more and more developers working on the same repos.
The submodule is just a separate repository. If you want to make changes to it, you should make the changes in its repository and push them like in a regular Git repository (just execute the git commands in the submodule's directory).
Note that this would make superproject/path/to/<module>/
a nested Git repo, whose SHA1 would still be recorded by the parent project.
To keep the exact same state, you can copy superproject/.git/modules/<module>
and rename to superproject/path/to/<module>
, and rename <module>/<module>
to <module>/.git
.
Then you can use the git submodule deinit
to remove the submodule:
mv asubmodule asubmodule_tmp
git submodule deinit -f -- a/submodule
rm -rf .git/modules/a/submodule
# if you want to leave it in your working tree
git rm --cached asubmodule
mv asubmodule_tmp asubmodule
I still want to be a submodule of superprojec
Then its .git
folder would be in superproject/.git/modules/<module>
submodule absorbgitdirs
does not leave any choice:
If a git directory of a submodule is inside the submodule, move the git directory of the submodule into its superprojects
$GIT_DIR/modules
path and then connect the git directory and its working directory by setting thecore.worktree
and adding a.git
file pointing to the git directory embedded in the superprojects git directory.
I don't see in git config
any configuration that might move $GIT_DI R/modules
.
absorbgitdirs
was introduced in commit f6f8586 for Git 2.12 (Q4 2016)
Its tests shows it expects to use GIT_DIR/modules
.
Older Git (before Git 1.7.8, Oct. 2011) had a .git
directly inside the submodule folder.
As noted by Jeremiah Rose in the comments:
Another use case is: if you are using a Docker container to use
git
commands inside a submodule, where the container can't see the superproject and errors out. :(
I wrote a script to do this. Add this to your ~/.gitconfig
:
[alias]
extract-submodules = "!gitextractsubmodules() { set -e && { if [ 0 -lt \"$#\" ]; then printf \"%s\\n\" \"$@\"; else git ls-files --stage | sed -n \"s/^160000 [a-fA-F0-9]\\+ [0-9]\\+\\s*//p\"; fi; } | { local path && while read -r path; do if [ -f \"${path}/.git\" ]; then local git_dir && git_dir=\"$(git -C \"${path}\" rev-parse --absolute-git-dir)\" && if [ -d \"${git_dir}\" ]; then printf \"%s\t%s\n\" \"${git_dir}\" \"${path}/.git\" && mv --no-target-directory --backup=simple -- \"${git_dir}\" \"${path}/.git\" && git --work-tree=\"${path}\" --git-dir=\"${path}/.git\" config --local --path --unset core.worktree && rm -f -- \"${path}/.git~\" && if 1>&- command -v attrib.exe; then MSYS2_ARG_CONV_EXCL=\"*\" attrib.exe \"+H\" \"/D\" \"${path}/.git\"; fi; fi; fi; done; }; } && gitextractsubmodules"
and then run:
git extract-submodules [<path>...]
If you run it without specifying any submodules, it will extract all of them.
If you want to see what the code is doing, just change
&& gitextractsubmodules
at the end to
&& type gitextractsubmodules
and then run the command without arguments to make Bash pretty-print the function body.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With