Skip to content

Update references atomically in FetchRemote

FetchRemote fetches a set of refspecs from a given URL into the target repository. The RPC call relies on the fact that this fetch is not an atomic one: it's perfectly expected that only a subset of refs in the target repository got updated in case the caller doesn't specify the Force flag. This is used e.g. to keep diverging branches when mirroring other remotes.

FetchRemote currently fetches from the remote and updates the references. It then votes on the result after the fact. This is not ideal as we should only update the references if all of the replicas agree on the result. Further, we also want to support partial updates of references. If some of the references don't apply, we still want to apply the remaining ones. Git doesn't provide a great way to achieve on its own but we can (ab)use the reference transaction hook to achieve this. This can be done by:

  1. git fetch --atomic the remote
  2. Capture the reference changes about to be made via the reference-transaction hook's prepare phase.
  3. Exit the hook with an error so git aborts the transaction.
  4. In the RPC handler
    1. See which references updates apply to the repository
    2. Vote on the ones that apply to ensure the replicas agree
    3. Apply them via git update-ref
Edited by Sami Hiltunen
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information