gitversion-controlgit-bundle

Using git bundle to synch airgapped repos


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?


Solution

  • 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...