Search code examples
gitbundlegit-submodules

How do you bundle submodule changes in git?


If I have a repository that contains submodules, and I want to make a bundle for sneakernet, how do I make the bundle include the objects needed to update the submodules?

For example, let's say I have a repository called parent and it contains a submodule called submod. I want to create a bundle that contains all the recent work since commit basecommit, so naturally, from inside the parent root directory I would do:

git bundle create mybundlefile.bundle basecommit..myworkingbranch

This creates a file called mybundlefile.bundle that contains all the commit objects from the parent repo on the range basecommit..myworkingbranch as well as the ref myworkingbranch. The problem is that if any of those commits changed the submodule, the resultant bundle will not be very useful because such commits are only stored in the bundle file as changing the submodule hash. So the object stored in the bundle file just says "I'm commit 3ba024b and I change the hash of submodule submod from 2b941cf to 1bb84ec." but the bundle doesnt actually include the objects 2b941cf..1bb84ec necceassary to update the submodule from the bundle and make a clean working tree for myworkingbranch.

How do I create the bundle file such that all those objects from the submodule repos are also included. That is, if the parents repo's base commit basecommit points submodule submod at hash A and the parent repo's working branch myworkingbranch points submodule submod at hash B, then my bundle needs to contain not only basecommit..myworkingbranch, but also A..B.


Solution

  • How do I create the bundle file such that all those objects from the submodule repos are also included.

    You can't. A bundle file is specific to a Git repository. A submodule is simply a link to another Git repository, so you must create a separate bundle for the separate Git repository. (You can then make an archive out of the various bundles.)

    It's pretty clear that Git could descend into each submodule and run git bundle in each such one, making these various files for you. The arguments to pass to the sub-git bundle commands are tricky, though. You will have to write your own script and use git submodule foreach to get it to run in each submodule, and have your script figure out the parameters to use.

    You will then probably want to package together each bundle (presumably into a tar or rar or zip or whatever archive) for transport and unbundling / fetching. You'll want another git submodule foreach during the unbundling, which will probably be even more annoying since ideally this should use the new set of submodules (after unbundling the top level one and selecting an appropriate commit).

    It's possible that someone has written scripts to do this, but if so, I don't know of it. It's not included in Git itself—bundles themselves are kind of klunky and non-mainstream-y.