git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 1/3] fetch: add --allow-local option

From
Junio C Hamano <gitster@pobox.com>
Date
May 19, 2013, 05:51 UTC
Message-ID
<7vtxlz1pr1.fsf@alter.siamese.dyndns.org>
In-Reply-To
<CAMP44s3xdWzVviPvrN7D1fTG6Lwgg-dEzju--VuiwZA-8bV+MQ@mail.gmail.com>
Felipe Contreras <felipe.contreras@gmail.com> writes:
Show 21 quoted lines
> On Fri, May 17, 2013 at 1:30 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>>
>>> This is irrelevant, it's an implementation detail of 'git pull'. *THE
>>> USER* is not running 'git fetch .'
>>
>> To those who fear running "git pull", the following has worked as a
>> quick way to "preview" what they would be getting.
>>
>>         git fetch
>>         git log ..FETCH_HEAD
>>
>> and then they can "git merge FETCH_HEAD" to conclude it, or run a
>> "git pull" for real.  We teach the more explicit form to end users
>> in our tutorial,
>
> That "tutorial" is mostly irrelevant; it has not been properly updated
> in years, and it doesn't do it's job properly.
>
> Nowadays most people use the Pro Git book, which doesn't mention
> FETCH_HEAD even once. And why would it?

Because the book was written by those who did not know about its use, and I do not necessarily think it is their fault. Our own documentation can use updates.

Patches to the tutorial to explain (you can refer to postings by people who discuss on public "users help other users" site like stackoverflow) the equivalence of the "git pull" == "git fetch" followed by "git merge FETCH_HEAD" better than it currently does is welcome. IIUC, ProGit is maintained in public and you can send patches to it, too.

Users of stackoverflow seem to know about and how to use FETCH_HEAD:
    http://stackoverflow.com/questions/9237348/what-does-fetch-head-in-git-mean
    http://stackoverflow.com/questions/11478558/fetch-head-not-updating-after-git-fetch

and they expect exactly what I described in the earlier message. If you ask your search engine about "FETCH_HEAD", you would find other real-world use of it as well (one of them I found was about somebody requesting to teach TortoiseGit to offer FETCH_HEAD as a candate to be merged, IIRC).

Incidentally, this discussion on our own list
    http://thread.gmane.org/gmane.comp.version-control.git/42788/focus=42798

shows that I was originally not very keen to defend "fetch, then inspect with log FETCH_HEAD, and then finally merge" workflow to keep working myself [*1*], which is somewhat funny.

So, no, it is not my whim, but people do depend on "git fetch" that updates FETCH_HEAD to what is to be merged with "git pull".

Show 10 quoted lines
>> So when "the user" is running "git fetch" on "mywork" branch that
>> happens to be forked from a local "master",...
>> we still need to have FETCH_HEAD updated to point at what we would
>> be merging if she did a "git pull".
>
> No, we don't need that. That is only needed by 'git pull', and in
> fact, it should be possible to reimplement 'git pull' so that it skips
> FETCH_HEAD when the remote is local.
>
> These are mere implementation details.

You seem to be incapable to understand what backward compatibility is. It is not about "keep only what I use myself, I think others should use, and/or I understand, working, and destroy everything else".

Also your "special-case local repository and fetch from 'origin'" breaks down once your users need to work on a project with subsystem maintainers.

Imagine one clones from me (i.e. git.git is her upstream), and forks her fh-octopus branch out of her master branch ("git clone" arranges the latter to be a fork of origin/master taken from me). She helps git-svn and has Eric's repository as her "git-svn" remote (because my tree lags behind Eric's tree with respect to git-svn). Her local git-svn branch is a fork of Eric's master, and she has her svn-ext branch that is a fork of it [*2*].

    git clone git://git.kernel.org/pub/scm/git/git.git git
    cd git
    git checkout -t -b fh-octopus master
    git remote add git-svn git://git.bogomips.org/git-svn.git/
    git checkout -t -b git-svn git-svn/master
    git checkout -t -b svn-ext git-svn

She has four local branches, master, fh-octopus, git-svn, and svn-ext. Is this a too-contrived example? I do not think so.

On any of these branches, she can say
    git pull [--rebase]

without having to be constantly aware of what branch (either remote or local) the work on her current branch builds on. Like some people in the thread $gmane/42788 discussion, she may prefer to do the same integration with "first fetch, inspect and then integrate" workflow, relying on the equivalence "git pull" == "git fetch" + "git merge/rebase":

    git fetch
    git log ..FETCH_HEAD
    git merge FETCH_HEAD
But when she does this:
    git checkout fh-octopus
    git fetch
the "git fetch" does not fetch from me (i.e. her 'origin').
Would she be unhappy?
I agree that it could be argued so.

After all, she is working on a topic that is eventually based on my 'master' and the only reason she forked from her 'master' is because she may have other changes of her own on her 'master' that are not necessarily related to her fh-octopus topic. She wants her "git log @{u}.." not to show those unrelated changes on her 'master', but wants to rebase against her 'master'.

Because her @{u} does not refer to 'origin/master' taken from me (it refers to her local 'master'), however, even if we change "git fetch" to fetch from 'origin', what "git log ..@{u}" shows does not change, so the only "improvement" is that it does not trigger "I said 'git fetch' but it did not fetch anything? Did I make some mistake?" confusion.

Is that lack of confusion a big enough improvement, or is it easy enough for her to realize that what she wanted to inspect was what I've been doing in the meantime and run "git fetch origin"?

