If you write
git push $remote tag $string
it is handled exactly as if you wrote:
git push $remote refs/tags/${string}:refs/tags/${string}
and if you write
git push $remote master
it is handled exactly as if you wrote:
git push $remote master:master
The manual correctly describes the above, but the issue the fix
addresses is about what happens to that 'master' string that
follows the colon, and the 'master' string becomes ambiguous if
the remote end uses separate-remote layout.
The way this command:
git push $remote $src:$dst
is handled is:
(0) send-pack gets ls-remote equivalent from the remote. This
tells us the set of refs the remote has and the value of
each of them.
(1) $src can be a ref that is resolved locally the usual way.
You could have any valid SHA-1 expression (e.g. HEAD~6).
(2) $dst is compared with the list of refs that the remote
has, and unique match is found. So if the set of refs the
remote side has:
refs/heads/origin
refs/heads/master
refs/tags/v1.0.0
and if $dst is 'master', refs/heads/master is what will be
updated.
(3) Then send-pack generates and sends the necessary pack to
update the remote side with objects needed for $src, using
the knowledge of what the remote has. Also, send-pack
instructs the remote to update which ref with what value.
Continuing with the example, it tells the remote to update
its refs/heads/master with the value of our 'master'.
That *matching* in step (2) is what the fix is about.
The matching code of send-pack from the beginning has been the
unique tail-match. When the other end had a branch 'bugfix' and
a tag 'bugfix', then both of them would match because both
refs/heads/bugfix and refs/tags/bugfix ends with 'bugfix'
('gfix' does not match 'refs/heads/bugfix' -- we are not that
stupid ;-).
So you had to disambiguate this case by saying heads/bugfix if
you want to push the branch. That was fine between branches and
tags, since having a branch and a tag with the same name is
usually not done in order to keep user's sanity.
However, separate-remote layout poses a more serious problem,
because most of the time you would expect to see similar names
under refs/heads/ and refs/remotes/origin/ directories. If we
kept the original ref matching code, a cloned remote would have
both refs/heads/master and refs/remotes/origin/master almost
always, so somebody who is pushing 'master' to such a remote
would have had to disambiguate it by saying:
git push heads/master
which is (as described in the part of the manual you quoted) a
shorthand for
git push heads/master:heads/master
'heads/master' before the colon is used to find out which commit
in your local repository we are pushing, and 'heads/master'
after the colon is used to match against the list of refs from
the remote (which contains both 'refs/heads/master' and
'refs/remotes/origin/master'), and only because the user said
'heads/master' (not just 'master') this avoids ambiguity.
Even under separate-remote layout, we would want to be able to
say:
git push master
to mean we want to push to remote's heads/master when the remote
has remotes/{origin,blech}/master.
And that is what the fix is about.
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html