170

I need to transfer a complete repo to a new non-networked machine, preferable as a single file entity. The git bundle allows a git fetch, git pull style operation in a sneakernet environment but appears to assume that you already have a working version of the repo on the destination machine.

What is the right invocation to:

  1. Bundle all the branches in the current repo
  2. Start up the new repo on the destination directory, i.e. get the root commit correctly installed

I've sent a patch upstream to clarify:

`git clone` can use any bundle created without negative refspecs
(e.g., `new`, but not `old..new`).
If you want to match `git clone --mirror`, which would clone other
refs such as `refs/remotes/*`, use `--all`.
If you want to provide the same set of refs that a clone directly
from the source repository would get, use `--branches --tags` for
the `<git-rev-list-args>`.

So $ git bundle create repo.bundle --branches --tags best matches cloning.

$ git bundle create repo.bundle --all will provide a mirror image of your source machine, including it's remote refs.

Philip Oakley
  • 13,333
  • 9
  • 48
  • 71

4 Answers4

267

What is the right invocation to:

  • Bundle all the branches in the current repo

Simple:

$ git bundle create repo.bundle --all

Here repo.bundle is the name of bundle file you want to create. Note that --all would not include remote-tracking branches... just like ordinary clone wouldn't either.

  • Start up the new repo on the destination directory, i.e. get the root commit correctly installed

First, clone is just init + fetch (+ administrativia).

Second, you can use bundle file everywhere the repository URL can be used, so you can simply clone from a bundle file:

$ git clone repo.bundle

This would create repo as a git repository.

Jakub Narębski
  • 309,089
  • 65
  • 217
  • 230
  • 10
    Thanks, the `--all` options isn't in my man page for `bundle` (I'm looking at version 1.7.6.msysgit.0), nor is the use of the .bundle file in the URLs section for `clone`. It gives me greater confidence to recommend its use. – Philip Oakley Aug 03 '12 at 13:19
  • 27
    The synopsis for **create** command is `git bundle create `. Running `man git-rev-list` (or `man git-log`) would give you `--all`. But I agree that it should be more visible in the bundle command documentation. – Jakub Narębski Aug 03 '12 at 13:37
  • 1
    I see that the bundle man page, under Specifying References, says that it "will only package refs that are shown by `git show-ref`", which doesn't include [list] the git-rev-list options. – Philip Oakley Aug 04 '12 at 17:13
  • 2
    @Philip Oakley: The `git-rev-list-args` is how you *select* refs that are shown by `git show-ref` command. – Jakub Narębski Aug 04 '12 at 17:21
  • 2
    `--all` did include remote-tracking branches for me (git 2.1.4). I could see `refs/remotes/origin/*` with `git bundle list-heads bundlefile` or `git ls-remote bundlefile`. Although getting them back from the bundle is little tricky. – Alex Jun 25 '16 at 20:42
  • @Alex, how did you do it though? I can see the branches with your method and i can checkout the commits but i have not found a way to checkout the branches themselves. – user3637541 Jan 26 '17 at 14:04
  • @user3637541 I never did it. I just know that they are stored in the bundle and can be reconstructed with some script. Still missing in the bundle file is the remotes. You have a `refs/remotes/origin/master` in the bundle but the `origin` URL is lost. This is exactly why I just tar xz my _minified_ git repos instead of bundling them -- to preserve the remotes. – Alex Mar 08 '17 at 22:53
  • can any one tell me how to `bundle` only the `last 3 commits` ? – Prateek Naik Sep 20 '17 at 10:37
  • @Ben.Bean: you can `bundle` the last 3 commits in the same way as you would list them (with `git log`), for example with `git bundle create last-3-commits.bundle -3 master HEAD` (or something like that), or `master~3..master`, etc. – Jakub Narębski Sep 20 '17 at 13:13
  • @JakubNarębski, I tried your command like `git bundle create latest.bundle -3 develop HEAD`, it created file as `latest.bundle` but when i tried to unbundle it using `git clone latest.undle` its throwing errors `Cloning into 'last-3-commits'... error: Repository lacks these prerequisite commits: error: 3f2d2d3647de90fdfaed5a604473d9cabce78aa2 error: 31921433b6c52ed2ae87a9e8cedacc22bc97b170 fatal: bad object d1f94ed93b2df5a133118bf9f851adb6baa95911 fatal: remote did not send all necessary objects ` – Prateek Naik Sep 21 '17 at 03:49
  • 1
    @Ben.Bean: this simply means that last 3 commits are not enough - you need more than that. Simplest thing would be to check the date of latest commit in the repository you want to unbundle in, and pack `--since` that date (with some slack, just in case). – Jakub Narębski Sep 22 '17 at 10:39
  • @PhilipOakley funny that [it still isn't](http://man7.org/linux/man-pages/man1/git-bundle.1.html) seven years later. But then, `git-fast-export` also mentions `--all` in the examples but doesn't mention it in the section where arguments are discussed ... – 0xC0000022L Sep 13 '19 at 13:03
  • @0xC0000022L I tried to send in a doc patch but it was rejected as somehow obvious or bad https://public-inbox.org/git/7vzk4mj38g.fsf@alter.siamese.dyndns.org/ – Philip Oakley Sep 13 '19 at 20:30
  • @PhilipOakley I lack the words (and not just because I am not a native speaker of English) ... thanks for the update. – 0xC0000022L Sep 15 '19 at 20:43
  • How can I prevent it from messing up references? For instance, `refs/heads/4.1` is changed to `refs/remotes/origin/4.1`, and some other references are simply dropped. – vinc17 Dec 09 '20 at 00:07
  • 2
    OK, https://stackoverflow.com/a/48391271/3782797 gives the solution (the issue is actually when "restoring" the repository from the bundle, not creating the bundle): `git init .`, then `git fetch --update-head-ok /path/to/bundle '*:*'`. I've checked that the output of `git log --all --date=iso-local -m --name-status --decorate=full --graph --date-order` is the same. – vinc17 Dec 09 '20 at 00:28
49

First clone the repository, and include the --mirror option.

git clone --mirror git@example.org:path/repo.git

This ensures all remote branched are also local branches ready for bundeling.

Then run

git bundle create repo.bundle --all as described by the answer from Jakub Narębski

thoutbeckers
  • 2,599
  • 22
  • 24
5

I would suggest you tar or zip the .git folder and simply unpack it in the new location and then do git reset --hard HEAD. Everything required for all the branches is under .git and all you should need to do is adjust any remotes in the .git/config file or remove them.

tar cf myrepo.tgz .git
cp myrepo.tgz [USB_STICK]
... move to new machine ...
mkdir myrepo && cd myrepo
tar xpf [USB_STICK]/myrepo.tgz
git reset --hard HEAD
patthoyts
  • 32,320
  • 3
  • 62
  • 93
  • 5
    One caveat is that you'll need to look at the .git/config file to check if the original repo owner had any user specific stuff in there. – Noufal Ibrahim Aug 03 '12 at 09:23
  • @patthoyts: Given that it's disconnected, there'd be no remotes ;-) It does look like bundle is (may be) missing an option, and maybe clone (need to think about cloning from a bundle) – Philip Oakley Aug 03 '12 at 09:33
