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

Re: Pull is Mostly Evil

From
Junio C Hamano <gitster@pobox.com>
Date
May 6, 2014, 22:06 UTC
Message-ID
<xmqqy4yed0jq.fsf@gitster.dls.corp.google.com>
In-Reply-To
<20140502214817.GA10801@sigill.intra.peff.net>
Jeff King <peff@peff.net> writes:
> I realize this has veered off into talking about an "update" command,
> and not necessarily "pull", but since there a lot of proposals floating
> around, I wanted to make one point: if we are going to do such a switch,
> let's please make it something the user explicitly turns on.

I mentioned "update" in an attempt to suggest some way to avoid breaking "git pull" for people who do want to advane the history with real work (i.e. not just following along with fast-forwarding).

A failed "git push" that suggests to pull first, which came from the original "To emulate CVS workflow, you can pull, work, push, and if the push fails, pull again and then push" in the early tutorial, turns out to be very bad in the "trunk" centric worldview. And I think the solution is to realize that we use "git pull" for two fairly differnt workflows.

 - You know you own the tip of the "trunk" (in the global view).
   You merge from other people to advance the global world view in a
   way that makes sense in the "first-parent chain is the trunk"
   worldview.  That is what "git pull [--no-ff]" was designed to do,
   and it does it very well.
 - You have some work of yours (either you committed directly, you
   merged your own work done on a side branch, or you merged from
   other people using "git pull") on top of a commit that used to be
   at the tip of the global world.  You want to make sure that
   branch you are on is not missing what has happened while you are
   not communicating with the outside world.

The problematic case is the latter, and by introducing a new command to do that well (which is *not* just about "swapping the order of the parents", by the way), updating the "leaf developer" section of "Everyday Git" document and tutorials, and suggesting to use that upon failed "git push", I think users would get a more pleasant experience. And move "git pull" into "integrator" section, a command that is not necessary for leaf developers.

I am not married to the name "update". I think the ideal behaviour of that "leaf-developer" command would be something along the lines of the following:

 - If we can fast-forward, do so and we are done.
 - Otherwise, we have a history of this shape:
        ----O    
             \
    -----A----B----C
          \
           X---Y---Z
   where A was where we forked, B was a merge the user made, C was a
   commit the user directly made, and X, Y, and Z (some of them may
   be merges) are the "trunk" history  "git pull" would create a
   merge M whose parents are <C Z>, which is wrong from the
   "first-parent is the trunk" worldview.
   But recording the merge to have parents <Z C> does not give us
   "the first-parent is the trunk" worldview, in the presense of B.
   We would prefer to end up with a history more like this:
    -----A       ----O
          \           \
           X---Y---Z---B'--C'
   so that your work, your contribution with two commits of yours,
   was to merge the work done on a side branch and then made one
   commit directly on top of it.
   Hence, I think the ideal behaviour of the new command is to
   replay the first-parent history on top of the updated tip of your
   upstream (which by the way is different from how "rebase
   --preserve-merges" works; it is more like how J6t wanted to make
   "rebase --preserve-merges" work, IIRC).

After that, you can attempt to push, and it may fail again (because somebody has grown the shared history to have a child W of Z at the tip), in which case exactly the same "git update" would attempt to recreate a history of this shape:

    -----A           ----O
          \               \
           X---Y---Z---W---B"--C"

During a long transition period (essentially, waiting for the current crop of documents and tutorials to die out), we will need extra safety to prevent people, who merely wanted to bring their branch up to date, from running "git pull", and I think the command needs to:

 - check which branch of what repository it is trying to pull;
 - check which branch of what repository it is going to update if
   "git push" is given;
 - if they are the same, then you are attempting to update from your
   upstream, so either warn or error out.  If we are going to warn
   but make a merge anyway, the warning message *must* come at the
   very end of the output (and tell the user the way to recover is
   to reset one away and run the other command).
Or something like that.
Previous: David KastrupNext: Felipe Contreras
Message 22 of 50 in “Pull is Mostly Evil”
  1. Marc BranchaudMay 2, 2014
  2. David KastrupMay 2, 2014
  3. Philip OakleyMay 2, 2014
  4. Felipe ContrerasMay 2, 2014
  5. Philip OakleyMay 2, 2014
  6. Jonathan NiederMay 2, 2014
  7. Philip OakleyMay 3, 2014
  8. Felipe ContrerasMay 2, 2014
  9. Philip OakleyMay 3, 2014
  10. Felipe ContrerasMay 3, 2014
  11. David LangMay 2, 2014
  12. David KastrupMay 2, 2014
  13. Junio C HamanoMay 2, 2014
  14. Felipe ContrerasMay 2, 2014
  15. Junio C HamanoMay 2, 2014
  16. Felipe ContrerasMay 2, 2014
  17. Jeff KingMay 2, 2014
  18. Felipe ContrerasMay 2, 2014
  19. Jeff KingMay 2, 2014
  20. Felipe ContrerasMay 2, 2014
  21. David KastrupMay 3, 2014
  22. Junio C HamanoMay 6, 2014
  23. Felipe ContrerasMay 6, 2014
  24. Richard HansenMay 3, 2014
  25. David KastrupMay 3, 2014
  26. Felipe ContrerasMay 3, 2014
  27. David KastrupMay 3, 2014
  28. David LangMay 4, 2014
  29. Felipe ContrerasMay 4, 2014
  30. David KastrupMay 4, 2014
  31. James DenholmMay 4, 2014
  32. David KastrupMay 4, 2014
  33. Felipe ContrerasMay 4, 2014
  34. James DenholmMay 4, 2014
  35. David KastrupMay 4, 2014
  36. Felipe ContrerasMay 3, 2014
  37. Richard HansenMay 3, 2014
  38. Felipe ContrerasMay 4, 2014
  39. Richard HansenMay 4, 2014
  40. Felipe ContrerasMay 4, 2014
  41. Richard HansenMay 4, 2014
  42. Felipe ContrerasMay 4, 2014
  43. Richard HansenMay 5, 2014
  44. Felipe ContrerasMay 5, 2014
  45. Max KirillovMay 7, 2014
  46. John SzakmeisterMay 3, 2014
  47. Richard HansenMay 5, 2014
  48. Felipe ContrerasMay 5, 2014
  49. Philip OakleyMay 2, 2014
  50. Marc BranchaudMay 9, 2014

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.