293

I have, in my naivety, set up a git submodule and treated it like a Subversion external - i.e. it's now full of changes that I've just realized haven't been committed or pushed anywhere.

Is there some easy way to commit/push the submodule changes back to the upstream repo? And what's the recommended technique in Git for doing simultaneous development on separate (but linked) repositories in this way?

Scott Harwell
  • 7,327
  • 2
  • 26
  • 41
Dylan Beattie
  • 50,029
  • 31
  • 120
  • 189
  • 2
    Note: http://stackoverflow.com/questions/3131912/why-are-git-submodules-incompatible-with-svn-externals/3132221#3132221 and http://stackoverflow.com/questions/2879414/git-submodule-svn-external/2879490#2879490 can help illustrating the difference between submodule and external. – VonC Apr 04 '11 at 19:03

5 Answers5

474

A submodule is its own repo/work-area, with its own .git directory.

So, first commit/push your submodule's changes:

$ cd path/to/submodule
$ git add <stuff>
$ git commit -m "comment"
$ git push

Then, update your main project to track the updated version of the submodule:

$ cd /main/project
$ git add path/to/submodule
$ git commit -m "updated my submodule"
$ git push
Teocci
  • 4,348
  • 1
  • 34
  • 36
timdev
  • 57,660
  • 6
  • 74
  • 90
  • 13
    except that git appears to have placed the submodule into an anonymous branch at times...$ git.exe b -a * (no branch) – rogerdpack Dec 03 '11 at 02:48
  • 18
    @rogerdpack - you're correct. Submodules usually end up on "no branch". You'll often need to check out some branch before adding/committing to your submodule. – timdev Dec 23 '11 at 16:57
  • 6
    even though this is marked as duplicate, +1 because your answer is clearer than the other – Tobias J Nov 21 '13 at 20:12
  • 11
    It's also worth noting that you may need to ```git checkout master``` after creating submodules from file trees within the github super project if you see ```HEAD detached at ...``` when you type ```git status```. – 4Z4T4R Jul 28 '14 at 21:32
  • 3
    This "no-branch" / detached head problem seems to go away if you make the submodule follow the tip of the master branch, instead of the default, which follows a commit. [This worked for me](http://stackoverflow.com/questions/9189575/git-submodule-tracking-latest?answertab=active#tab-top). – Alfred Bratterud Apr 30 '15 at 11:21
  • 10
    This fixed it for me git push origin HEAD:master – malhal Jun 09 '16 at 12:15
  • 3
    Is there a way to do both operations at the same time? – static_rtti Mar 21 '17 at 16:57
  • 1
    Except it won't work if you do not have rights to the submodule repository, so git will not allow you to push to it. Which is strange that no one mentioned this. You cannot push to repositories which you don't have access. Am I missing something? – Bersan Jun 08 '18 at 14:54
  • 1
    The only way I know is to fork the repo and push to it. – Bersan Jun 08 '18 at 14:55
  • @Sunset - Of course you can't push to a repo on which you don't have write permission. The use case discussed here assumes you own your own submodule's repo (perhaps it's some library code that you use in multiple projects). – timdev Jun 12 '18 at 18:08
  • This answer should be in the git submodule docs at https://git-scm.com/docs/git-submodule ! – GaryO Jun 27 '19 at 15:11
  • Shouldn't the command be `git submodule add path/to/submodule`? – firstpostcommenter Jul 17 '19 at 14:12
  • If the submodule follows e.g. the master branch and the change is pushed to submodule's master, the second step is not required. – kap Mar 03 '20 at 12:50
58

Note that if you have committed a bunch of changes in various submodules, you can (or will be soon able to) push everything in one go (ie one push from the parent repo), with:

git push --recurse-submodules=on-demand

git1.7.11 ([ANNOUNCE] Git 1.7.11.rc1) 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|no>::

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.

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

Alexis Wilke
  • 15,168
  • 8
  • 60
  • 116
VonC
  • 1,042,979
  • 435
  • 3,649
  • 4,283
7
$ git submodule status --recursive

Is also a life saver in this situation. You can use it and gitk --all to keep track of your sha1's and verify your sub-modules are pointing at what you think they are.

rahvin_t
  • 689
  • 8
  • 9
6

You can treat a submodule exactly like an ordinary repository. To propagate your changes upstream just commit and push as you would normally within that directory.

nickgrim
  • 5,243
  • 1
  • 20
  • 26
  • 2
    For me this was the best answer. If you treat it like any other git repo, you don't need to memorize any new commands! Just cd into the submodule's directory and: `git add -A` `git commit -m "some message"` `git push` Then cd to the main repo and do the same. – shmim May 13 '15 at 03:41
  • 21
    ...except that my ordinary repositories don't have detached heads. – Seth Jul 13 '16 at 23:03
  • Seems like this isn't quite complete. If you `cd submod; git commit -am'New stuff'; git push` that pushes the new commit to the submod's origin, but it doesn't record the new SHA in the parent project. The official docs don't even mention how to do this. I suspect it's (in parent project): `git add submod; git commit -m'Updated submod'; git push`. – GaryO Jun 27 '19 at 15:09
2

Before you can commit and push, you need to init a working repository tree for a submodule. I am using tortoise and do following things:

First check if there exist .git file (not a directory)

  • if there is such file it contains path to supermodule git directory
  • delete this file
  • do git init
  • do git add remote path the one used for submodule
  • follow instructions below

If there was .git file, there surly was .git directory which tracks local tree. You still need to a branch (you can create one) or switch to master (which sometimes does not work). Best to do is - git fetch - git pull. Do not omit fetch.

Now your commits and pulls will be synchronized with your origin/master

fantastory
  • 1,646
  • 19
  • 22