I know you would say it is an improvement; I am on the fence in the sense that no confusion is better than confusion, but that is a qualified "on the fence". I do not mind it fixed as long as the confusion avoidance does not regress other aspects of the operation we have kept working for people.

But more importantly, what should happen when she is working on her svn-ext branch?

    git checkout svn-ext
    git fetch

This does not fetch from me (i.e. her 'origin'), either. If this fetched from me, would she be happier?

It could be argued that it might be better if it fetched from Eric; after all she is working on svn-ext that eventually reaches Eric's tree. But fetching from me while she is working on svn-ext does not make any sense at all in her set-up, does it?

As I already said, I am OK with an enhancement that does (an equivalent of) the following:

 - Teach "git fetch --no-fetch-head <any args>" an option that
   causes it to do everything "git fetch <any args>" would do,
   except that in that mode, it does not touch FETCH_HEAD at all
   (the "--append" option that changes the behaviour of "git fetch"
   to only change what happens to FETCH_HEAD can be thought of a
   precedent).
 - Only when 'git fetch' (with no parameters, i.e. relies on
   configured defaults) is to fetch from '.':
   - First internally fork and run "git fetch --no-fetch-head
     <remote>" from the <remote> found by the following loop:
    - Set a variable B to the name of the current branch 
    - while branch.B.remote is the local repository:
      - assign the branch the branch B forked from,
        i.e. branch.B.merge, to variable B
    - branch.B.remote is the first remote repository in the fork
      ancestry chain.  That is the <remote> we are looking for.
   - Then do the usual 'git fetch' against the local repository,
     leaving what is to be merged in FETCH_HEAD as usual.
 - (optional) make the second "special case" opt-in, as people who
   have known Git may be upset when their "git pull" that they know
   would go to local repository touches network.  I do not think it
   is a huge deal, though, and that is why I marked it as optional.

I think that would alleviate the puzzlement some people may feel when they run 'git fetch' on a branch that integrates with their local branch, and sees no objects are transferred. It would do so without breaking anything.

Anything that breaks the "pull=fetch+merge" equivalence is not acceptable and no loud repeating from you will change that, with or without patches.

We owe at least that much to the people who asked us to keep it working over time and those who responded to them by working on maintaining it over time.

[Footnotes]
*1* Back then, FETCH_HEAD did not have the commit to be merged
    necessarily on the first line, so it was not very easy to work
    with it.  But that was fixed by 96890f4c428e (write first
    for-merge ref to FETCH_HEAD first, 2011-12-26), has been with us
    since v1.7.9, and the fix was not made by me, but Joey Hess.
*2* The invariant "git pull <fetch params>" == "git fetch <the same
    fetch params>" + "git merge FETCH_HEAD" (for any <fetch params>,
    including empty) has been true forever, and over time we made
    sure it hold true when we introduced new features because people
    depended on it, with commmits like these:
     - 85295a52e683 (git-merge: Put FETCH_HEAD data in merge commit
       message, 2007-03-22)
     - 96890f4c428e (write first for-merge ref to FETCH_HEAD first,
       2011-12-26)
    A remaining known bug is when the pull is to create an octopus,
    because "git merge FETCH_HEAD" currently can resolve FETCH_HEAD
    as only one commit.  The fh-octopus topic would extend the itch
    these two fixes started to scratch by teaching "git merge" to
    expand FETCH_HEAD into all commits that are not marked as
    not-for-merge to finish scratching that itch.
    svn-ext may teach git-svn to express a svn external as a git
    submodule.
Previous: Felipe ContrerasNext: Felipe Contreras
Message 21 of 31 in “fetch: fix '.' fetching”
  1. 0/3 fetch: fix '.' fetchingFelipe Contreras, May 16, 2013
  2. 1/3 fetch: add --allow-local optionFelipe Contreras, May 16, 2013
  3. Ramkumar RamachandraMay 16, 2013
  4. Felipe ContrerasMay 16, 2013
  5. Ramkumar RamachandraMay 16, 2013
  6. Felipe ContrerasMay 16, 2013
  7. Ramkumar RamachandraMay 16, 2013
  8. Felipe ContrerasMay 16, 2013
  9. Ramkumar RamachandraMay 16, 2013
  10. Felipe ContrerasMay 16, 2013
  11. Junio C HamanoMay 16, 2013
  12. Felipe ContrerasMay 16, 2013
  13. Junio C HamanoMay 16, 2013
  14. Felipe ContrerasMay 16, 2013
  15. Junio C HamanoMay 16, 2013
  16. Felipe ContrerasMay 16, 2013
  17. Junio C HamanoMay 16, 2013
  18. Felipe ContrerasMay 17, 2013
  19. Junio C HamanoMay 17, 2013
  20. Felipe ContrerasMay 18, 2013
  21. Junio C HamanoMay 19, 2013
  22. Felipe ContrerasMay 19, 2013
  23. About overzealous compatibilityFelipe Contreras, May 19, 2013
  24. Felipe ContrerasMay 19, 2013
  25. Philip OakleyMay 18, 2013
  26. Felipe ContrerasMay 18, 2013
  27. Philip OakleyMay 18, 2013
  28. Felipe ContrerasMay 18, 2013
  29. Junio C HamanoMay 19, 2013
  30. 2/3 fetch: switch allow-local off by defaultFelipe Contreras, May 16, 2013
  31. 3/3 remote: disable allow-local for pushesFelipe Contreras, May 16, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.