Is there a way to make git pull automatically update submodules?
Is there a way to automatically have git submodule update
(or p开发者_如何转开发referably git submodule update --init
called whenever git pull
is done?
Looking for a git config setting, or a git alias to help with this.
As of Git 2.14, you can use git pull --recurse-submodules
(and alias it to whatever you like).
As of Git 2.15, you could set submodule.recurse
to true to enable the desired behaviour.
You can do this globally by running:
git config --global submodule.recurse true
git config --global alias.pullall '!git pull && git submodule update --init --recursive'
If you want arguments to be passed to git pull, then use this instead:
git config --global alias.pullall '!f(){ git pull "$@" && git submodule update --init --recursive; }; f'
Starting with Git 1.7.5 it should update submodules automatically by default like you want it to.
[EDIT: per comments: the new 1.7.5 behaviour is to automatically fetch the latest commits for submodules, but not to update them (in the git submodule update
sense). So the information in this answer is relevant as background, but is not a complete answer by itself. You still need an alias to pull and update submodules in one command.]
The default behavior, "on-demand", is to update submodules whenever you fetch a commit that updates the submodule commit, and this commit isn't already located in your local clone.
You can also have it updated on every fetch or never (pre-1.7.5 behavior I assume).
The config option to change this behavior is fetch.recurseSubmodules
.
This option can be either set to a boolean value or to
on-demand
.
Setting it to a boolean changes the behavior offetch
andpull
to unconditionally recurse into submodules when set to true or to not recurse at all when set to false.When set to
on-demand
(the default value),fetch
andpull
will only recurse into a populated submodule when its superproject retrieves a commit that updates the submodule’s reference.
See:
git config
man page (1.7.5) (or latestgit config
man page)git fetch
man page (1.7.5) (or latest git fetch man page)
for more information.
git fetch --recurse-submodules[=yes|on-demand|no]
I'm surprised nobody mentioned using git hooks to do this!
Just add files named post-checkout
and post-merge
to your .git/hooks
directory of the relevant repositories, and put the following into each of them:
#!/bin/sh
git submodule update --init --recursive
Since you specfically asked for an alias, assuming you want to have this for many repositories, you can create an alias which adds these to a repository's .git/hooks
for you.
As others have mentioned, you can easily set this with:
git config --global submodule.recurse true
However, if you're like me and have a more complex .gitconfig
setup (my main ~/.gitconfig
file uses include
to load in other .gitconfig
files), and you can never remember how to convert between the command-line git
config format and the .gitconfig
format, here's how to add it to any of your .gitconfig
files:
[submodule]
recurse = true
An alias, as suggested by Kevin Ballard, is a perfectly good solution. Just to toss another option out there, you could also use a post-merge hook which simply runs git submodule update [--init]
.
You can create an alias for the git command that automatically handles submodule updating. Add the following to your .bashrc
# make git submodules usable
# This overwrites the 'git' command with modifications where necessary, and
# calls the original otherwise
git() {
if [[ $@ == clone* ]]; then
gitargs=$(echo "$@" | cut -c6-)
command git clone --recursive $gitargs
elif [[ $@ == pull* ]]; then
command git "$@" && git submodule update --init --recursive
elif [[ $@ == checkout* ]]; then
command git "$@" && git submodule update --init --recursive
else
command git "$@"
fi
}
As of Git 2.15, you could set submodule.recurse to true to enable the desired behaviour.
Actually, you won't have to do that.
Before Git 2.34 (Q4 2021), after "git clone --recurse-submodules
"(man), all submodules are cloned but they are not by default recursed into by other commands.
With Git 2.34, and submodule.stickyRecursiveClone
configuration set, submodule.recurse
configuration is set to true
in a repository created by "clone" with "--recurse-submodules
" option.
See commit 48072e3 (14 Aug 2021) by Mahi Kolla (24mahik
).
(Merged by Junio C Hamano -- gitster
-- in commit 6d09fc5, 10 Sep 2021)
clone
: set submodule.recurse=true if submodule.stickyRecursiveClone enabledSigned-off-by: Mahi Kolla
Based on current experience, when running
git clone --recurse-submodules
(man), developers do not expect other commands such as pull or checkout to run recursively into active submodules.However, setting
submodule.recurse=true
at this step could make for a simpler workflow by eliminating the need for the--recurse-submodules
option in subsequent commands.To collect more data on developers' preference in regards to making submodule.recurse=true a default config value in the future, deploy this feature under the opt in
submodule.stickyRecursiveClone
flag.
Warning: use Git 2.37 (Q3 2022):
"git pull
"(man) without --recurse-submodules=<arg>
made submodule.recurse
take precedence over fetch.recurseSubmodules
by mistake, which has been corrected with Git 2.37 (Q3 2022).
See commit 5819417 (10 May 2022) by Glen Choo (chooglen
).
(Merged by Junio C Hamano -- gitster
-- in commit ed54e1b, 20 May 2022)
pull
: do not letsubmodule.recurse
overridefetch.recurseSubmodules
Reported-by: Huang Zou
Helped-by: Philippe Blain
Signed-off-by: Glen Choo
Fix a bug in "
git pull
"(man) wheresubmodule.recurse
is preferred overfetch.recurseSubmodules
when performing a fetch (Documentation/config/fetch.txt says thatfetch.recurseSubmodules
should be preferred.).Do this by passing the value of the "
--recurse-submodules
" CLI option to the underlying fetch, instead of passing a value that combines the CLI option and config variables.In other words, this bug occurred because
builtin/pull.c
is conflating two similar-sounding, but different concepts:
- Whether "
git pull
" itself should care about submodules e.g. whether it should update the submodule worktrees after performing a merge.- The value of "
--recurse-submodules
" to pass to the underlyinggit fetch
".Thus, when
submodule.recurse
is set, the underlying "git fetch
"(man) gets invoked with--recurse-submodules[=value]
", overriding the value offetch.recurseSubmodules
.An alternative (and more obvious) approach to fix the bug would be to teach "
git pull
" to understandfetch.recurseSubmodules
, but the proposed solution works better because:
- We don't maintain two identical config-parsing implementions in "
git pull
" andgit fetch
".- It works better with other commands invoked by "
git pull
" e.g. 'git merge
'(man) wont accidentally respectfetch.recurseSubmodules
.
Only way how I was able to get the submodules and nested submodules to update:
git submodule update --remote --merge --recursive; git submodule foreach --recursive "(git add .; git commit -m 'SubmoduleSync'; git push; git pull;);" git add .; git commit -m 'SubmodulesSynced'; git push; git pull;
I was struggling to create the alias through terminal due to the brackets so I had to manually add this to .gitconfig for global:
[alias] supdate = "!git submodule update --remote --merge --recursive; git submodule foreach --recursive '(git add .; git commit -m 'SubmoduleSync'; git push; git pull;);' git add .; git commit -m 'SubmodulesSynced'; git push; git pull;"
Any suggestions for how to run the commands or the alias automatically?
精彩评论