Git submodule push
Asked Answered
T

3

169

If I modify a submodule, can I push the commit back to the submodule origin, or would that require a clone? If clone, can I store a clone inside another repository?

Teetotal answered 28/4, 2011 at 6:5 Comment(1)
With git 2.7 (January 2016), you will only need to set once git config push.recurseSubmodules on-demand. Then a simple git push will be enough to push everything (main repo and submodules). See my edited answer below.Verdaverdant
U
184

A submodule is nothing but a clone of a git repo within another repo with some extra meta data (gitlink tree entry, .gitmodules file )

$ cd your_submodule
$ git checkout master
<hack,edit>
$ git commit -a -m "commit in submodule"
$ git push
$ cd ..
$ git add your_submodule
$ git commit -m "Updated submodule"
Unrobe answered 28/4, 2011 at 6:8 Comment(7)
Yes, and don't forget to pull changes from your synchronized local branch (if any) before pushing. Happens eg. when working with a gh-pages branch for documentation on a github repo :)Bred
I don't understand how can you cd your_submodule before add your_submodule ? I thougth the best way to add submodule was by using "add" git command. So is there another way to add submodule ?Doriedorin
@Doriedorin I think submodule is already there, he is cding into it to change something in the submodule.Spiritoso
can it be done iteratively for all submodules?Eatage
@Doriedorin git add your_submodule doesn't add the submodule to the project, the submodule is already here. The command to add a submodule to a project is: git submodule add [url]. What he's doing here is just moving the change done on the submodule from the working directory to the staging area. Like he would do with any other changes (i.e. git add [filename/-A/.]). Then he can commits the changes.Dekeles
Well, this reasoning does not work all the time. Sometimes, you don't change your submodule but still want the content of your submodule to be pushed on a remote. This may happen when you're pushing to a newly created remote.Raker
@Eatage yes, git submodule foreachConfiteor
V
151

Note that since git1.7.11 ([ANNOUNCE] Git 1.7.11.rc1 and release note, June 2012) mentions:

"git push --recurse-submodules" learned to optionally look into the histories of submodules bound to the superproject and push them out.

Probably done after this patch and the --on-demand option:

recurse-submodules=<check|on-demand>::

Make sure all submodule commits used by the revisions to be pushed are available on a remote tracking branch.

  • If check is used, it will be checked that all submodule commits that changed in the revisions to be pushed are available on a remote.
    Otherwise the push will be aborted and exit with non-zero status.
  • If on-demand is used, all submodules that changed in the revisions to be pushed will be pushed.
    If on-demand was not able to push all necessary revisions it will also be aborted and exit with non-zero status.

So you could push everything in one go with (from the parent repo) a:

git push --recurse-submodules=on-demand

This option only works for one level of nesting. Changes to the submodule inside of another submodule will not be pushed.


With git 2.7 (January 2016), a simple git push will be enough to push the parent repo... and all its submodules.

See commit d34141c, commit f5c7cd9 (03 Dec 2015), commit f5c7cd9 (03 Dec 2015), and commit b33a15b (17 Nov 2015) by Mike Crowe (mikecrowe).
(Merged by Junio C Hamano -- gitster -- in commit 5d35d72, 21 Dec 2015)

push: add recurseSubmodules config option

The --recurse-submodules command line parameter has existed for some time but it has no config file equivalent.

Following the style of the corresponding parameter for git fetch, let's invent push.recurseSubmodules to provide a default for this parameter.
This also requires the addition of --recurse-submodules=no to allow the configuration to be overridden on the command line when required.

The most straightforward way to implement this appears to be to make push use code in submodule-config in a similar way to fetch.

The git config doc now include:

push.recurseSubmodules:

Make sure all submodule commits used by the revisions to be pushed are available on a remote-tracking branch.

  • If the value is 'check', then Git will verify that all submodule commits that changed in the revisions to be pushed are available on at least one remote of the submodule. If any commits are missing, the push will be aborted and exit with non-zero status.
  • If the value is 'on-demand' then all submodules that changed in the revisions to be pushed will be pushed. If on-demand was not able to push all necessary revisions it will also be aborted and exit with non-zero status. -
  • If the value is 'no' then default behavior of ignoring submodules when pushing is retained.

You may override this configuration at time of push by specifying '--recurse-submodules=check|on-demand|no'.

So:

git config push.recurseSubmodules on-demand
git push

Git 2.12 (Q1 2017)

git push --dry-run --recurse-submodules=on-demand will actually work.

See commit 0301c82, commit 1aa7365 (17 Nov 2016) by Brandon Williams (mbrandonw).
(Merged by Junio C Hamano -- gitster -- in commit 12cf113, 16 Dec 2016)

