Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opposite/reverse of "git submodule absorbgitdirs"?

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.

like image 926
genpfault Avatar asked Jun 15 '17 05:06

genpfault


People also ask

Does git pull pull submodules?

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 .

Can a submodule point to a branch?

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).

Is git submodule a good idea?

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.

Can I modify the submodule in git?

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).


2 Answers

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 the core.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. :(

like image 81
VonC Avatar answered Oct 26 '22 13:10

VonC


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.

like image 45
user541686 Avatar answered Oct 26 '22 12:10

user541686