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

Re: Beyond Merge and Rebase: The Upstream Import Approach in Git

From
Junio C Hamano <gitster@pobox.com>
Date
Jul 11, 2023, 17:02 UTC
Message-ID
<xmqqwmz6z8j1.fsf@gitster.g>
In-Reply-To
<CADWu+UnThMq2M+kCMADP9rZ5c6nL+Hz+z0-OqRnuG2oYVzbvWw@mail.gmail.com>
Aleksander Korzyński <ak@akorzy.net> writes:
Show 16 quoted lines
> So the alternative solution is to rebase your "main" branch on top of
> "upstream/main":
>
>   o---o---o---o---o  upstream/main
>                    \
>                     o'---o'---o'  main
>
> You now have the advantage of having greater visibility into the
> differences between "upstream/main" and "main". However, a rebase
> comes with a different problem: if any user of your fork had the
> "main" branch checked out in their local repository and they run "git
> pull", they are going to get an error stating that the local and
> upstream branches have diverged. They will have to take special steps
> to recover from the rebase of the "main" branch.
>
> So how to solve that problem?

In short, what you wrote is a way to use rebase but help those who have older versions of your work to bring themselves up to date. That is a useful thing for downstream contributors to have, and it is a valuable goal to aim to help these downstream contributors to coordinate sharing of their work. Because in general, downstream contributors tend to outnumber upstream maintainers. It would help you to hear perspective from upstream maintainers as well, and here are a few things that come to my mind.

    o---o---o---o---o  upstream/main
         \           \
          \           a'---b'---c'
           \                     \
            a---b---c-------------S  main
 * It certainly would help folks who received a copy of c from you
   and then want to observe your progress after you rebased c to c',
   but how does this help those who have older versions of your
   work, *and* built their own changes on top?  They would not just
   need to update their remote-tracking branch that has your older
   version of the work to the latest, but also rebase their work on
   top.
    o---o---o---o---o  upstream/main
         \           \
          \           a'---b'---c'---d'---e'
           \                     \
            a---b---c-------------S  main
                     \
                      d---e  your coworker
 * It is a reasonable way to for keeping your work as a fork from
   the upstream up-to-date, but it is unclear what the eventual
   presentation to and adoption by the upstream would look like.  As
   an upstream maintainer, for example, I do not want to merge S
   above to the upstream tree.
 * There is no need to say that it is undesirable to merge from
   upstream to your working topic branch like 'main' repeatedly, as
   everybody knows it will clutter your history, but more
   importantly, the resulting history becomes more useless from the
   upstream's point of view as you have more such reverse merges.
   The upstream wants to see your work and only your work delineated
   on your repository.  If you repeat the "rebase and merge", then
   the next round would create a new history a", b" and c" forked on
   top of an updated upstream/main, merged on top of S, perhaps
   looking like this:
    o---o---o---o---o---------------o  upstream/main
         \           \               \
          \           a'---b'---c'    a"--b"--c"
           \                     \             \
            a---b---c-------------S-------------T  main
   However, once you keep going this way for several rounds, would
   the result really be much better than bushy history with full of
   reverse merges from upstream?  Would it help to add new history
   simplification mechanisms and options to help visualize the
   history, or do we already have necessary support (e.g. if the
   convention for these "merge to cauterize the older versions of
   history with the newly rebased history" S and T merges is to
   record the rebased history as the first-parent, then "git log
   --first-parent upstream/main..main" should be sufficient).  The
   users would benefit to have an easy way, given only T or S, to
   get range-diff among (a,b,c) and (a',b',c') and (a",b",c").

What is interesting is that, because S and T are essentially "ours" merges of your local history into the history that would result if you rebased on top of the upstream (i.e. merge S and T would have the same tree as c' and c"), what is tested and used by the holder of S and T are the changes represented by the latest rebased versions of the commits. So from the upstream point of view, throwing a pull request for c" (not the original a, b and c) would be a reasonable way to finalize your work. That way, what you are offering to the upstream is not an ancient original commits (i.e. a, b, and c) that you haven't been using at all once you created S and T.

Thanks.
Previous: Aleksander KorzyńskiNext: Aleksander Korzyński
Message 2 of 9 in “Beyond Merge and Rebase: The Upstream Import Approach in Git”
  1. Aleksander KorzyńskiJul 11, 2023
  2. Junio C HamanoJul 11, 2023
  3. Aleksander KorzyńskiJul 13, 2023
  4. Johannes SchindelinJul 12, 2023
  5. Junio C HamanoJul 12, 2023
  6. Junio C HamanoJul 12, 2023
  7. Aleksander KorzyńskiJul 14, 2023
  8. Aleksander KorzyńskiAug 1, 2023
  9. Aleksander KorzyńskiJul 14, 2023

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.