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 [email protected]: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
I mentioned before that
git submodule update --remote --merge
is supposed to not detached the HEAD of a submodule following a branch.I understand you have set
update = merge
, but just for testing, try the complete update command, to see if this works.Since the HEAD is still detached, you need to add (to a git alias script for instance) the command
I just tested it:
First, in the Git repository, I check the submodule is in a detached HEAD mode:
Then I define my alias, with escaped
$
:\$
.No need for
../
when accessing the.gitmodules
file. That is what$toplevel
is for.Final test: