Hi Junio, What I mean by "behave like push" is the following: [remote "foo"] url = ... fetch = refs/users/bob/heads/*:refs/heads/* #Note that the fetch and push configuration match. push = refs/heads/*:refs/users/bob/heads/* git ls-remote foo refs/heads/master git push foo master refs/heads/master -> refs/users/bob/heads/master git fetch foo master refs/heads/master -> FETCH_HEAD In this case, the fetch commit isn't the same as the one we just pushed! Yes, I agree that the abbreviation expansion works as designed (using the rev_parse_rules), but the point of that email is that those rules become counter-intuitive when you configure a fetch refspec. You specifically tell git that you don't care about refs/heads/* and all you care about is refs/users/bob/heads/*, why would it go and fetch refs/heads/master? Of course, you should still be able to fetch it when you explicitly asks for it but the configured refspec should take precedence over the default rev_parse_rules. Maybe more people could give their opinion as to whether this would be more intuitive or not. I (and other people I've asked) find the current behaviour counter-intuitive. Our opinion seem to differ because you consider the 'master' abbreviation as being explicit. In my opinion, explicit means 'refs/heads/master' and an abbreviation is absolutely not explicit. If a patch wouldn't be welcome I'll fix it with aliases or a plugin. -Lewis On Tue, Apr 8, 2014 at 9:45 PM, Junio C Hamano <gitster@xxxxxxxxx> wrote: > Lewis Diamond <me@xxxxxxxxxxxxxxxx> writes: > >>>> 'git fetch foo master' would result in (FETCH_HEAD omitted): >>>> [new ref] refs/heads/master -> foo/master //OK, but missing another >>>> ref! (case 2) >>>> //It should also fetch refs/users/bob/heads/master -> foo/bob/master >>> >>> This is an incorrect expectation. >> >> Indeed this is the "correct" behaviour since it works as designed. >> However, this behaviour is inconsistent with the push command. An >> expectation is never "incorrect" as we are talking about intuitive vs >> non-intuitive. >> >>> >>> The user who gave the command line said only "master", and did not >>> want to grab "users/bob/heads/master". If the user wanted to get it >>> as well, the command line would have said so, e.g. >>> >>> git fetch there master users/bob/heads/master >>> >> >> Actually, the user specifically configured the remote to fetch >> refs/users/bob/heads/*, meaning "those are the branches I'm interested >> in". >> >>>> If you remove this configuration line: fetch = >>>> +refs/heads/*:refs/remotes/foo/* >>>> Then you run 'git fetch foo master', this would result in: >>>> * branch master -> FETCH_HEAD //Debatable whether this is OK or not, >>>> but it's definitely missing bob's master! (case 3) >>> >>> Likewise. >>> >>> The 'master' short-hand is designed not to match refs/users/any/thing. >> >> Sure, this shorthand is designed to match refs listed in the rev parse >> rules list. However, a quick survey showed me that most people would >> expect their configuration to be honoured when using the shorthand for >> fetching (like it is for push). This thread is about improving the >> fetch command so that the short-hand works in such cases (and make it >> consistent with what push does). > > Now, I am puzzled, as I do not think push behaves in such an insane > way. You got me worried enough that I had to make sure (see below). > > Perhaps there is some misunderstanding. > > With two repositories src and dst, I prepared these in src: > > $ git ls-remote ../src > cae2fe07f0954772ec9d871391313cb91a030cba HEAD > cae2fe07f0954772ec9d871391313cb91a030cba refs/heads/master > cae2fe07f0954772ec9d871391313cb91a030cba refs/users/bob/master > > and then this config in dst/.git/config: > > [remote "origin"] > url = ../src > fetch = +refs/heads/*:refs/remotes/origin/* > fetch = +refs/users/bob/*:refs/remotes/bob/* > push = refs/heads/*:refs/users/alice/* > > Now, from such an empty dst repository: > > $ cd dst > $ git fetch -v origin > From ../src > * [new branch] master -> origin/master > * [new ref] refs/users/bob/master -> bob/master > $ git reset --hard origin/master > $ git ls-remote . > cae2fe07f0954772ec9d871391313cb91a030cba HEAD > cae2fe07f0954772ec9d871391313cb91a030cba refs/heads/master > cae2fe07f0954772ec9d871391313cb91a030cba refs/remotes/bob/master > cae2fe07f0954772ec9d871391313cb91a030cba refs/remotes/origin/master > > $ git commit --allow-empty -m another > $ git push -v origin master > Pushing to ../src > Counting objects: 1, done. > Writing objects: 100% (1/1), 185 bytes | 0 bytes/s, done. > Total 1 (delta 0), reused 0 (delta 0) > To ../src > cae2fe0..faae8fb master -> refs/users/alice/master > > Redoing the same experiment with this config with an extra item in > dst/.git/config: > > [remote "origin"] > url = ../src > fetch = +refs/heads/*:refs/remotes/origin/* > fetch = +refs/users/bob/*:refs/remotes/bob/* > push = refs/heads/*:refs/users/alice/* > push = refs/remotes/bob/*:refs/users/bob/* > > gives the same. > > ... the same procedure to prepare 'master' that is one commit > ... ahead with "allow-empty" > $ git update-ref refs/remotes/bob/master HEAD > $ git push -v origin master > Pushing to ../src > Counting objects: 1, done. > Writing objects: 100% (1/1), 185 bytes | 0 bytes/s, done. > Total 1 (delta 0), reused 0 (delta 0) > To ../src > cae2fe0..faae8fb master -> refs/users/alice/master > > We do not look at remotes/bob/master we have, and we do not touch > users/bob/master at the remote site, either. > > When you explicitly say what you want to push on the command line, > that is what you are telling Git to push. 'master' which is an > abbreviation of refs/heads/master. Where it goes may be determined > by using remote.origin.push as a mapping, but the left hand side of > the mapping is still what you gave from the commad line (after > dwimming the abbreviated refname exactly the same way other commands > like "git log master" interpret them). > > This is very much deliberately so and unlikely to change. And that > goes the same for fetching as well. > > The command line interface is optimized for the two most common use > cases. Either you want to fetch everything you are interested in > (in which case you do not say what you want to fetch on the command > line and let the configured refspecs kick in), or you want to > explicitly want to state what you want. Allowing random set of refs > that happens to match left hand side of wildcard patterns of refspec > will break the expectation big time, when somebody asks "git push > origin master" meaning "I want to push my 'master' branch out" (or > "git pull origin master" meaning "I want to merge the master branch > from the origin") and you instead push out "remotes/bob/master" (or > even worse, create an octopus merge with origin's master and bob's > master). > > Hope this clarifies the confusion. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html