3

With Git 2.34 (Q4 2021), git bundle create is further clarified:

See commit 1d9c8da, commit 0bb92f3, commit 9ab80dd, commit 5c8273d (31 Jul 2021) by Ævar Arnfjörð Bjarmason (avar).
(Merged by Junio C Hamano -- gitster -- in commit f19b275, 24 Aug 2021)

bundle doc: elaborate on object prerequisites

Signed-off-by: Ævar Arnfjörð Bjarmason

Split out the discussion bout "object prerequisites" into its own section, and add some more examples of the common cases.

See 2e0afaf ("Add git-bundle: move objects and references by archive", 2007-02-22, Git v1.5.1-rc1 -- merge) for the introduction of the documentation being changed here.

git bundle now includes in its man page:

OBJECT PREREQUISITES

When creating bundles it is possible to create a self-contained bundle that can be unbundled in a repository with no common history, as well as providing negative revisions to exclude objects needed in the earlier parts of the history.

Feeding a revision such as new to git bundle create will create a bundle file that contains all the objects reachable from the revision new. That bundle can be unbundled in any repository to obtain a full history that leads to the revision new:

$ git bundle create full.bundle new

A revision range such as old..new will produce a bundle file that will require the revision old (and any objects reachable from it) to exist for the bundle to be "unbundle"-able:

$ git bundle create full.bundle old..new

A self-contained bundle without any prerequisites can be extracted into anywhere, even into an empty repository, or be cloned from (i.e., new, but not old..new).

git bundle now includes in its man page:

The 'git bundle verify' command can be used to check whether your recipient repository has the required prerequisite commits for a bundle.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250