Re: The fetch command should "always" honor remote.<name>.fetch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]