My situation: I have a large number of computers that I use for various tasks. I have a large number of libraries, each in its own git repo.
My desire: I want to be able to modify one of the libraries on any computer, do a git commit/push; then go to another computer, do a git pull
, and have all the libraries updated. Then I modify one of these libraries, commit/push, and everything works when I get tot he next computer.
My current attempt: I have a top-level git project that incorporates all the other library repos as submodules. This includes a .gitmodules file that specifies the working branch of each module by using
git config -f .gitmodules submodule.modulename.branch develop
I have update = merge
set for each module.
I have submodule.recurse
set to true, so git pull
at the top level does something to each module.
How it is broken: Heads become detached. I wrote a script that parses the .gitmodules
file and does a checkout
of the appropriate branch of each module. I then commit
and push
the top module. Whenever I modify things and try to do a pull, e.g. on another machine, heads become detached. If I don't notice that the head is detached before I start modifications, I have to carefully unscramble the wreckage before I can commit my changes.
There are literally 3.6k stack overflow questions about git detached heads over the past decade, and most seem to be from the submodule capability. I haven't gone through all of them, but what I have tried isn't working.
I forget why I rejected git-subtree
, but git-subrepo
hasn't been touched in over a year and has 153 issues and 25 pull requests pending, so I think it's dead.
Does anyone have a working solution to this?
Accepted answer from @vonC looks good.
I could probably streamline this a bit, but my readme for the top-level project now says:
Recommended checkout:
git clone --recursive --jobs=8 *mysuperproject_clone_url*
cd *mysuperproject*
git config alias.pullall 'submodule foreach git pull'
git config alias.statusall 'submodule foreach git status'
git config alias.switchall \
"submodule foreach --recursive 'git switch \$(git config -f \${toplevel}/.gitmodules submodule.\${sm_path}.branch)'"
git switchall
Updating from repository
git pullall
If heads become detached, fix with
git switchall
To add a module
Module named newmodule
working on path develop
in the following example.
cd /path/to/mysuperproject
git submodule add git@github.com:myaccount/newmodule
git config -f .gitmodules submodule.newmodule.branch develop
git config -f .gitmodules submodule.newmodule.update merge
If the submodule is on the default master
branch, you still have to config the branch.
If you switch a submodule to a different branch, then in the top level you must config again
git config -f .gitmodules submodule.newmodule.branch newbranch
And push both the submodule and the top level project.
On a different working directory (such as on a different machine), you must
cd /path/to/mysuperproject
git pull
git switchall
git pullall