libgit2 does not respect force flag
We ran into a scenario that meant that a peer can end up on a previous commit despite having the latest commit beforehand. The scenario was discovered by the following interactions.
There are 3 peers, A, B, and Seed.
- A creates a project
Xand announces it toSeed -
Seedreplicates the project and has commitP -
Breplicates the project fromSeedand has commitP -
Apushes a commitQand announces toSeed -
Seedreplicates fromA -
Seedannounces toB -
Breplicates fromSeed, which in turn kicks offrere(mutual replication) -
rerewins the race against the replication ofBfrom theSeed -
Seedreplicates and has commitP-- the initial commit -
Breplicates fromSeedand stays at commitP
Initially, we thought it was messing up by setting the wrong force value, but after setting it to false the situation was not remedied.
The issue can be replicated using two local repositories and a script using git2 to fetch an outdated branch.
Digging into the issue further, we did some spelunking in the libgit2 code to see how the force flag might be used. From what we could see, it wasn't be used at all and we found this issue which also agrees that the force flags aren't respected.
It seems we will have to work around this until a patch is (possibly) added. One solution we've mentioned is having some kind of staging area for references that we fetch into and check if they are fast-forwards or not.