0

I'm trying to create a git bundle with only partial history. The command I run to bundle the entire branch is. (reference)

git bundle create my.bundle --all

However if I want to only bundle the initial commit up to (not including) a specific commit the correct rev-parse syntax is. (reference)

git bundle create my.bundle dae86e1950b1277e545cee180551750029cfe735^@

But this fails and git says...

fatal: Refusing to create empty bundle.

How do I create bundle with only the initial-commit and all history up to some specific revision?

EDIT

I found this post which explains git bundle only works with a tag (or other reference like HEAD). However I'm trying to bundle a range of commits, but the .. shorthand is exclusive and wont include an initial commit.

Aage Torleif
  • 1,907
  • 1
  • 20
  • 37
  • Possible duplicate of [Error trying to create a git bundle ranged between 2 commits](https://stackoverflow.com/questions/42542005/error-trying-to-create-a-git-bundle-ranged-between-2-commits) – Aage Torleif Aug 07 '18 at 11:26

1 Answers1

2

The short answer is that you can't—well, not quite. Essentially, git bundle is the server half of a git fetch: it builds a file that you literally hand over to git fetch later, when you have transported that file from the server to the client. The client needs that file to contain the kind of data that the server would pass to the client.

The result is that the bundle file must contain:

  • a list of reference names and their hash IDs, plus
  • the objects that git fetch would get based on those hash IDs, minus
  • the objects that git fetch would not need based on the client's "I already have ..." hash IDs.

When preparing the bundle, the arguments you supply are:

  • the reference names, and
  • the basis hash IDs that the client would have provided, had the client been able to connect directly.

Nowhere in this list of things-you-provide is there the ability to use rev^@-style references.

What you can do

What you can do is attach reference names to each of those heads:

for parent in $(git rev-parse ${rev}^@); do
    git tag bundle-p$parent $parent
done

Now you have actual reference names (lightweight tags) pointing to each of the commits that you do want to include in the bundle. You can now supply --tags='bundle-p*' as a set of positive refs, assuming there are no other tags that begin with bundle-p. (You can delete the tags afterward to maintain this invariant. You can use branch names instead, with --branches='bundle-p*', if that's more convenient for you.)

(Be aware that ${rev}^@ will produce no output when applied to a root commit. This means there will be no bundle-p* tags for this case.)

If your particular stop-point is an ordinary (single-parent) commit, you can just attach a single reference name to ${rev}^. In all cases, you must attach a reference name to the end-point commits that you do want to have in the bundle.

torek
  • 448,244
  • 59
  • 642
  • 775
  • @torak thanks! This is exactly what I needed. I'm places a tag at the commit I want and its `git rev-list --max-parents=0 $rev` and using `git bundle create --tags='xxx'` like you described. Also - thank you for your explanation of the purpose of the `bundle` command. – Aage Torleif Aug 09 '18 at 00:47