Using Git Bundles, i.e. Sharing Without a Network

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 git-fetch, git-pull, and git-clone.

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 /tmp/ejmr.bundle.

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?

Further Reading

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

The command 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.

Advertisements

One thought on “Using Git Bundles, i.e. Sharing Without a Network

  1. If I make changes in two repos, exchange bundles, and pull into each repo from the other’s bundle, I can merge in the changes and have the same file contents in each repo. However, the commit hashes for the two merges are different, at least because the committer or commit date are different. So HEAD of one repo is a different commit hash than HEAD of another repo. I think that means that my histories will forever diverge after that point unless I rebase somehow. Have you had this experience? If so, do you know of a way to merge the histories? Thanks!

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s