I want to automatically push commits in the post-receive hook from a central repo on our LAN to another central repo in the cloud. The LAN repo is created using git clone --mirror git@cloud:/path/to/repo
or equivalent commands.
Because the files being committed will be large relative to our upstream bandwidth, it's entirely possible something like this could happen:
- Alice initiates a push to the LAN repo.
- Bill pulls from the LAN repo while the post-receive hook is running.
- The LAN repo is in the middle of pushing to the cloud repo.
- This also means Bill's local repo contains the commits Alice pushed. Confirmed through testing.
- Bill initiates a push to the LAN repo.
- Bill's push is a fast-forward of Alice's push, so the LAN repo will accept it.
When the post-receive hook for the LAN repo executes, a second push from the LAN repo to the cloud repo will start and the two will run concurrently.
I'm not worried about the git objects. The worst-case scenario is that both pushes upload all of the objects from Alice's push, but that shouldn't matter as far as I understand git's internals.
I'm concerned about the refs. Suppose Alice pushed using a much slower connection, so that Bill's push finishes first. Suppose packet loss or something else causes the hook's push from the LAN repo to the cloud of Bill's push to finish before the hook's push from the LAN repo to the cloud of Alice's push. If both Alice and Bill are pushing the master branch and Bill's push finishes first, What will the master ref be on the cloud repo? I want it to be Bill's HEAD, since that's the later push, but I'm concerned it will be Alice's HEAD.
Further clarification:
I realize Alice's push from her machine to the LAN repo will fail if Bill's push from his machine to the LAN repo finishes first. In that case, the LAN repo's post-receive hook will not execute. Furthermore, please assume nobody will be doing force pushes, so if the post-receive hook runs on the LAN repo, all ref changes are fast-forwards.