Thread (4 messages) 4 messages, 3 authors, 2016-06-15

Re: [RFC] Reverting "git push logic change"?

From: Daniel Barkalow <hidden>
Date: 2016-06-15 22:42:17

On Fri, 20 Jan 2006, Junio C Hamano wrote:
The change introduced by 9e9b267 commit broke "correct" usage of
git push to push matching refs, to work around a problem
observed in a usage pattern on a shared repository.

I think I made a bad judgement in evaluating the scenario, and
made a bad change to "fix" a problem that did not exist.  I
apologize for having caused this confusion.

My conclusion after thinking about the problem again is that we
would be better of if we reverted that commit.  This message is
to make my intention clear, and solicit objections or comments
from the list.

The use case that prompted this change was this:

 - A shared repository is created by cloning Linus repository.
   This repository gets "origin" (then-current Linus master) and
   "master" (the same).

	$ git clone --naked \
          git://git.kernel.org/.../linux-2.6.git/ project.git

 - Two developers use this as their shared repository.  They
   first start out by cloning from it, do their development in
   their "master" branch and pushing back to the "master" branch
   of the shared repository.  Their workflow is:

	0. Clone it (once per developer):
        $ git clone ssh://pub.example.com/project.git/ work

	1. To make sure the developers are in sync:
	$ git pull ssh://pub.example.com/project.git/ ;# (a) or
	$ git pull origin			      ;# (b)

        2. His own development:
	$ edit;compile;test;git commit

	3. Pull from upstream, to avoid conflicts with it (only when needed):
	$ git pull git://git.kernel.org/.../linux-2.6.git/

	4. Push back the result to shared repository:
        $ git push ssh://pub.example.com/project.git/

With this workflow, in the two developer repositories, "origin"
branch is not really well maintained.  If "git pull origin" was
used with the remotes/origin file "git clone" initially gave
him, it would have kept track of the latest push into the shared
"master" closely, but if the explicit URL was used, "origin" of
the developer repository would have been left behind.

This is not problem as far as the correctness of the "master"
branch is concerned.  The fast-forward check when pushing into
the shared repository "master" branch prevents the two
developers from losing commits.  In other words, either way to
pull from the shared repository is legal/valid.

However, the push done in step 4. triggers the default "push all
matching refs" behaviour.  All three repositories have "origin"
and "master", which means this results in "origin" being updated
in the shared repository.  But one developer repository has a
stale "origin" while the other developer has an up-to-date
"origin".  This triggers a "not a fast forward" error, which
does not cause the push of "master" to fail, but still looks
worrisome.
I think there are a number of good solutions:

 - Make the case of a pure rewind (i.e., pushing something that would be a 
   fast-forward in the other direction) have no effect and give a more 
   positive message like 'Remote "origin" is already ahead of your 
   version.' I expect that something of that sort would comfort the users 
   and distinguish branches that you're not actively using and have fallen 
   behind on from branches that you are using, but someone else is also 
   using. This seems like a good idea even if we do other stuff.
 - Have a command to write, report, and modify remotes files, so Greg can 
   tell it exactly what he actually wants without mucking around with the 
   files by hand. Also generally nice.
 - Require --all in push, but, if none are given, produce a summary of 
   what you could specify instead of assuming you mean to push nothing. 
   Then Greg would see master:master as the obvious thing, and do that.
 - Maybe "git clone" should add "Push: master:master" by default if the 
   URL permits pushing?

I think that having it default to matching branches isn't really ideal, 
since that seems to me to work for practically everybody only by 
coincidence: master:master is by far the most common case; then 
there are some people who use multiple branches, but they must have done 
something other than the default to create this situation, anyway; then 
there's the case where "master" isn't a head on both sides, but (at least 
in my experience), master:master is still what the user means (case 
happens when pushing a first commit from a clone of an empty repository). 

Maybe the default should be master:master? It seems to fit the general 
pattern of defaulting to master. Or maybe (what HEAD points to):(matching 
branch), or (but I'm not too comfortable with this one) HEAD:master.

	-Daniel
*This .sig left intentionally blank*
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help