Reputation: 11716
I have a Git repository on one machine (machine 1) that I would like to keep mirrored on another machine (machine 2). The second machine does not share network access with the first, so simply using git push
or git fetch
in one direction or another isn't an option. The repository contains many branches, tags, etc. and I would like to replicate that state exactly onto the second machine. The flow of changes is strictly from machine 1 -> machine 2; I don't have to support bringing commits back the other way.
One approach that works is to use Git bundles. That is, if I do the following:
git clone --mirror /path/to/my/source/repo
git bundle create bundle.gitb --all
Then the resulting bundle.gitb
file is a perfect mirror of the source repository. I can then copy this to machine 2 and use it as an origin to push changes into the repository mirror.
The main drawback of this approach is that it requires me to transfer the entire repository history each time. In my case, the history is very deep and is several GB in size, so I have to carry all of that data on every update, even if there are just a few new commits.
Therefore, I would like some kind of incremental Git bundle that only contains the commits that I have yet to transfer to machine 2. Is there a good way to do this?
I considered using the --since
flag to limit the commits to transfer by commit date, but it's possible that it could cause commits to be missed during the transfer.
--since=10.days.ago
to get all of the commits in the last 10 days, and I set up the incremental transfer to happen every 10 days. If someone pushes a new branch to the source repository that contains some changes that are older than 10 days, then they will not be included in the next transfer, and they will never make it to machine 2.I think that in order to meet all of my goals, I would need to be able to provide some kind of manifest of commit SHAs that have already been transferred, and thus I do not want to include in the bundle. So the workflow would be something like:
git clone --mirror /path/to/my/source/repo
# do something here to filter out all commits that have already been transferred
git bundle create bundle.gitb --all
And the resulting file would just contain the incremental commits. Is there a way to achieve this with one of Git's commands?
Upvotes: 1
Views: 734
Reputation: 3778
I'm trying this after torek's comment:
#!/usr/bin/env bash
LAST=$(ls | grep \\.bundle$ | sort | tail -n 1)
NEXT=$(date --iso=seconds).bundle
if [ -z "$LAST" ]
then
git bundle create "$NEXT" --all
else
git bundle list-heads "$LAST" | cut -d ' ' -f 1 | xargs git bundle create "$NEXT" --all --not
fi
It uses list-heads
to output the refs in the last bundle, and xargs
with --not
to exclude them from the next bundle.
The documentation for --all
and --not
is in git rev-list --help
.
Upvotes: 1