push run with --dry-run doesn't actually (Git 2.11 Dec. 2016 and lower/before) perform a dry-run when push is configured to push submodules on-demand.
Instead all submodules which need to be pushed are actually pushed to their remotes while any updates for the superproject are performed as a dry-run.
This is a bug and not the intended behaviour of a dry-run.

Teach push to respect the --dry-run option when configured to recursively push submodules 'on-demand'.
This is done by passing the --dry-run flag to the child process which performs a push for a submodules when performing a dry-run.


And still in Git 2.12, you now havea "--recurse-submodules=only" option to push submodules out without pushing the top-level superproject.

See commit 225e8bf, commit 6c656c3, commit 14c01bd (19 Dec 2016) by Brandon Williams (mbrandonw).
(Merged by Junio C Hamano -- gitster -- in commit 792e22e, 31 Jan 2017)


With Git 2.36 (Q2 2022), "git fetch --negotiate-only"(man) is an internal command used by git push(man) to figure out which part of our history is missing from the other side.
It should never recurse into submodules even when fetch.recursesubmodules configuration variable is set, nor it should trigger "gc".
The code has been tightened up to ensure it only does common ancestry discovery and nothing else.

See commit 386c076, commit 135a12b, commit bec587d (18 Jan 2022) by Glen Choo (chooglen).
See commit de4eaae (20 Jan 2022) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit 472a219, 09 Feb 2022)

fetch --negotiate-only: do not update submodules

Signed-off-by: Glen Choo

git fetch --negotiate-only(man) is an implementation detail of push negotiation and, unlike most git fetch(man) invocations, does not actually update the main repository.
Thus it should not update submodules even if submodule recursion is enabled.

This is not just slow, it is wrong e.g. push negotiation with "submodule.recurse=true" will cause submodules to be updated because it invokes git fetch --negotiate-only.

Fix this by disabling submodule recursion if --negotiate-only was given.
Since this makes --negotiate-only and --recurse-submodules incompatible, check for this invalid combination and die.

fetch-options now includes in its man page:

This is incompatible with --recurse-submodules=[yes|on-demand].


With Git 2.39 (Q4 2022), push all submodules recursively with '--recurse-submodules=on-demand'.

See commit e62f779 (14 Nov 2022) by Jonathan Tan (jhowtan).
(Merged by Junio C Hamano -- gitster -- in commit 173fc54, 23 Nov 2022)

Doc: document push.recurseSubmodules=only

Signed-off-by: Jonathan Tan
Signed-off-by: Taylor Blau

Git learned pushing submodules without pushing the superproject by the user specifying --recurse-submodules=only through 6c656c3 ("submodules: add RECURSE_SUBMODULES_ONLY value", 2016-12-20, Git v2.12.0-rc0 -- merge listed in batch #8) and 225e8bf ("push: add option to push only submodules", 2016-12-20, Git v2.12.0-rc0 -- merge listed in batch #8).
For users who use this feature regularly, it is desirable to have an equivalent configuration.

It turns out that such a configuration (push.recurseSubmodules=only) is already supported, even though it is neither documented nor mentioned in the commit messages, due to the way the --recurse-submodules=only feature was implemented (a function used to parse --recurse-submodules was updated to support only, but that same function is used to parse push.recurseSubmodules too).
What is left is to document it and test it, which is what this commit does.

There is a possible point of confusion when recursing into a submodule that itself has the push.recurseSubmodules=only configuration, because if a repository has only its submodules pushed and not itself, its superproject can never be pushed.
Therefore, treat such configurations as being "on-demand", and print a warning message.

Warning message:

recursing into submodule with push.recurseSubmodules=only; using on-demand instead

git config now includes in its man page:

May be "check", "on-demand", "only", or "no", with the same behavior as that of "push --recurse-submodules".

git push now includes in its man page:

When using 'on-demand' or 'only', if a submodule has a "push.recurseSubmodules={on-demand,only}" or "submodule.recurse" configuration, further recursion will occur. In this case, "only" is treated as "on-demand".

Verdaverdant answered 4/6, 2012 at 8:19 Comment(7)
This is available now isn't it?Mme
@Mme yes it is, you can see it in git-scm.com/docs/git-push. I have edited the answer.Verdaverdant
Is there a recursive commit?Mme
you can always do 'git submodule foreach commit'Kellda
I had to update my .gitmodules file with the bitbucket urls.Farmergeneral
Can git push --recurse-submodules be squashed into the last submodules's latest commit?Eatage
@Eatage I don't think so: any squashing should be done at the source side of the push.Verdaverdant
S
4

You can use the foreach command of git

example of bash command:

git submodule foreach "git add . && git commit -m 'update' && git push"
Spadework answered 12/5, 2022 at 16:35 Comment(1)
This one is awesome. Looking for thisTransitive

© 2022 - 2024 — McMap. All rights reserved.