It may not be common, but there are times when you need to share commits from one Git repo with a clone on another computer with no network connection between the two. For example, Jeff and I once needed to share commits on our game with no way to connect our computers. That ruled out the use of Git’s protocols like
git://, HTTP, rsync, and so forth.
But thanks to Git ‘bundles’, if you can transfer files from one computer to another—we used flash drives—then you can continue to share updates between repositories. In this article I will explain how.
What are Bundles?
In this article I refer to ‘bundles’ as anything originating from or suitable for the
git-bundle command. I will not call these ‘packs’ or ‘archives’ because those have other meanings in Git parlance. You will see that we can use bundles with other commands besides
git-bundle, but it remains the primary command for their creation, verification, and management.
A bundle is a single file. Nothing more. That one file may contain the entire history of a repository, or it may have only a selected range of commits. It is not necessary to understand the internal structure of bundles. All that matters is to know that we can treat bundles as ‘remotes’ suitable for use with commands like
Creating a Bundle
Here is the example scenario we’ll use: Jeff and I are both working on our game on our individual computers. I have merged updates into my
master branch that I want to make available to him so that he can update his
master branch accordingly. Since we have no way to directly connect the computers I will create a bundle for the master branch via this command:
$ git bundle create ejmr.bundle master
The format for the command is this:
$ git bundle create <filename> <refs ...>
The first command above will create an
ejmr.bundle file that contains all of the history and commits for my
master branch, going all the way back to the initial commit. Realistically speaking, Jeff will already have a lot of these commits. But that overlap will cause no problems. If I knew, for example, that we shared updates less than a week ago I could cut down on that overlap by telling
git-bundle to restrict the amount of data it needs to store, like so:
$ git bundle create ejmr.bundle --since="one week ago" master
If I failed to include any necessary commits then we will be able to see that later on.
Loading From a Bundle
Now I put my
ejmr.bundle file into a USB thumb drive and hand it to Jeff. He copies the bundle somewhere on his computer. Let’s say
A good first step is to ensure the integrity and usefulness of the bundle. Jeff can do this like so:
$ git bundle verify /tmp/ejmr.bundle
This command will (among other things) tell Jeff if the bundle is missing any necessary commits. This can happen if I create a bundle that contains only a partial range of commits instead of a complete history. But assuming everything looks good, Jeff can integrate the changes from the bundle by pulling from it as he would any other remote source (assuming he is on his
master branch in this example).
$ git pull /tmp/ejmr.bundle
Pretty straight-forward, right?
The manual for git-bundle is not long so at this point you should give it a read. It explains some uses of the command which I did not touch on here, such as the flexibility you have when determining exactly what goes into a bundle. For example, want to put all of your branches and tags into a bundle?
$ git bundle create ejmr.bundle --branches --tags
git bundle list-heads ejmr.bundle would show exactly what the bundle includes. But these situations are clearly and concisely explained by the official manual.
Personally I have rarely found myself resorting to
git-bundle, but when in those rare cases it has proven extremely useful. It’s nice to know I have a way to keep repositories in sync so long as I can transfer files between computers in any way possible.