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

[RFC PATCH 00/35] git update: fix broken git pull

From
Felipe Contreras <felipe.contreras@gmail.com>
Date
Jul 5, 2021, 12:31 UTC
Message-ID
<20210705123209.1808663-1-felipe.contreras@gmail.com>

Throughout the years many big threads have been started [1] [2] [3] [4] [5] [6] because `git pull` is broken (for everyone that isn't a maintainer), and nothing has been fixed.

The two main problems are:
  1. The order of the parents is the opposite of what it should be
  2. By default it should fail unless it's a fast-forward

However, every attempt to fix these issues gets entangled in an inescapable web of interrelated problems.

That's because `git pull` is in fact *two* commands pretending to be one.

I have spent several days re-reading old threads looking for anything related to `git pull` and fast-forward throughout the entire history of the git mailing list, going as far back as 2008.

This process has been illuminating.

The amount of people that have pondered about, and even suggested, a `git update` command is striking:

 * Linus Torvalds: [7]
 * Junio C. Hamano: [8]
 * Richard Hansen: [9]
 * John Keeping: [10]

And of course me [11], who not only suggested it, but implemented it as well [12].

It's not just the name, but the behavior too:
  `git fetch` + `git merge --ff-only`

This way `git pull` can be used by maintainers to integrate pull requests, and `git update` for everyone else (normal developers) to update their local branch to its upstream.

Plus it has a --merge mode that creates a merge commit, but with the parents in the right order (master to upstream, not upstream to master).

Both problems are fixed by this approach.

Also, a thorny issue since a long time ago has been how to properly advise users what to do in case a fast-forward is not possible.

I propose a new command: `git fast-forward`. When a fast-forward is not possible `git fast-forward` fails, and shows an advice (that can be easily turned off).

Therefore in fact `git update` is really `git fetch` + `git fast-forward`, and it's the latter that throws the advice. The advice also suggests `git help fast-forward` which has an explanation about what a fast-forward is, what are the options to synchronize with the remote branch (merge and rebase), and what do they look like.

In addition there's a ton of fixes for `git pull` which have been sent before, including the `pull.mode` configuration, the `--merge` option, the per-branch `pullMode` configuration, `pull.mode=fast-forward`, and an improved advice message to prepare users for a future default change:

  The pull was not a fast-forward, in the future you will have to choose
  between a merge or a rebase.
  To quell this message you have two main options:
  1. Adopt the new behavior:
    git config --global pull.mode fast-forward
  2. Maintain the current behavior:
    git config --global pull.mode merge
  For now we will fall back to the traditional behavior: merge.
  For more information check "git help fast-forward".

It doesn't just improve the situation for normal developers, but it also opens the possibility to fix a wart in `git pull --rebase`:

Right now:
 git pull --merge github john (merge "github/john" into "master)
 git pull --rebase github john (rebase "master" onto "github/john")

Since now `git update --rebase` can be used to rebase the current branch onto its upstream, that leaves `git pull --rebase` open to rebase github/john onto master, not the other way around like it currently is.

Junio has suggested there's no consensus over fast-forward by default, but that's not true. Here is a non-exhaustive list of people that have agreed the default should be fast-forward only.

 * Linus Torvalds
 * Junio C Hamano
 * Jeff King
 * Jonathan Nieder
 * Richard Hansen
 * Philip Oakley
 * Elijah Newren
 * John Keeping
 * Ramkumar Ramachandra
 * Alex Henrie
 * W. Trevor King
 * Greg Troxel
 * Peter Kjellerstedt
 * Konstantin Tokarev
 * Robert Dailey
 * Vít Ondruch
 * Raymond E. Pasco
 * Jacob Keller
 * Felipe Contreras

There's only one person against the change: Matthieu Moy. His argument back then [13] was: why ask users to merge or rebase if newcomers will not pick a rebase? To that my response is: for the same reason we ask them to do `git commit --all`: so that they eventually learn about the staging area. Just like they can do `git commit --all`, they can do `git pull --merge`. They can figure out what that means later.

The people in favor of reordering the parents:
 * Andreas Krey
 * John Szakmeister
 * Jeremy Rosen
 * John Keeping
And the people in favor of my old `git update`:
 * Damien Robert
 * Ping Yin
 * Philippe Vaucher

This patch series doesn't implement all of the features my old `git update` had, but it implements most of them, most importantly--unlike `git pull`--it's not broken.

Right now only `git update` without arguments works, and only if the upstream branch is configured. I have a pretty good idea of what the it should do with different arguments (as I had already implemented that), but for now that's open to discussion.

If you want to give it a try:
https://github.com/felipec/git/tree/fc/update

[1] https://lore.kernel.org/git/200910201947.50423.trast@student.ethz.ch/ [2] https://lore.kernel.org/git/20130522115042.GA20649@inner.h.apk.li/ [3] https://lore.kernel.org/git/1377988690-23460-1-git-send-email-felipe.contreras@gmail.com/ [4] https://lore.kernel.org/git/4ay6w9i74cygt6ii1b0db7wg.1398433713382@email.android.com/ [5] https://lore.kernel.org/git/5363BB9F.40102@xiplink.com/ [6] https://lore.kernel.org/git/20201204061623.1170745-1-felipe.contreras@gmail.com/ [7] https://lore.kernel.org/git/CA+55aFzxsNxgKD1uGZQCiib+=+wCMSa0=B+Ye3Zi-u6kpz8Vrg@mail.gmail.com/ [8] https://lore.kernel.org/git/xmqqppjyhnom.fsf@gitster.dls.corp.google.com/ [9] https://lore.kernel.org/git/5228A14B.3000804@bbn.com/ [10] https://lore.kernel.org/git/20130628174252.GF2232@serenity.lan/ [11] https://lore.kernel.org/git/5366db742d494_18f9e4b308aa@nysa.notmuch/ [12] https://github.com/felipec/git/commit/61e05c9798b3c74bab8b2d47ede4c12e8e305345 [13] https://lore.kernel.org/git/vpqbo3za8r9.fsf@anie.imag.fr/

Felipe Contreras (35):
  merge: improve fatal fast-forward message
  merge: split cmd_merge()
  fast-forward: add new builtin
  doc: fast-forward: explain what it is
  fast-forward: add advice for novices
  fast-forward: make the advise configurable
  fast-forward: add help about merge vs. rebase
  update: new built-in
  update: add options and usage skeleton
  update: add --ff option
  update: add --merge mode
  commit: support for multiple MERGE_MODE
  merge: add --reverse-parents option
  update: reverse the order of parents
  update: fake a reverse order of parents in message
  update: add --rebase mode
  update: add mode configuation
  update: add per-branch mode configuration
  pull: cleanup autostash check
  pull: trivial cleanup
  pull: trivial whitespace style fix
  pull: introduce --merge option
  rebase: add REBASE_DEFAULT
  pull: move configuration fetches
  pull: show warning with --ff options
  pull: add pull.mode
  pull: add per-branch mode configuration
  pull: add pull.mode=fast-forward
  pull: reorganize mode conditionals
  pull: add diverging advice on fast-forward mode
  pull: improve --rebase and pull.rebase interaction
  pull: improve default warning
  pull: advice of future changes
  FUTURE: pull: enable ff-only mode by default
  !fixup FUTURE: pull: enable ff-only mode by default
 .gitignore                             |   2 +
 Documentation/config.txt               |   4 +
 Documentation/config/advice.txt        |   2 +
 Documentation/config/branch.txt        |  10 ++
 Documentation/config/pull.txt          |   6 +
 Documentation/config/update.txt        |   5 +
 Documentation/git-fast-forward.txt     | 104 +++++++++++++++++
 Documentation/git-pull.txt             |  10 +-
 Documentation/git-update.txt           |  47 ++++++++
 Documentation/merge-options.txt        |   4 +
 Makefile                               |   2 +
 advice.c                               |  15 +++
 advice.h                               |   2 +
 builtin.h                              |   2 +
 builtin/commit.c                       |   7 +-
 builtin/merge.c                        |  59 +++++++---
 builtin/pull.c                         | 156 +++++++++++++++++--------
 builtin/update.c                       | 153 ++++++++++++++++++++++++
 contrib/completion/git-completion.bash |  22 ++++
 fmt-merge-msg.c                        |  21 +++-
 fmt-merge-msg.h                        |   3 +-
 git.c                                  |   2 +
 rebase.c                               |  12 ++
 rebase.h                               |  13 ++-
 t/t4013-diff-various.sh                |   2 +-
 t/t5520-pull.sh                        | 123 +++++++++++++++++--
 t/t5521-pull-options.sh                |   4 +-
 t/t5524-pull-msg.sh                    |   4 +-
 t/t5553-set-upstream.sh                |  14 +--
 t/t5563-update.sh                      |  87 ++++++++++++++
 t/t5604-clone-reference.sh             |   4 +-
 t/t6402-merge-rename.sh                |  16 +--
 t/t6409-merge-subtree.sh               |   6 +-
 t/t6417-merge-ours-theirs.sh           |  10 +-
 t/t7600-merge.sh                       |  47 ++++++++
 t/t7601-merge-pull-config.sh           | 116 ------------------
 t/t7603-merge-reduce-heads.sh          |   2 +-
 37 files changed, 870 insertions(+), 228 deletions(-)
 create mode 100644 Documentation/config/update.txt
 create mode 100644 Documentation/git-fast-forward.txt
 create mode 100644 Documentation/git-update.txt
 create mode 100644 builtin/update.c
 create mode 100755 t/t5563-update.sh
-- 
2.32.0.36.g70aac2b1aa
Next: Felipe Contreras
Message 1 of 53 in “git update: fix broken git pull”
  1. 00/35 git update: fix broken git pullFelipe Contreras, Jul 5, 2021
  2. 01/35 merge: improve fatal fast-forward messageFelipe Contreras, Jul 5, 2021
  3. Ævar Arnfjörð BjarmasonJul 6, 2021
  4. Felipe ContrerasJul 6, 2021
  5. Randall S. BeckerJul 6, 2021
  6. Junio C HamanoJul 6, 2021
  7. Felipe ContrerasJul 6, 2021
  8. Randall S. BeckerJul 6, 2021
  9. Junio C HamanoJul 6, 2021
  10. Randall S. BeckerJul 6, 2021
  11. Felipe ContrerasJul 6, 2021
  12. Randall S. BeckerJul 6, 2021
  13. Felipe ContrerasJul 6, 2021
  14. 02/35 merge: split cmd_merge()Felipe Contreras, Jul 5, 2021
  15. 03/35 fast-forward: add new builtinFelipe Contreras, Jul 5, 2021
  16. 04/35 doc: fast-forward: explain what it isFelipe Contreras, Jul 5, 2021
  17. 05/35 fast-forward: add advice for novicesFelipe Contreras, Jul 5, 2021
  18. Ævar Arnfjörð BjarmasonJul 6, 2021
  19. Felipe ContrerasJul 6, 2021
  20. 06/35 fast-forward: make the advise configurableFelipe Contreras, Jul 5, 2021
  21. 07/35 fast-forward: add help about merge vs. rebaseFelipe Contreras, Jul 5, 2021
  22. 08/35 update: new built-inFelipe Contreras, Jul 5, 2021
  23. 09/35 update: add options and usage skeletonFelipe Contreras, Jul 5, 2021
  24. 10/35 update: add --ff optionFelipe Contreras, Jul 5, 2021
  25. Ævar Arnfjörð BjarmasonJul 6, 2021
  26. Felipe ContrerasJul 6, 2021
  27. 11/35 update: add --merge modeFelipe Contreras, Jul 5, 2021
  28. Ævar Arnfjörð BjarmasonJul 6, 2021
  29. Felipe ContrerasJul 6, 2021
  30. 12/35 commit: support for multiple MERGE_MODEFelipe Contreras, Jul 5, 2021
  31. 13/35 merge: add --reverse-parents optionFelipe Contreras, Jul 5, 2021
  32. 14/35 update: reverse the order of parentsFelipe Contreras, Jul 5, 2021
  33. 15/35 update: fake a reverse order of parents in messageFelipe Contreras, Jul 5, 2021
  34. 16/35 update: add --rebase modeFelipe Contreras, Jul 5, 2021
  35. 17/35 update: add mode configuationFelipe Contreras, Jul 5, 2021
  36. 18/35 update: add per-branch mode configurationFelipe Contreras, Jul 5, 2021
  37. 19/35 pull: cleanup autostash checkFelipe Contreras, Jul 5, 2021
  38. 20/35 pull: trivial cleanupFelipe Contreras, Jul 5, 2021
  39. 21/35 pull: trivial whitespace style fixFelipe Contreras, Jul 5, 2021
  40. 22/35 pull: introduce --merge optionFelipe Contreras, Jul 5, 2021
  41. 23/35 rebase: add REBASE_DEFAULTFelipe Contreras, Jul 5, 2021
  42. 24/35 pull: move configuration fetchesFelipe Contreras, Jul 5, 2021
  43. 25/35 pull: show warning with --ff optionsFelipe Contreras, Jul 5, 2021
  44. 26/35 pull: add pull.modeFelipe Contreras, Jul 5, 2021
  45. 27/35 pull: add per-branch mode configurationFelipe Contreras, Jul 5, 2021
  46. 28/35 pull: add pull.mode=fast-forwardFelipe Contreras, Jul 5, 2021
  47. 29/35 pull: reorganize mode conditionalsFelipe Contreras, Jul 5, 2021
  48. 30/35 pull: add diverging advice on fast-forward modeFelipe Contreras, Jul 5, 2021
  49. 31/35 pull: improve --rebase and pull.rebase interactionFelipe Contreras, Jul 5, 2021
  50. 32/35 pull: improve default warningFelipe Contreras, Jul 5, 2021
  51. 33/35 pull: advice of future changesFelipe Contreras, Jul 5, 2021
  52. 34/35 FUTURE: pull: enable ff-only mode by defaultFelipe Contreras, Jul 5, 2021
  53. 35/35 !fixup FUTURE: pull: enable ff-only mode by defaultFelipe Contreras, Jul 5, 2021

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.