17

I have a git repository with three submodules. The containing repository has two branches master and develop. All submodules only have one branch – the master branch.

When the containing repository is on the master branch, pushing to origin via git push --recurse-submodules=on-demand works as expected. Both the containing project as well as its submodules are pushed.

Now here is the problem. When the containing repository is on the develop branch, I am getting a problem when pushing via git push --recurse-submodules=on-demand. The push operation is cancelled and an error message is printed.

Here is the full output I get from git:

$ git push --recurse-submodules=on-demand
fatal: src refspec 'refs/heads/develop' must name a ref
fatal: process for submodule 'Frameworks/OpenLearnWareClient' failed

I can mitigate this problem by first pushing changes in each submodule manually and then pushing the containing repository. This however is very tedious and defeats the purpose of --recurse-submodules=on-demand.

Here is my .gitmodules file:

[submodule "Frameworks/OpenLearnWareKit"]
    path = Frameworks/OpenLearnWareKit
    url = git@github.com:kaiengelhardt/OpenLearnWareKit.git
    branch = master
[submodule "Frameworks/OpenLearnWareClient"]
    path = Frameworks/OpenLearnWareClient
    url = git@github.com:kaiengelhardt/OpenLearnWareClient.git
    branch = master
[submodule "Frameworks/KEFoundation"]
    path = Frameworks/KEFoundation
    url = git@github.com:kaiengelhardt/KEFoundation.git
    branch = master

I am using git version 2.20.1 (Apple Git-117).

Does anybody know what is going wrong here and how to make recursive pushing work?

Kai Engelhardt
  • 1,272
  • 13
  • 17
  • [this](https://stackoverflow.com/a/10878273/10309266) might be of some help – gavin Apr 23 '19 at 17:10
  • @gavin That’s what OP is already doing but it fails in this case. – Konrad Rudolph May 21 '19 at 10:38
  • This absolutely seems like a bug with git itself. Still getting this with git version 2.24.0 on macOS mojave. I don't know how to file a bug with git, but all anyone would need to do is link to this SO question. – Devin Rhode Nov 25 '19 at 04:00
  • Just found out, I can successfully run `git push --recurse-submodules=on-demand` on my `dev` branch, and it successfully pushed a new commit to a submodule. (Note: no PR workflow was used here, just pushing directly to my own branch) – Devin Rhode Nov 25 '19 at 17:49
  • I got this error while using third-party submodules and found I could get the push to go through with `--recurse-submodules=no`. Obviously that's not the case in the OP, but leaving this comment for future searchers. My submodules both have detached heads. – Adam J Richardson May 15 '21 at 15:24

1 Answers1

9

As far as I can tell (I’d like to be proved wrong!) there is no “recursive push” for submodule branches. In general, branches in submodules are an odd beast and don’t work the same way as regular branches in Git.

A close workaround is to use the git submodule foreach command to perform the pushes. This is still annoying but at least it solves the “tedious” aspect. Combine the commands as follows to ensure that a failed submodule push aborts the parent module push:

git submodule foreach --recursive 'git push' &&
git push

As far as I can tell this is essentially equivalent to passing --recurse-submodules=on-demand, but works with branches.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • This sadly doesn't work if I have dependencies (to whose repos I don't have write access) as submodules. `--recurse-submodules=on-demand` just skips these, because I don't commit anything in those repos. But `git push` in the submodule asks for a password (which I don't have and don't want to have...) – T S Nov 18 '21 at 11:38
  • 1
    @TS Unfortunately I don’t have a solution for this case. **But** in general you should mirror all submodule remotes. That is, submodules in your project should have remotes that you control and for which you therefore have push rights; otherwise your project is fragile: if the upstream maintainer of one of your submodules decides to delete their repository, or otherwise makes destructive changes to the repository, you’re screwed. – Konrad Rudolph Nov 18 '21 at 12:01