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*