git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Interleaved remote branch update problems

From
Jeff King <peff@peff.net>
Date
Apr 6, 2012, 06:09 UTC
Message-ID
<20120406060947.GB25301@sigill.intra.peff.net>
In-Reply-To
<9a97881f-a49e-47b2-9c14-b067bc7a525c@email.android.com>
On Thu, Apr 05, 2012 at 11:32:40PM -0600, Martin Fick wrote:
Show 6 quoted lines
> >Yes, that's expected. --force means "it's OK to push something that
> > will rewind history", not "it's OK to clobber somebody else who is
> > pushing at the same time".
> 
> But why is it ok to clobber somebody else right after they pushed,
> this seems like splitting hairs?  Why force me to wait to clobber?

Because it gives you a chance to take it back. You have told git "it is OK to move from A to B, even if that is a rewind". You did not tell it "it is OK to move C to B". Imagine your workflow is:

  1. Try to push B, and see that the remote is at A; your push is
     rejected.
  2. Examine "git log --graph A...B" and see that yes, your B is an
     amendment over A, and so it is OK to push. Or maybe you just happen
     to know what B and A are, because you just pushed a broken A and
     are amending it, in which case you can skip the log. But the point
     is that the user makes a decision about the case.
  3. Do "git push -f" to approve writing B over A.

If somebody else has built C on top of A, and pushed it during (3), then you don't necessarily want to clobber it; you should repeat your analysis from (2) and make a new decision.

The astute reader will notice that somebody might have pushed C between steps (1) and (3), and therefore the second "push -f" may overwrite their C, even though that was not what was intended by the user. The git protocol already says "I am expecting to move ref R from A to B". The problem is that the interface is mis-designed for this workflow. The first push should note "A" somewhere on disk, and the second "git push -f" should really be "git push --retry-with-force", and check to make sure that our starting point really is "A".

I suspect nobody has complained so far because it is a race condition that just doesn't come up unless you have an extremely busy repository with lots of force pushes.

> And what about the fast forward case?  If client A is pushing change a
> and then client B starts pushing b which depends on a, why shouldn't B
> succeed as long as A succeeds first, even without the force flag?  But
> it does not work this way even with the force flag.

Right. Because the force flag is about history rewinds, not about clobbering simultaneous pushes.

Don't get me wrong; I can see the use for an option to clobber a simultaneous push in some workflows. I just think that there is value in distinguishing it from what "force" does now.

Show 8 quoted lines
> I think this use case distinction is irrelevant to users on a shared
> server unless you could somehow tell git to "only clobber the branch
> if it currently points to shax".  Which is sort of what git is
> pretending to do, but it isn't really since the user isn't specifying
> shax, it is determined when the push starts and is inherently subject
> to a race.  It's not like the user can safely determine what the
> remote branch points to before they update it to see if it is ok to
> clobber it.

Right. And I think that is a bug (or an interface misdesign), albeit one that doesn't come up much. But I'd rather not make it worse by losing what safety we have.

-Peff
Previous: Martin Fick
Message 4 of 4 in “Interleaved remote branch update problems”
  1. Martin FickApr 5, 2012
  2. Jeff KingApr 6, 2012
  3. Martin FickApr 6, 2012
  4. Jeff KingApr 6, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.