Ramkumar Ramachandra <artag...@gmail.com> writes:
> I agree with you largely, but I would still argue that choosing a
> destination based on the current branch is a historical mistake made
> by "matching".
"matching" is not necessarily a good default for everybody, and we
are fixing that historical mistake in Git 2.0.
Step back and think again. "matching" has never been about where the
push goes. It is about what are pushed out, once you decide where
If a user often wants to push out a branch as soon as he made a
commit on it (even when other branches that go to the same
publishing point should not be pushed out yet), an instructoin "Ok,
I'll push to that repository" that pushes all matching branches will
not work well, because it will publish uncooked other branches, too.
That is the historical mistake of making "matching" the unconfigured
default. The historical mistake of "matching" does not have anything
to do with the choice of "where to push". It is only about "what to
If you re-read your three-remote example involving "upstream" (me),
"ram" (your wip publishing point) and "peff":
you'll see that the only reason why you thought you need the hack to
set pushremote to null was because you did _not_ use matching. It
illustrates one reason why blaming matching for selection of
destination misses the point.
In any case, dispelling a misplaced blame on "matching" is not the
main point of this message.
> With this patch, users must mandatorily know about
> remote.pushdefault and branch.<name>.pushremote, if they want to
> work in multiple-remote scenarios.
I am afraid that it is neither sufficient nor a good solution.
I do not necessarily think that the best course is to devise an
unintuitive (to unsuspecting users) set of rules and force users to
understand it. That is where my secondary unhappiness comes from,
and that was why I said that limiting the magic only to a very
simple and easy to understand case might make it more sellable.
"git push" that pays attention to "branch.*.remote" was the original
To casual users with push.default=current/upstream, the two branches
(my current branch? the branch I am pushing out?) have always been
the same when branch.*.remote is used. These users don't even have
to think about the distinction between the two [*1*]. But the
distinction starts mattering once you start wishing to omit saying
_where_ to push, because at that point, _what_ to push is the only
thing the user would give us, but the end users are not used to see
the destination chosen based on what is being pushed out.
The new branch.*.pushremote does not alleviate this confusion. It
gives the same "when on this branch, we push out to that remote"
(and not "when pushing this branch out, it goes there" impression.
The new remote.pushdefault _is_ a definite improvement: "If I do not
say where to push, this is where things go". It makes a very clear
statement, and does not have that confusion.
> - In git push master, master is verified not to be a path on the
> filesystem, not a remote, and finally a local branch.
> - In git push master:next, master:next is interpreted as a destination.
Ideally it should notice and diagnose it as a syntax error and error
out (of course an attempt to locate master: URL handler will fail,
but that is less nice).
> - In git push master next:pu, master is verified as usual, and next:pu
> is pushed to the remote specified by next. My patch currently does
> this (checks that <src> and <dst> are branches).
I am not sure what you mean by "and next:pu is...". If "git push
next:pu master" should error out without mistaking "next:pu" as
destination, so should "git push master next:pu", I think.
The last one is also the same. The "guess destination" magic should
kick in only when we can verify _all_ the refs we are pushing out
are simple ones (branch names, and possibly tag names), and the
behaviour should not depend on the order. Anything more complex is
I personally think it is much more sellable to use an even simpler
rule than what Jeff suggested, to make
git push -- <refspec>
go to the remote.pushdefault (falling back to remote.default that is
"origin"), without even paying attention to what branch you are on,
and ignoring branch.*.remote/pushremote configuration.
That is sufficient to support the triangular, the publish-to-mine,
and the centralized workflows, no? In any of these cases, the
repository you push out to is _one_, even though it may be a
different one from where you pull from. If you have a very special
branch that goes to a different place than all the other branches,
you can always push out while on that branch without any refspec,
*1* If you really think about what branch.*.remote is _for_, it says
"I want this branch to integrate with that branch at this remote".
If the user were to push the branch out using the configuration, it
is more logical to think of it as "When pushing this branch out, it
goes there", and not as "When I am on this branch and say 'git
push', 'git push' pushes there".
But that is clear and logical _only_ to Git-heads who have thought
about this hard enough.
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html