2

I'm running into a problem whereby I want to synch 2 repositories that are not connected via network. I have used git bundle to synch between the two, but have run into a corner case.

I'm creating the git bundle via:

git bundle create --since=<timestamp of lastBundle> --all <my_bundle_path>

where <timestamp of lastBundle> was picked from the commit time associated with the lastBundle tag. This allows me to only bundle the delta and pick up all new commits across all branches.

The corner case is when this particular scenario occurs

master               2017-12-4 <dev who committed c2 finally gets around to pushing it to origin>
|\
| \
|  c3 <lastBundle>   2017-12-3 <commit that was synched>
|   |
c2  |                2017-12-2 <commit from dev, timestamped to when s/he committed it to their local repo>
 \  |
  \ |
   c1                2017-12-1 <base commit>

lastBundle was synced, and corresponds to the most current reference of the airgapped repo, but someone had committed c2 earlier in time than c3 in their own local copy of the repo and didn't push the reference to origin immediately. Thus, the next time I bundle every commit from lastBundle onwards and put it on a drive, load it on the other machine, it fails to validate because c2 is not in the bundle, only its merge to master.

I have looked at git merge-base to see if I can find a common ancestor, and use that instead. While that can do the job, I think I would need a lastBundle tag for each and every branch to make it work, since this situation could occur on 0, 1 or more branches at the same time. That seems non-optimal.

Ideally, I think I would like to be able to do a git bundle verify <mybundle> with respect to a given location in the git history, rather than the whole repository. That way I could verify it will fail before I put it on disk, and just change how far back I go for commits when bundling. Unless there is some other way to what I'm trying to do.

Any ideas?

  • Since you problem has been solved, you can add an answer for the detailed clarifications for how to preserve tags. It will also benefit others who have similar questions. – Marina Liu Dec 21 '17 at 09:14

1 Answers1

2

you should make your bundle not based on time, but on what you actually have sent. Use remote references for this (not tested):

git bundle create foo.bundle --branches
git fetch foo.bundle 'refs/heads/*:refs/remotes/sent/*'
....
git bundle create foo.bundle --branches --not --remotes sent
git fetch...
max630
  • 8,762
  • 3
  • 30
  • 55
  • 1
    Thanks for responding! So I think the command needs to be `--remotes=sent`, but other than that, it appears to do what it needs to do! For clarification for others, the goal is to bundle all the references the first time, and then create a refspec that points to the references that were bundled. Later, you bundle everything except the `sent` refspec, and then update your "sent" by fetching against your bundle again. – hobbitmessiah Dec 04 '17 at 15:27
  • So there is one missing piece: this doesn't deal with tags. I'd like to be able to also preserve tags between synchs. The only way I can think is to do something similar: `git fetch foo.bundle 'refs/tags/*:refs/tags/sent/*'` and modify the bundle to be `git bundle create foo.bundle --branches --tags --not --remotes=sent --tags=sent`. This will create a bunch of extra references, but that's okay. Also, it fails if a tag is forcibly changed, but then that shouldn't be done anyways. – hobbitmessiah Dec 04 '17 at 16:54