threads / patch / 63930

patch, 5 partsdoc: git-rebase: clarify DESCRIPTION section

Subject: [PATCH 0/5] doc: git-rebase: clarify DESCRIPTION section

## tl;dr

103 messages between Aug 8, 2025 and Aug 23, 2025. Diffs are folded; open one to read it.

replies: 102people: 6as markdown or json

Julia Evans via GitGitGadget· Aug 8, 2025, 15:24 UTC · lore

This patch series reorganizes the DESCRIPTION section of the git rebase man page. My goal is to make the page more accessible to git newcomers (who from my experience have an extremely difficult time understanding git man pages) while keeping the exact same information available for more advanced users. This series:

 * puts more commonly used information first (a basic example of a rebase
   and "how to fix merge conflicts" are moved to before "how rebase modifies
   ORIG_HEAD" and "what git rebase <upstream> <branch> does")
 * removes duplication
 * more closely parallels the git merge man page's structure by starting it
   with the same example history
 * moves the --onto examples to their own section

I've never contributed to Git before so I'd appreciate any pointers to past discussions of Git's documentation philosophy or who the target audience for Git documentation is.

Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 287 ++++++++++++++++------------------
 1 file changed, 139 insertions(+), 148 deletions(-)
base-commit: 64cbe5e2e8a7b0f92c780b210e602496bd5cad0f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 15:24 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>

Start with an example that mirrors the example in the `git-merge` man page, to make it easier for folks to understand the difference between a rebase and a merge.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 46 +++++++++++++++--------------------
 1 file changed, 20 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +20 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..fee73623990d 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,26 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+
+For example, assume the following history exists and the current branch is `topic`:
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+Then `git rebase master` will find all of the commits since `topic` diverged
+from `master` and copy the changes in each of those commits on top of the
+`master` branch.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +78,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Junio C Hamano· Aug 8, 2025, 16:30 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH 1/5] doc: git-rebase: start with an example

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 20 quoted lines
> From: Julia Evans <julia@jvns.ca>
>
> Start with an example that mirrors the example in the `git-merge` man
> page, to make it easier for folks to understand the difference between a
> rebase and a merge.
>
> Signed-off-by: Julia Evans <julia@jvns.ca>
> ---
>  Documentation/git-rebase.adoc | 46 +++++++++++++++--------------------
>  1 file changed, 20 insertions(+), 26 deletions(-)
>
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index 956d3048f5a6..fee73623990d 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -16,6 +16,26 @@ SYNOPSIS
>  
>  DESCRIPTION
>  -----------
> +Transplant a series of commits onto a different starting point.

It is an excellent idea to start with what it does, before explaining how you would drive it.

> +For example, assume the following history exists and the current branch is `topic`:

The line is a bit overly long, and the style a bit on the "description of dry facts" side, which might want to give a bit more "motivation" to help readers.

Here is my attempt.
    Imagine that you have been working on the `topic` branch in this
    history, and you'd want to "catch up" to the work done on the
    `master` branch.
      *** Illustration of "before" state ***
    You want to transplant the commits you made on `topic` since it
    diverged from `master` (i.e. A, B, and C), on top of the current
    `master`.  You can do so by running `git rebase master` while the
    `topic` branch is checked out.  `git rebase master topic` works
    as a short-cut to `git checkout topic && git rebase master`.
      *** Illustration of "after" state ***
perhaps?  

Note that you lost the mention of `git rebase master topic` syntax and the explanation that the form being a shorthand for checkout followed by rebase, which I do not think appear anywhere else in the document, so my suggested rewrite above resurrects it.

Show 52 quoted lines
> +------------
> +          A---B---C topic
> +         /
> +    D---E---F---G master
> +------------
> +
> +Then `git rebase master` will find all of the commits since `topic` diverged
> +from `master` and copy the changes in each of those commits on top of the
> +`master` branch.
> +
> +------------
> +                  A'--B'--C' topic
> +                 /
> +    D---E---F---G master
> +------------
> +
>  If `<branch>` is specified, `git rebase` will perform an automatic
>  `git switch <branch>` before doing anything else.  Otherwise
>  it remains on the current branch.
> @@ -58,32 +78,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
>  original `<branch>` and remove the `.git/rebase-apply` working files, use
>  the command `git rebase --abort` instead.
>  
> -Assume the following history exists and the current branch is "topic":
> -
> -------------
> -          A---B---C topic
> -         /
> -    D---E---F---G master
> -------------
> -
> -From this point, the result of either of the following commands:
> -
> -
> -    git rebase master
> -    git rebase master topic
> -
> -would be:
> -
> -------------
> -                  A'--B'--C' topic
> -                 /
> -    D---E---F---G master
> -------------
> -
> -*NOTE:* The latter form is just a short-hand of `git checkout topic`
> -followed by `git rebase master`. When rebase exits `topic` will
> -remain the checked-out branch.
> -
>  If the upstream branch already contains a change you have made (e.g.,
>  because you mailed a patch which was applied upstream), then that commit
>  will be skipped and warnings will be issued (if the 'merge' backend is
Julia Evans· Aug 8, 2025, 17:13 UTC · re: Junio C Hamano · lore

Re: [PATCH 1/5] doc: git-rebase: start with an example

On Fri, Aug 8, 2025, at 12:30 PM, Junio C Hamano wrote:
Show 31 quoted lines
> "Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
>
>> From: Julia Evans <julia@jvns.ca>
>>
>> Start with an example that mirrors the example in the `git-merge` man
>> page, to make it easier for folks to understand the difference between a
>> rebase and a merge.
>>
>> Signed-off-by: Julia Evans <julia@jvns.ca>
>> ---
>>  Documentation/git-rebase.adoc | 46 +++++++++++++++--------------------
>>  1 file changed, 20 insertions(+), 26 deletions(-)
>>
>> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
>> index 956d3048f5a6..fee73623990d 100644
>> --- a/Documentation/git-rebase.adoc
>> +++ b/Documentation/git-rebase.adoc
>> @@ -16,6 +16,26 @@ SYNOPSIS
>>  
>>  DESCRIPTION
>>  -----------
>> +Transplant a series of commits onto a different starting point.
>
> It is an excellent idea to start with what it does, before
> explaining how you would drive it.
>
>> +For example, assume the following history exists and the current branch is `topic`:
>
> The line is a bit overly long, and the style a bit on the
> "description of dry facts" side, which might want to give
> a bit more "motivation" to help readers.
I'm very happy to hear that feedback: I thought it was very dry as well, but I copied that part from elsewhere in the man page because I thought that was git's preferred documentation style. I'll work on making it less dry.
> Note that you lost the mention of `git rebase master topic` syntax
> and the explanation that the form being a shorthand for checkout
> followed by rebase, which I do not think appear anywhere else in the
> document, so my suggested rewrite above resurrects it.
That's actually in PATCH 3/5 of this series: I also thought the explanation that the form being a shorthand for checkout followed by rebase was extremely clear so I moved it to be the primary explanation of what `git rebase <upstream> <branch>` does.
Junio C Hamano· Aug 8, 2025, 18:11 UTC · re: Julia Evans · lore

Re: [PATCH 1/5] doc: git-rebase: start with an example

"Julia Evans" <julia@jvns.ca> writes:
> I'm very happy to hear that feedback: I thought it was very dry as
> well, but I copied that part from elsewhere in the man page
> because I thought that was git's preferred documentation
> style. I'll work on making it less dry.

[administrivia: please wrap your overlong lines; we write for this hypothetiical reader on an 80-column terminal].

Show 6 quoted lines
>> Note that you lost the mention of `git rebase master topic` syntax
>> and the explanation that the form being a shorthand for checkout
>> followed by rebase, which I do not think appear anywhere else in the
>> document, so my suggested rewrite above resurrects it.
>
> That's actually in PATCH 3/5 of this series:...

Which I think is too late; both are quite commonly used and useful, so showing them upfront when the command line examples are first introduced would be more preferrable.

Thanks.
Julia Evans via GitGitGadget· Aug 8, 2025, 15:24 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 52 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +23 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index fee73623990d..3087e558b509 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -36,6 +36,29 @@ from `master` and copy the changes in each of those commits on top of the
     D---E---F---G master
 ------------
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. Typically this would be
+   done with
+
+   git add <filename>
+
+   You can then continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -71,13 +94,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -180,28 +196,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Junio C Hamano· Aug 8, 2025, 17:48 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH 2/5] doc: git rebase: dedup merge conflict discussion

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
> +If there is a merge conflict during this process, `git rebase` will stop at the
> +first problematic commit and leave conflict markers. If this happens, you can:

By using the numbered enumeration below, we may mislead the readers that these are the things they have to do in this order, when we actually are giving them choices.

	If this happens, you can do one of these things:
would be an easy workaround.
Show 10 quoted lines
> +1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
> +   and make edits to resolve the conflict. For each file you edit, you need to
> +   tell Git that the conflict has been resolved. Typically this would be
> +   done with
> +
> +   git add <filename>
> +
> +   You can then continue the rebasing process with
> +
> +   git rebase --continue

The original (below) does not do a perfect job, but I am afraid that this increases the chance of misunderstanding by new readers that they'd run "continue" after marking each confclited fines as "done" with "git add", by reducing a sentence to a mere "then" in "You can then continue".

	Typically after resolving all the conflicts in a single
	file, you would tell Git that you are done with this file:
	git add <filename>
	And after dealing with all the conflicted files and telling
	Git that you are done, you would continue the rebasing
	process with
	git rebase --continue
or something?
Show 7 quoted lines
> +2. Stop the `git rebase` and return your branch to its original state with
> +
> +   git rebase --abort
> +
> +3. Skip the commit that caused the merge conflict with
> +
> +   git rebase --skip

The explanation in the above looks good, and the new organization is much easier to follow and is definite improvement compared to the original.

I am not sure how the above how the above formats, though, especially on a medium that is not monospaced text (e.g., html rendition, not "git help -m rebase" on terminals). The prose should typeset just like the normal text (i.e. your "Transplant a series of commits" in the previous step that starts the description section), but the command that the users would type should be typeset in monospace typewriter. Have you tried?

Thanks.
Julia Evans via GitGitGadget· Aug 8, 2025, 15:24 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

I found this extremely hard to understand as it was and this seemed like a clearer wording to me.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
Show changes to Documentation/git-rebase.adoc +3 −5
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 3087e558b509..ada9f6b2614b 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -58,12 +58,10 @@ first problematic commit and leave conflict markers. If this happens, you can:
 
    git rebase --skip
 
+`git rebase <upstream> <branch>` is shorthand for `git switch <branch>`
+followed by `git rebase <upstream>`.
 
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 15:24 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Show changes to Documentation/git-rebase.adoc +87 −69
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index ada9f6b2614b..c63d67f340a0 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -113,87 +113,6 @@ will result in:
     D---E---A'---F master
 ------------
 
-Here is how you would transplant a topic branch based on one
-branch to another, to pretend that you forked the topic branch
-from the latter branch, using `rebase --onto`.
-
-First let's assume your 'topic' is based on branch 'next'.
-For example, a feature developed in 'topic' depends on some
-functionality which is found in 'next'.
-
-------------
-    o---o---o---o---o  master
-         \
-          o---o---o---o---o  next
-                           \
-                            o---o---o  topic
-------------
-
-We want to make 'topic' forked from branch 'master'; for example,
-because the functionality on which 'topic' depends was merged into the
-more stable 'master' branch. We want our tree to look like this:
-
-------------
-    o---o---o---o---o  master
-        |            \
-        |             o'--o'--o'  topic
-         \
-          o---o---o---o---o  next
-------------
-
-We can get this using the following command:
-
-    git rebase --onto master next topic
-
-
-Another example of --onto option is to rebase part of a
-branch.  If we have the following situation:
-
-------------
-                            H---I---J topicB
-                           /
-                  E---F---G  topicA
-                 /
-    A---B---C---D  master
-------------
-
-then the command
-
-    git rebase --onto master topicA topicB
-
-would result in:
-
-------------
-                 H'--I'--J'  topicB
-                /
-                | E---F---G  topicA
-                |/
-    A---B---C---D  master
-------------
-
-This is useful when topicB does not depend on topicA.
-
-A range of commits could also be removed with rebase.  If we have
-the following situation:
-
-------------
-    E---F---G---H---I---J  topicA
-------------
-
-then the command
-
-    git rebase --onto topicA~5 topicA~3 topicA
-
-would result in the removal of commits F and G:
-
-------------
-    E---H'---I'---J'  topicA
-------------
-
-This is useful if F and G were flawed in some way, or should not be
-part of topicA.  Note that the argument to `--onto` and the `<upstream>`
-parameter can be any valid commit-ish.
-
 MODE OPTIONS
 ------------
 
@@ -239,6 +158,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -1017,6 +938,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
+Here is how you would transplant a topic branch based on one
+branch to another, to pretend that you forked the topic branch
+from the latter branch, using `rebase --onto`.
+
+First let's assume your 'topic' is based on branch 'next'.
+For example, a feature developed in 'topic' depends on some
+functionality which is found in 'next'.
+
+------------
+    o---o---o---o---o  master
+         \
+          o---o---o---o---o  next
+                           \
+                            o---o---o  topic
+------------
+
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
+
+------------
+    o---o---o---o---o  master
+        |            \
+        |             o'--o'--o'  topic
+         \
+          o---o---o---o---o  next
+------------
+
+We can get this using the following command:
+
+    git rebase --onto master next topic
+
+
+Another example of --onto option is to rebase part of a
+branch.  If we have the following situation:
+
+------------
+                            H---I---J topicB
+                           /
+                  E---F---G  topicA
+                 /
+    A---B---C---D  master
+------------
+
+then the command
+
+    git rebase --onto master topicA topicB
+
+would result in:
+
+------------
+                 H'--I'--J'  topicB
+                /
+                | E---F---G  topicA
+                |/
+    A---B---C---D  master
+------------
+
+This is useful when topicB does not depend on topicA.
+
+A range of commits could also be removed with rebase.  If we have
+the following situation:
+
+------------
+    E---F---G---H---I---J  topicA
+------------
+
+then the command
+
+    git rebase --onto topicA~5 topicA~3 topicA
+
+would result in the removal of commits F and G:
+
+------------
+    E---H'---I'---J'  topicA
+------------
+
+This is useful if F and G were flawed in some way, or should not be
+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
+parameter can be any valid commit-ish.
+
+
 RECOVERING FROM UPSTREAM REBASE
 -------------------------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 15:24 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about three steps of a process
- delete a duplicate explanation of how git rebase skips commits with
  the same textual changes (it's explained in more detail a few lines
  further down)
- move the `ORIG_HEAD` note down so that it doesn't interrupt the
  discussion of the mechanics.
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
Show changes to Documentation/git-rebase.adoc +7 −8
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index c63d67f340a0..6b79cd0daca9 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -67,18 +67,23 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
+Here is a more detailed description of what `git rebase <upstream>` does:
+
+First, all changes made by commits in the current branch but that are not
 in `<upstream>` are saved to a temporary area.  This is the same set
 of commits that would be shown by `git log <upstream>..HEAD`; or by
 `git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
 description on `--fork-point` below); or by `git log HEAD`, if the
 `--root` option is specified.
 
-The current branch is reset to `<upstream>` or `<newbase>` if the
+Then the current branch is reset to `<upstream>` or `<newbase>` if the
 `--onto` option was supplied.  This has the exact same effect as
 `git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
 to point at the tip of the branch before the reset.
 
+Then the commits that were previously saved into the temporary area are
+reapplied to the current branch, one by one, in order.
+
 [NOTE]
 `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
 at the end of the rebase if other commands that write that pseudo-ref
@@ -86,12 +91,6 @@ at the end of the rebase if other commands that write that pseudo-ref
 however, is accessible using the reflog of the current branch
 (i.e. `@{1}`, see linkgit:gitrevisions[7]).
 
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 19:15 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v2 0/5] doc: git-rebase: clarify DESCRIPTION section

Thanks for the review comments, here are the new changes which:
 * make the intro to the man page less dry, with the suggested wording
 * clarify the merge conflict resolution explanation & fix the HTML
   formatting issues
 * move the explanation of the git rebase <upstream> <branch> syntax up into
   the intro

I'm still curious about the intention for the git rebase master topic syntax, since I'd never heard of it before. Is it just to save on typing, since it's fewer characters than git switch topic and then git rebase master? I ask because someone mentioned to me on Mastodon (https://hachyderm.io/@simontatham/114988051822317920) that they sometimes use git rebase HEAD main as part of their workflow, which is not equivalent to git checkout main && git rebase HEAD. That made me think that there might be some broader intent to enable rebases that wouldn't otherwise be possible without that syntax.

I'll wrap my text to 80 characters in the future, still learning the process for emailing a plain-text mailing list :)

Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 285 ++++++++++++++++------------------
 1 file changed, 137 insertions(+), 148 deletions(-)
base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
Range-diff vs v1:
 1:  ac3a91c04bf ! 1:  26b742eb49f doc: git-rebase: start with an example
     @@ Documentation/git-rebase.adoc: SYNOPSIS
       -----------
      +Transplant a series of commits onto a different starting point.
      +
     -+For example, assume the following history exists and the current branch is `topic`:
     ++For example, imagine that you have been working on the `topic` branch in this
     ++history, and you want to "catch up" to the work done on the `master` branch.
      +
      +------------
      +          A---B---C topic
     @@ Documentation/git-rebase.adoc: SYNOPSIS
      +    D---E---F---G master
      +------------
      +
     -+Then `git rebase master` will find all of the commits since `topic` diverged
     -+from `master` and copy the changes in each of those commits on top of the
     -+`master` branch.
     ++You want to transplant the commits you made on `topic` since it diverged from
     ++`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
     ++by running `git rebase master` while the `topic` branch is checked out.  If you
     ++want to rebase `topic` while on another branch, `git rebase master topic` is a
     ++short-cut for `git switch topic && git rebase master`.
      +
      +------------
      +                  A'--B'--C' topic
 2:  f4f0a5a1172 ! 2:  249a5127904 doc: git rebase: dedup merge conflict discussion
     @@ Commit message
          Signed-off-by: Julia Evans <julia@jvns.ca>
      
       ## Documentation/git-rebase.adoc ##
     -@@ Documentation/git-rebase.adoc: from `master` and copy the changes in each of those commits on top of the
     +@@ Documentation/git-rebase.adoc: short-cut for `git switch topic && git rebase master`.
           D---E---F---G master
       ------------
       
      +If there is a merge conflict during this process, `git rebase` will stop at the
     -+first problematic commit and leave conflict markers. If this happens, you can:
     ++first problematic commit and leave conflict markers. If this happens, you can do
     ++one of these things:
      +
      +1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
      +   and make edits to resolve the conflict. For each file you edit, you need to
     -+   tell Git that the conflict has been resolved. Typically this would be
     -+   done with
     -+
     -+   git add <filename>
     -+
     -+   You can then continue the rebasing process with
     ++   tell Git that the conflict has been resolved. You can mark the conflict as
     ++   resolved with  `git add <filename>`. After resolving all of the conflicts,
     ++   you can continue the rebasing process with
      +
      +   git rebase --continue
      +
 3:  b27117ea19a ! 3:  ce7ab74ea0f doc: git rebase: clarify arguments syntax
     @@ Metadata
       ## Commit message ##
          doc: git rebase: clarify arguments syntax
      
     -    I found this extremely hard to understand as it was and this seemed like
     -    a clearer wording to me.
     +    This removes the explanation of `git rebase <upstream> <branch>`, since
     +    it was already explained above that it's shorthand for `git switch
     +    <branch> && git rebase <upstream>`
      
          Signed-off-by: Julia Evans <julia@jvns.ca>
      
       ## Documentation/git-rebase.adoc ##
     -@@ Documentation/git-rebase.adoc: first problematic commit and leave conflict markers. If this happens, you can:
     +@@ Documentation/git-rebase.adoc: one of these things:
       
          git rebase --skip
       
     -+`git rebase <upstream> <branch>` is shorthand for `git switch <branch>`
     -+followed by `git rebase <upstream>`.
     - 
     +-
      -If `<branch>` is specified, `git rebase` will perform an automatic
      -`git switch <branch>` before doing anything else.  Otherwise
      -it remains on the current branch.
 4:  28b00d3b32f = 4:  590d7486d3d doc: git-rebase: move --onto explanation down
 5:  7d4dc6d2c04 = 5:  ad97cd9e671 doc: git-rebase: update discussion of internals
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 19:15 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v2 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>

Start with an example that mirrors the example in the `git-merge` man page, to make it easier for folks to understand the difference between a rebase and a merge.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +23 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..6dacf693bd71 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,29 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+short-cut for `git switch topic && git rebase master`.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +81,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Junio C Hamano· Aug 8, 2025, 23:31 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v2 1/5] doc: git-rebase: start with an example

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 16 quoted lines
> +Transplant a series of commits onto a different starting point.
> +
> +For example, imagine that you have been working on the `topic` branch in this
> +history, and you want to "catch up" to the work done on the `master` branch.
> +
> +------------
> +          A---B---C topic
> +         /
> +    D---E---F---G master
> +------------
> +
> +You want to transplant the commits you made on `topic` since it diverged from
> +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
> +by running `git rebase master` while the `topic` branch is checked out.  If you
> +want to rebase `topic` while on another branch, `git rebase master topic` is a
> +short-cut for `git switch topic && git rebase master`.
s/switch/checkout/, as that is how the original defines the short-cut.
Show 6 quoted lines
> +------------
> +                  A'--B'--C' topic
> +                 /
> +    D---E---F---G master
> +------------
> +
Other than that, looks great.
Julia Evans via GitGitGadget· Aug 8, 2025, 19:15 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v2 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 50 +++++++++++++++--------------------
 1 file changed, 21 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +21 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 6dacf693bd71..a93c616f38b1 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -39,6 +39,27 @@ short-cut for `git switch topic && git rebase master`.
     D---E---F---G master
 ------------
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -74,13 +95,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -183,28 +197,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 19:15 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v2 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

This removes the explanation of `git rebase <upstream> <branch>`, since it was already explained above that it's shorthand for `git switch <branch> && git rebase <upstream>`

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
Show changes to Documentation/git-rebase.adoc +1 −6
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index a93c616f38b1..e700b92e35ac 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -59,12 +59,7 @@ one of these things:
 
    git rebase --skip
 
-
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Junio C Hamano· Aug 8, 2025, 21:09 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v2 3/5] doc: git rebase: clarify arguments syntax

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 5 quoted lines
> From: Julia Evans <julia@jvns.ca>
>
> This removes the explanation of `git rebase <upstream> <branch>`, since
> it was already explained above that it's shorthand for `git switch
> <branch> && git rebase <upstream>`

We usually do not say "This [commit] does X". In this particular case, since the objective is so obvious, we do not necessarily have to follow the whole "summarize the current state, explain why it is problematic, and then tell somebody sitting in front of a keyboard to change the code in this and that way to make it improve" 9 yards; just tweaking it into

	Remove the redundant explanation of `git ...`, since it was
	already explained earlier.
would be sufficient.

Although the proposed log message does not mention it, I actually like the other change in this patch, that rephrases the "if you don't specify...", even better. The addtional "to rebase onto" does make the description clearer.

Thanks.
Show 23 quoted lines
> Signed-off-by: Julia Evans <julia@jvns.ca>
> ---
>  Documentation/git-rebase.adoc | 7 +------
>  1 file changed, 1 insertion(+), 6 deletions(-)
>
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index a93c616f38b1..e700b92e35ac 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -59,12 +59,7 @@ one of these things:
>  
>     git rebase --skip
>  
> -
> -If `<branch>` is specified, `git rebase` will perform an automatic
> -`git switch <branch>` before doing anything else.  Otherwise
> -it remains on the current branch.
> -
> -If `<upstream>` is not specified, the upstream configured in
> +If you don't specify an `<upstream>` to rebase onto, the upstream configured in
>  `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
>  linkgit:git-config[1] for details) and the `--fork-point` option is
>  assumed.  If you are currently not on any branch or if the current
Julia Evans via GitGitGadget· Aug 8, 2025, 19:15 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v2 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Show changes to Documentation/git-rebase.adoc +87 −69
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index e700b92e35ac..6a4b3dbd5960 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -111,87 +111,6 @@ will result in:
     D---E---A'---F master
 ------------
 
-Here is how you would transplant a topic branch based on one
-branch to another, to pretend that you forked the topic branch
-from the latter branch, using `rebase --onto`.
-
-First let's assume your 'topic' is based on branch 'next'.
-For example, a feature developed in 'topic' depends on some
-functionality which is found in 'next'.
-
-------------
-    o---o---o---o---o  master
-         \
-          o---o---o---o---o  next
-                           \
-                            o---o---o  topic
-------------
-
-We want to make 'topic' forked from branch 'master'; for example,
-because the functionality on which 'topic' depends was merged into the
-more stable 'master' branch. We want our tree to look like this:
-
-------------
-    o---o---o---o---o  master
-        |            \
-        |             o'--o'--o'  topic
-         \
-          o---o---o---o---o  next
-------------
-
-We can get this using the following command:
-
-    git rebase --onto master next topic
-
-
-Another example of --onto option is to rebase part of a
-branch.  If we have the following situation:
-
-------------
-                            H---I---J topicB
-                           /
-                  E---F---G  topicA
-                 /
-    A---B---C---D  master
-------------
-
-then the command
-
-    git rebase --onto master topicA topicB
-
-would result in:
-
-------------
-                 H'--I'--J'  topicB
-                /
-                | E---F---G  topicA
-                |/
-    A---B---C---D  master
-------------
-
-This is useful when topicB does not depend on topicA.
-
-A range of commits could also be removed with rebase.  If we have
-the following situation:
-
-------------
-    E---F---G---H---I---J  topicA
-------------
-
-then the command
-
-    git rebase --onto topicA~5 topicA~3 topicA
-
-would result in the removal of commits F and G:
-
-------------
-    E---H'---I'---J'  topicA
-------------
-
-This is useful if F and G were flawed in some way, or should not be
-part of topicA.  Note that the argument to `--onto` and the `<upstream>`
-parameter can be any valid commit-ish.
-
 MODE OPTIONS
 ------------
 
@@ -237,6 +156,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -1015,6 +936,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
+Here is how you would transplant a topic branch based on one
+branch to another, to pretend that you forked the topic branch
+from the latter branch, using `rebase --onto`.
+
+First let's assume your 'topic' is based on branch 'next'.
+For example, a feature developed in 'topic' depends on some
+functionality which is found in 'next'.
+
+------------
+    o---o---o---o---o  master
+         \
+          o---o---o---o---o  next
+                           \
+                            o---o---o  topic
+------------
+
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
+
+------------
+    o---o---o---o---o  master
+        |            \
+        |             o'--o'--o'  topic
+         \
+          o---o---o---o---o  next
+------------
+
+We can get this using the following command:
+
+    git rebase --onto master next topic
+
+
+Another example of --onto option is to rebase part of a
+branch.  If we have the following situation:
+
+------------
+                            H---I---J topicB
+                           /
+                  E---F---G  topicA
+                 /
+    A---B---C---D  master
+------------
+
+then the command
+
+    git rebase --onto master topicA topicB
+
+would result in:
+
+------------
+                 H'--I'--J'  topicB
+                /
+                | E---F---G  topicA
+                |/
+    A---B---C---D  master
+------------
+
+This is useful when topicB does not depend on topicA.
+
+A range of commits could also be removed with rebase.  If we have
+the following situation:
+
+------------
+    E---F---G---H---I---J  topicA
+------------
+
+then the command
+
+    git rebase --onto topicA~5 topicA~3 topicA
+
+would result in the removal of commits F and G:
+
+------------
+    E---H'---I'---J'  topicA
+------------
+
+This is useful if F and G were flawed in some way, or should not be
+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
+parameter can be any valid commit-ish.
+
+
 RECOVERING FROM UPSTREAM REBASE
 -------------------------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 19:15 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v2 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about three steps of a process
- delete a duplicate explanation of how git rebase skips commits with
  the same textual changes (it's explained in more detail a few lines
  further down)
- move the `ORIG_HEAD` note down so that it doesn't interrupt the
  discussion of the mechanics.
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
Show changes to Documentation/git-rebase.adoc +7 −8
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 6a4b3dbd5960..5a49e4f2de9a 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -65,18 +65,23 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
+Here is a more detailed description of what `git rebase <upstream>` does:
+
+First, all changes made by commits in the current branch but that are not
 in `<upstream>` are saved to a temporary area.  This is the same set
 of commits that would be shown by `git log <upstream>..HEAD`; or by
 `git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
 description on `--fork-point` below); or by `git log HEAD`, if the
 `--root` option is specified.
 
-The current branch is reset to `<upstream>` or `<newbase>` if the
+Then the current branch is reset to `<upstream>` or `<newbase>` if the
 `--onto` option was supplied.  This has the exact same effect as
 `git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
 to point at the tip of the branch before the reset.
 
+Then the commits that were previously saved into the temporary area are
+reapplied to the current branch, one by one, in order.
+
 [NOTE]
 `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
 at the end of the rebase if other commands that write that pseudo-ref
@@ -84,12 +89,6 @@ at the end of the rebase if other commands that write that pseudo-ref
 however, is accessible using the reflog of the current branch
 (i.e. `@{1}`, see linkgit:gitrevisions[7]).
 
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Junio C Hamano· Aug 8, 2025, 21:54 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v2 5/5] doc: git-rebase: update discussion of internals

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
> From: Julia Evans <julia@jvns.ca>
>
> - make it clearer that we're talking about three steps of a process

A good call. "First, then, then" does make it clear where each new step begins. "First, then, finally" would make it even more obvious which step concludes the sequence, though.

> - delete a duplicate explanation of how git rebase skips commits with
>   the same textual changes (it's explained in more detail a few lines
>   further down)
OK.
> - move the `ORIG_HEAD` note down so that it doesn't interrupt the
>   discussion of the mechanics.

I thought you moved the "finally we reapply" up, instead of moving the note down ;-) And when viewed that way, a more direct way to justify this change is that you made sure these three steps are kept together.

Again, good change.
Show 9 quoted lines
> -All changes made by commits in the current branch but that are not
> +Here is a more detailed description of what `git rebase <upstream>` does:
> +
> +First, all changes made by commits in the current branch but that are not
>  in `<upstream>` are saved to a temporary area.  This is the same set
>  of commits that would be shown by `git log <upstream>..HEAD`; or by
>  `git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
>  description on `--fork-point` below); or by `git log HEAD`, if the
>  `--root` option is specified.

If we are ambitious, we may want to rewrite this first step to put almost no stress on "saving" and "temporary area". Especially when you rebase with merge backend, it would be morally a sequence of cherry-pick, without us having to save anything---we only need to figure out which commits to replay in what order.

    First, the command figures out changes from which commits to
    replay in what order.  The set of commits are those shown by
    `git log <base>..HEAD`, where <base> is the <upstream> if given,
    or computed fork-point if the `--fork-point` option is active,
    or all commits that lead to `HEAD` if `--root` is given.
Show 5 quoted lines
> -The current branch is reset to `<upstream>` or `<newbase>` if the
> +Then the current branch is reset to `<upstream>` or `<newbase>` if the
>  `--onto` option was supplied.  This has the exact same effect as
>  `git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
>  to point at the tip of the branch before the reset.
"This has the exact same effect as" made my reading hiccup.
    Then `git reset --hard` rewinds the current branch to the commit
    given by `--onto`, if specified, or to `<upstream>`.

I am not sure if it is worth talking about ORIG_HEAD at this point, as that is part of what `git reset --hard` does with this step. Given especially that we have NOTE that says ORIG_HEAD cannot be relied upon once the replaying of commits begin, mentioning the value of ORIG_HEAD before the replaying begins does not seem to add much value to the explanation.

> +Then the commits that were previously saved into the temporary area are
> +reapplied to the current branch, one by one, in order.
Yup.  As I suggested, "Then" -> "Finally".

I do not know how much detail we want to give to readers, and I do to prefer to tell some white lie in end-user facing documentation if simplified description helps the initial understanding, so I am not yet decided if I recommend rewriting these "three step" explanation, but FYI, the modern rebase machinery works slightly differently:

    First the command figures out what to replay, on which commit,
    and in what order.
    Then the HEAD is detached ("git checkout --detach <onto>") to
    the commit the first change is replayed onto.
    Then the changes are replayed, one by one, in the order.
    Optionally a mergy history can be rebased while retaining
    the topology.
    Finally, the branch being rebased is made to point at the
    resulting HEAD (i.e. equivalent to "git checkout -B <branch>"
    to jump back from the detached HEAD state).

The difference between the simplified procedure and this "replaying is done while on detached HEAD" procedure gives us a somewhat big usability improvement, as a rebasing will be recorded in a single reflog event for the branch getting rebased, no matter how many commits are on the branch.

Julia Evans via GitGitGadget· Aug 8, 2025, 22:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v3 0/5] doc: git-rebase: clarify DESCRIPTION section

I liked the idea of trying a more ambitious rewrite of the "here's how git rebase works internally" section, so here's an attempt at it.

My idea is to give an accurate technical description of how the merge backend works while deferring some of the details (like how exactly --fork-point works or what happens when you rebase a merge) to later in the man page. I've also tried to use a minimum of git jargon, for example saying "Then it checks out <upstream>" instead of mentioning anything about a "detached HEAD" since I know that term can jarring for folks who aren't used to that term.

I hedged a bit by saying that rebase is "similar to" running git cherry-pick repeatedly since I think of a rebase as being like doing a bunch of cherry-picks (and very often hear people describing it that way), but I'm sure that there are differences that I'm not aware of.

I've also updated the "clarify arguments syntax" commit message.
Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 300 ++++++++++++++++------------------
 1 file changed, 145 insertions(+), 155 deletions(-)
base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v3
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v3
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
Range-diff vs v2:
 1:  26b742eb49f = 1:  26b742eb49f doc: git-rebase: start with an example
 2:  249a5127904 = 2:  249a5127904 doc: git rebase: dedup merge conflict discussion
 3:  ce7ab74ea0f ! 3:  013a5044ef3 doc: git rebase: clarify arguments syntax
     @@ Metadata
       ## Commit message ##
          doc: git rebase: clarify arguments syntax
      
     -    This removes the explanation of `git rebase <upstream> <branch>`, since
     -    it was already explained above that it's shorthand for `git switch
     -    <branch> && git rebase <upstream>`
     +    Remove duplicate explanation of `git rebase <upstream> <branch>` which
     +    is already explained above.
      
          Signed-off-by: Julia Evans <julia@jvns.ca>
      
 4:  590d7486d3d = 4:  c574a27412d doc: git-rebase: move --onto explanation down
 5:  ad97cd9e671 ! 5:  eabacd3c159 doc: git-rebase: update discussion of internals
     @@ Metadata
       ## Commit message ##
          doc: git-rebase: update discussion of internals
      
     -    - make it clearer that we're talking about three steps of a process
     +    - make it clearer that we're talking about a multistep process
     +    - give a more technically accurate description how rebase works with the
     +      merge backend.
          - delete a duplicate explanation of how git rebase skips commits with
            the same textual changes (it's explained in more detail a few lines
            further down)
     -    - move the `ORIG_HEAD` note down so that it doesn't interrupt the
     -      discussion of the mechanics.
     +    - remove the explanation of how exactly `--fork-point` and `--root`
     +      work since that information is in the OPTIONS section
     +    - put all discussion of `ORIG_HEAD` inside the note
      
          Signed-off-by: Julia Evans <julia@jvns.ca>
      
     @@ Documentation/git-rebase.adoc: linkgit:git-config[1] for details) and the `--for
       branch does not have a configured upstream, the rebase will abort.
       
      -All changes made by commits in the current branch but that are not
     +-in `<upstream>` are saved to a temporary area.  This is the same set
     +-of commits that would be shown by `git log <upstream>..HEAD`; or by
     +-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
     +-description on `--fork-point` below); or by `git log HEAD`, if the
     +-`--root` option is specified.
     +-
     +-The current branch is reset to `<upstream>` or `<newbase>` if the
     +-`--onto` option was supplied.  This has the exact same effect as
     +-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
     +-to point at the tip of the branch before the reset.
      +Here is a more detailed description of what `git rebase <upstream>` does:
      +
     -+First, all changes made by commits in the current branch but that are not
     - in `<upstream>` are saved to a temporary area.  This is the same set
     - of commits that would be shown by `git log <upstream>..HEAD`; or by
     - `git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
     - description on `--fork-point` below); or by `git log HEAD`, if the
     - `--root` option is specified.
     - 
     --The current branch is reset to `<upstream>` or `<newbase>` if the
     -+Then the current branch is reset to `<upstream>` or `<newbase>` if the
     - `--onto` option was supplied.  This has the exact same effect as
     - `git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
     - to point at the tip of the branch before the reset.
     - 
     -+Then the commits that were previously saved into the temporary area are
     -+reapplied to the current branch, one by one, in order.
     ++First, it makes a list of all commits in the current branch that are not in
     ++`<upstream>`. This is the same set of commits that would be shown by `git log
     ++<upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
     ++list of commits is constructed.
     ++
     ++Then it checks out `<upstream>` (or `<newbase>` if the `--onto` option was
     ++supplied) with the equivalent of `git switch --detach <upstream>`.
      +
     ++Then it replays the commits, one by one, in order. This is similar to running
     ++`git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
     ++are handled.
     ++
     ++Finally, it updates your branch to point to the final commit with the equivalent
     ++of `git switch -C <branch>`.
     + 
       [NOTE]
     ++`ORIG_HEAD` is set to point at the tip of the branch before the rebase.
       `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
       at the end of the rebase if other commands that write that pseudo-ref
     -@@ Documentation/git-rebase.adoc: at the end of the rebase if other commands that write that pseudo-ref
     + (e.g. `git reset`) are used during the rebase. The previous branch tip,
       however, is accessible using the reflog of the current branch
       (i.e. `@{1}`, see linkgit:gitrevisions[7]).
       
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 22:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v3 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>

Start with an example that mirrors the example in the `git-merge` man page, to make it easier for folks to understand the difference between a rebase and a merge.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +23 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..6dacf693bd71 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,29 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+short-cut for `git switch topic && git rebase master`.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +81,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 22:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v3 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 50 +++++++++++++++--------------------
 1 file changed, 21 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +21 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 6dacf693bd71..a93c616f38b1 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -39,6 +39,27 @@ short-cut for `git switch topic && git rebase master`.
     D---E---F---G master
 ------------
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -74,13 +95,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -183,28 +197,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 22:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v3 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

Remove duplicate explanation of `git rebase <upstream> <branch>` which is already explained above.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
Show changes to Documentation/git-rebase.adoc +1 −6
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index a93c616f38b1..e700b92e35ac 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -59,12 +59,7 @@ one of these things:
 
    git rebase --skip
 
-
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 22:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v3 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Show changes to Documentation/git-rebase.adoc +87 −69
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index e700b92e35ac..6a4b3dbd5960 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -111,87 +111,6 @@ will result in:
     D---E---A'---F master
 ------------
 
-Here is how you would transplant a topic branch based on one
-branch to another, to pretend that you forked the topic branch
-from the latter branch, using `rebase --onto`.
-
-First let's assume your 'topic' is based on branch 'next'.
-For example, a feature developed in 'topic' depends on some
-functionality which is found in 'next'.
-
-------------
-    o---o---o---o---o  master
-         \
-          o---o---o---o---o  next
-                           \
-                            o---o---o  topic
-------------
-
-We want to make 'topic' forked from branch 'master'; for example,
-because the functionality on which 'topic' depends was merged into the
-more stable 'master' branch. We want our tree to look like this:
-
-------------
-    o---o---o---o---o  master
-        |            \
-        |             o'--o'--o'  topic
-         \
-          o---o---o---o---o  next
-------------
-
-We can get this using the following command:
-
-    git rebase --onto master next topic
-
-
-Another example of --onto option is to rebase part of a
-branch.  If we have the following situation:
-
-------------
-                            H---I---J topicB
-                           /
-                  E---F---G  topicA
-                 /
-    A---B---C---D  master
-------------
-
-then the command
-
-    git rebase --onto master topicA topicB
-
-would result in:
-
-------------
-                 H'--I'--J'  topicB
-                /
-                | E---F---G  topicA
-                |/
-    A---B---C---D  master
-------------
-
-This is useful when topicB does not depend on topicA.
-
-A range of commits could also be removed with rebase.  If we have
-the following situation:
-
-------------
-    E---F---G---H---I---J  topicA
-------------
-
-then the command
-
-    git rebase --onto topicA~5 topicA~3 topicA
-
-would result in the removal of commits F and G:
-
-------------
-    E---H'---I'---J'  topicA
-------------
-
-This is useful if F and G were flawed in some way, or should not be
-part of topicA.  Note that the argument to `--onto` and the `<upstream>`
-parameter can be any valid commit-ish.
-
 MODE OPTIONS
 ------------
 
@@ -237,6 +156,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -1015,6 +936,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
+Here is how you would transplant a topic branch based on one
+branch to another, to pretend that you forked the topic branch
+from the latter branch, using `rebase --onto`.
+
+First let's assume your 'topic' is based on branch 'next'.
+For example, a feature developed in 'topic' depends on some
+functionality which is found in 'next'.
+
+------------
+    o---o---o---o---o  master
+         \
+          o---o---o---o---o  next
+                           \
+                            o---o---o  topic
+------------
+
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
+
+------------
+    o---o---o---o---o  master
+        |            \
+        |             o'--o'--o'  topic
+         \
+          o---o---o---o---o  next
+------------
+
+We can get this using the following command:
+
+    git rebase --onto master next topic
+
+
+Another example of --onto option is to rebase part of a
+branch.  If we have the following situation:
+
+------------
+                            H---I---J topicB
+                           /
+                  E---F---G  topicA
+                 /
+    A---B---C---D  master
+------------
+
+then the command
+
+    git rebase --onto master topicA topicB
+
+would result in:
+
+------------
+                 H'--I'--J'  topicB
+                /
+                | E---F---G  topicA
+                |/
+    A---B---C---D  master
+------------
+
+This is useful when topicB does not depend on topicA.
+
+A range of commits could also be removed with rebase.  If we have
+the following situation:
+
+------------
+    E---F---G---H---I---J  topicA
+------------
+
+then the command
+
+    git rebase --onto topicA~5 topicA~3 topicA
+
+would result in the removal of commits F and G:
+
+------------
+    E---H'---I'---J'  topicA
+------------
+
+This is useful if F and G were flawed in some way, or should not be
+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
+parameter can be any valid commit-ish.
+
+
 RECOVERING FROM UPSTREAM REBASE
 -------------------------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 8, 2025, 22:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v3 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about a multistep process
- give a more technically accurate description how rebase works with the
  merge backend.
- delete a duplicate explanation of how git rebase skips commits with
  the same textual changes (it's explained in more detail a few lines
  further down)
- remove the explanation of how exactly `--fork-point` and `--root`
  work since that information is in the OPTIONS section
- put all discussion of `ORIG_HEAD` inside the note
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)
Show changes to Documentation/git-rebase.adoc +17 −17
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 6a4b3dbd5960..df77bbdecfec 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -65,31 +65,31 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
-in `<upstream>` are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`; or by
-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
-description on `--fork-point` below); or by `git log HEAD`, if the
-`--root` option is specified.
-
-The current branch is reset to `<upstream>` or `<newbase>` if the
-`--onto` option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
-to point at the tip of the branch before the reset.
+Here is a more detailed description of what `git rebase <upstream>` does:
+
+First, it makes a list of all commits in the current branch that are not in
+`<upstream>`. This is the same set of commits that would be shown by `git log
+<upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
+list of commits is constructed.
+
+Then it checks out `<upstream>` (or `<newbase>` if the `--onto` option was
+supplied) with the equivalent of `git switch --detach <upstream>`.
+
+Then it replays the commits, one by one, in order. This is similar to running
+`git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
+are handled.
+
+Finally, it updates your branch to point to the final commit with the equivalent
+of `git switch -C <branch>`.
 
 [NOTE]
+`ORIG_HEAD` is set to point at the tip of the branch before the rebase.
 `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
 at the end of the rebase if other commands that write that pseudo-ref
 (e.g. `git reset`) are used during the rebase. The previous branch tip,
 however, is accessible using the reflog of the current branch
 (i.e. `@{1}`, see linkgit:gitrevisions[7]).
 
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 9, 2025, 01:14 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v4 0/5] doc: git-rebase: clarify DESCRIPTION section

Replaced git switch topic && git rebase master with git checkout topic && git rebase master

Also "short-cut" with "shortcut" which is the spelling used elsewhere in the man pages

Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 300 ++++++++++++++++------------------
 1 file changed, 145 insertions(+), 155 deletions(-)
base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v4
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v4
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
Range-diff vs v3:
 1:  26b742eb49f ! 1:  07a4bdb7ce5 doc: git-rebase: start with an example
     @@ Documentation/git-rebase.adoc: SYNOPSIS
      +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
      +by running `git rebase master` while the `topic` branch is checked out.  If you
      +want to rebase `topic` while on another branch, `git rebase master topic` is a
     -+short-cut for `git switch topic && git rebase master`.
     ++shortcut for `git checkout topic && git rebase master`.
      +
      +------------
      +                  A'--B'--C' topic
 2:  249a5127904 ! 2:  061790686b9 doc: git rebase: dedup merge conflict discussion
     @@ Commit message
          Signed-off-by: Julia Evans <julia@jvns.ca>
      
       ## Documentation/git-rebase.adoc ##
     -@@ Documentation/git-rebase.adoc: short-cut for `git switch topic && git rebase master`.
     +@@ Documentation/git-rebase.adoc: shortcut for `git checkout topic && git rebase master`.
           D---E---F---G master
       ------------
       
 3:  013a5044ef3 = 3:  fe9e161a51b doc: git rebase: clarify arguments syntax
 4:  c574a27412d = 4:  b37ebc8389d doc: git-rebase: move --onto explanation down
 5:  eabacd3c159 = 5:  105a65e6e71 doc: git-rebase: update discussion of internals
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 9, 2025, 01:14 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v4 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>

Start with an example that mirrors the example in the `git-merge` man page, to make it easier for folks to understand the difference between a rebase and a merge.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +23 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..449f01fba560 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,29 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+shortcut for `git checkout topic && git rebase master`.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +81,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Phillip Wood· Aug 10, 2025, 15:41 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

Hi Julia
On 09/08/2025 02:14, Julia Evans via GitGitGadget wrote:
Show 5 quoted lines
> From: Julia Evans <julia@jvns.ca>
> 
> Start with an example that mirrors the example in the `git-merge` man
> page, to make it easier for folks to understand the difference between a
> rebase and a merge.

This is a very welcome improvement which makes it clear what rebasing a branch does. There are other important uses of rebase such as rearranging commits and squashing fixup commits that it would be nice to mention early on in the man page as well. Those do not necessarily change the base of the branch. I wonder if we could add a sentence about that which links to the INTERACTIVE MODE section.

Thanks
Phillip
Show 72 quoted lines
> Signed-off-by: Julia Evans <julia@jvns.ca>
> ---
>   Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
>   1 file changed, 23 insertions(+), 26 deletions(-)
> 
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index 956d3048f5a6..449f01fba560 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -16,6 +16,29 @@ SYNOPSIS
>   
>   DESCRIPTION
>   -----------
> +Transplant a series of commits onto a different starting point.
> +
> +For example, imagine that you have been working on the `topic` branch in this
> +history, and you want to "catch up" to the work done on the `master` branch.
> +
> +------------
> +          A---B---C topic
> +         /
> +    D---E---F---G master
> +------------
> +
> +You want to transplant the commits you made on `topic` since it diverged from
> +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
> +by running `git rebase master` while the `topic` branch is checked out.  If you
> +want to rebase `topic` while on another branch, `git rebase master topic` is a
> +shortcut for `git checkout topic && git rebase master`.
> +
> +------------
> +                  A'--B'--C' topic
> +                 /
> +    D---E---F---G master
> +------------
> +
>   If `<branch>` is specified, `git rebase` will perform an automatic
>   `git switch <branch>` before doing anything else.  Otherwise
>   it remains on the current branch.
> @@ -58,32 +81,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
>   original `<branch>` and remove the `.git/rebase-apply` working files, use
>   the command `git rebase --abort` instead.
>   
> -Assume the following history exists and the current branch is "topic":
> -
> -------------
> -          A---B---C topic
> -         /
> -    D---E---F---G master
> -------------
> -
> -From this point, the result of either of the following commands:
> -
> -
> -    git rebase master
> -    git rebase master topic
> -
> -would be:
> -
> -------------
> -                  A'--B'--C' topic
> -                 /
> -    D---E---F---G master
> -------------
> -
> -*NOTE:* The latter form is just a short-hand of `git checkout topic`
> -followed by `git rebase master`. When rebase exits `topic` will
> -remain the checked-out branch.
> -
>   If the upstream branch already contains a change you have made (e.g.,
>   because you mailed a patch which was applied upstream), then that commit
>   will be skipped and warnings will be issued (if the 'merge' backend is
Patrick Steinhardt· Aug 11, 2025, 08:46 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

On Sat, Aug 09, 2025 at 01:14:13AM +0000, Julia Evans via GitGitGadget wrote:
Show 5 quoted lines
> From: Julia Evans <julia@jvns.ca>
> 
> Start with an example that mirrors the example in the `git-merge` man
> page, to make it easier for folks to understand the difference between a
> rebase and a merge.
Makes sense.
Show 9 quoted lines
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index 956d3048f5a6..449f01fba560 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -16,6 +16,29 @@ SYNOPSIS
>  
>  DESCRIPTION
>  -----------
> +Transplant a series of commits onto a different starting point.
Nit: while this is one use case for git-rebase(1), I'd claim that
nowadays with interactive rebases there's the other use case where we
don't change the starting point but only edit the range of commits
itself.
So how about this instead:
    Edit a series of commits and optionally transplant it onto a
    different starting point.

We could also make the two different modes a bit more explicit by pointing out both different use cases directly.

If you agree then we should probably also modernize the description in the NAME section accordingly.

Patrick
Karthik Nayak· Aug 11, 2025, 09:13 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 6 quoted lines
> From: Julia Evans <julia@jvns.ca>
>
> Start with an example that mirrors the example in the `git-merge` man
> page, to make it easier for folks to understand the difference between a
> rebase and a merge.
>
Happy to see these changes.
Show 30 quoted lines
> Signed-off-by: Julia Evans <julia@jvns.ca>
> ---
>  Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
>  1 file changed, 23 insertions(+), 26 deletions(-)
>
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index 956d3048f5a6..449f01fba560 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -16,6 +16,29 @@ SYNOPSIS
>
>  DESCRIPTION
>  -----------
> +Transplant a series of commits onto a different starting point.
> +
> +For example, imagine that you have been working on the `topic` branch in this
> +history, and you want to "catch up" to the work done on the `master` branch.
> +
> +------------
> +          A---B---C topic
> +         /
> +    D---E---F---G master
> +------------
> +
> +You want to transplant the commits you made on `topic` since it diverged from
> +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
> +by running `git rebase master` while the `topic` branch is checked out.  If you
> +want to rebase `topic` while on another branch, `git rebase master topic` is a
> +shortcut for `git checkout topic && git rebase master`.
> +
Nit: now that `git-switch(1)` is no longer experimental, we should start
recommending it over `git-checkout(1)` as necessary. So perhaps, we
could s/checkout/switch here?
[snip]
Ben Knoble· Aug 11, 2025, 12:27 UTC · re: Karthik Nayak · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

Show 38 quoted lines
> Le 11 août 2025 à 05:29, Karthik Nayak <karthik.188@gmail.com> a écrit :
> 
> "Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
>> 
>> Signed-off-by: Julia Evans <julia@jvns.ca>
>> ---
>> Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
>> 1 file changed, 23 insertions(+), 26 deletions(-)
>> 
>> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
>> index 956d3048f5a6..449f01fba560 100644
>> --- a/Documentation/git-rebase.adoc
>> +++ b/Documentation/git-rebase.adoc
>> @@ -16,6 +16,29 @@ SYNOPSIS
>> 
>> DESCRIPTION
>> -----------
>> +Transplant a series of commits onto a different starting point.
>> +
>> +For example, imagine that you have been working on the `topic` branch in this
>> +history, and you want to "catch up" to the work done on the `master` branch.
>> +
>> +------------
>> +          A---B---C topic
>> +         /
>> +    D---E---F---G master
>> +------------
>> +
>> +You want to transplant the commits you made on `topic` since it diverged from
>> +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
>> +by running `git rebase master` while the `topic` branch is checked out.  If you
>> +want to rebase `topic` while on another branch, `git rebase master topic` is a
>> +shortcut for `git checkout topic && git rebase master`.
>> +
> 
> Nit: now that `git-switch(1)` is no longer experimental, we should start
> recommending it over `git-checkout(1)` as necessary. So perhaps, we
> could s/checkout/switch here?
Junio previously recommended checkout (a prior version used switch): I suspect because checkout will detach head without extra syntax (where switch will not)?
Karthik Nayak· Aug 12, 2025, 09:05 UTC · re: Ben Knoble · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

Ben Knoble <ben.knoble@gmail.com> writes:
Show 40 quoted lines
>> Le 11 août 2025 à 05:29, Karthik Nayak <karthik.188@gmail.com> a écrit :
>>
>> "Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
>>>
>>> Signed-off-by: Julia Evans <julia@jvns.ca>
>>> ---
>>> Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
>>> 1 file changed, 23 insertions(+), 26 deletions(-)
>>>
>>> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
>>> index 956d3048f5a6..449f01fba560 100644
>>> --- a/Documentation/git-rebase.adoc
>>> +++ b/Documentation/git-rebase.adoc
>>> @@ -16,6 +16,29 @@ SYNOPSIS
>>>
>>> DESCRIPTION
>>> -----------
>>> +Transplant a series of commits onto a different starting point.
>>> +
>>> +For example, imagine that you have been working on the `topic` branch in this
>>> +history, and you want to "catch up" to the work done on the `master` branch.
>>> +
>>> +------------
>>> +          A---B---C topic
>>> +         /
>>> +    D---E---F---G master
>>> +------------
>>> +
>>> +You want to transplant the commits you made on `topic` since it diverged from
>>> +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
>>> +by running `git rebase master` while the `topic` branch is checked out.  If you
>>> +want to rebase `topic` while on another branch, `git rebase master topic` is a
>>> +shortcut for `git checkout topic && git rebase master`.
>>> +
>>
>> Nit: now that `git-switch(1)` is no longer experimental, we should start
>> recommending it over `git-checkout(1)` as necessary. So perhaps, we
>> could s/checkout/switch here?
>
> Junio previously recommended checkout (a prior version used switch): I suspect because checkout will detach head without extra syntax (where switch will not)?
I totally missed that, that makes sense!
Junio C Hamano· Aug 12, 2025, 14:30 UTC · re: Karthik Nayak · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

Karthik Nayak <karthik.188@gmail.com> writes:
>>> Nit: now that `git-switch(1)` is no longer experimental, we should start
>>> recommending it over `git-checkout(1)` as necessary. So perhaps, we
>>> could s/checkout/switch here?

Besides, the reason why it is no longer experimental is *not* because it has proved to be so much better than "checkout" and the users are encouraged to use it.

It is no longer experimental only because it and its set of options are now engraved in users' mustle memory deep enough that we can no longer change it without disrupting users. We were hoping to improve its end-user experience relative to "checkout", and allowed it to deviate from the precendent that was set by "git checkout", and that was the reason why "this is experimental. UI and behaviour is subject to change" label was on it.

The experiment unfortunately was not a great success. There were only a few meaningful differences invented during the experiment.

Phillip Wood· Aug 11, 2025, 13:07 UTC · re: Karthik Nayak · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

On 11/08/2025 10:13, Karthik Nayak wrote:
Show 12 quoted lines
> "Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
>> +
>> +You want to transplant the commits you made on `topic` since it diverged from
>> +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
>> +by running `git rebase master` while the `topic` branch is checked out.  If you
>> +want to rebase `topic` while on another branch, `git rebase master topic` is a
>> +shortcut for `git checkout topic && git rebase master`.
>> +
> 
> Nit: now that `git-switch(1)` is no longer experimental, we should start
> recommending it over `git-checkout(1)` as necessary. So perhaps, we
> could s/checkout/switch here?

Junio has already expressed a preference for "checkout" here c.f. <xmqqldnte6h3.fsf@gitster.g>. I think that is technically correct as "topic" can be a commitish and "git switch <object-id>" fails without "--detach". Also rebase does not do any of the extra checks that "git switch" does before switching branches (I'm not saying that is necessarily a good thing).

Thanks
Phillip
Karthik Nayak· Aug 12, 2025, 09:07 UTC · re: Phillip Wood · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

Phillip Wood <phillip.wood123@gmail.com> writes:
Show 21 quoted lines
> On 11/08/2025 10:13, Karthik Nayak wrote:
>> "Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
>>> +
>>> +You want to transplant the commits you made on `topic` since it diverged from
>>> +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
>>> +by running `git rebase master` while the `topic` branch is checked out.  If you
>>> +want to rebase `topic` while on another branch, `git rebase master topic` is a
>>> +shortcut for `git checkout topic && git rebase master`.
>>> +
>>
>> Nit: now that `git-switch(1)` is no longer experimental, we should start
>> recommending it over `git-checkout(1)` as necessary. So perhaps, we
>> could s/checkout/switch here?
>
> Junio has already expressed a preference for "checkout" here c.f.
> <xmqqldnte6h3.fsf@gitster.g>. I think that is technically correct as
> "topic" can be a commitish and "git switch <object-id>" fails without
> "--detach". Also rebase does not do any of the extra checks that "git
> switch" does before switching branches (I'm not saying that is
> necessarily a good thing).
>

I missed that, but since we do mention that `topic` is a branch, it still makes sense to use 'git switch'. But either way this is okay.

> Thanks
>
> Phillip
D. Ben Knoble· Aug 12, 2025, 17:07 UTC · re: Karthik Nayak · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

On Tue, Aug 12, 2025 at 5:11 AM Karthik Nayak <karthik.188@gmail.com> wrote:
Show 27 quoted lines
>
> Phillip Wood <phillip.wood123@gmail.com> writes:
>
> > On 11/08/2025 10:13, Karthik Nayak wrote:
> >> "Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
> >>> +
> >>> +You want to transplant the commits you made on `topic` since it diverged from
> >>> +`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
> >>> +by running `git rebase master` while the `topic` branch is checked out.  If you
> >>> +want to rebase `topic` while on another branch, `git rebase master topic` is a
> >>> +shortcut for `git checkout topic && git rebase master`.
> >>> +
> >>
> >> Nit: now that `git-switch(1)` is no longer experimental, we should start
> >> recommending it over `git-checkout(1)` as necessary. So perhaps, we
> >> could s/checkout/switch here?
> >
> > Junio has already expressed a preference for "checkout" here c.f.
> > <xmqqldnte6h3.fsf@gitster.g>. I think that is technically correct as
> > "topic" can be a commitish and "git switch <object-id>" fails without
> > "--detach". Also rebase does not do any of the extra checks that "git
> > switch" does before switching branches (I'm not saying that is
> > necessarily a good thing).
> >
>
> I missed that, but since we do mention that `topic` is a branch, it
> still makes sense to use 'git switch'. But either way this is okay.

In the general case, it may not be a branch though. (Of course, that's too confusing a detail for this section anyway.)

-- 
D. Ben Knoble
Junio C Hamano· Aug 12, 2025, 18:07 UTC · re: D. Ben Knoble · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

"D. Ben Knoble" <ben.knoble@gmail.com> writes:
>> > Junio has already expressed a preference for "checkout" here c.f.
>> > <xmqqldnte6h3.fsf@gitster.g>. I think that is technically correct as
>> > "topic" can be a commitish and "git switch <object-id>" fails without
>> > "--detach".

I wanted the new documentation text to use what was already used in the parts of the document that are not touched; otherwise we end up with text that uses checkout in some places and switch in others, which would invite confusions among uninitiated readers, who rightfully would wonder what criteria were used to decide which one among these two different commands to use. And teaching that these two commands are quasi-equivalent with possibly subtle differences is not what the documentation of "git rebase" needs to do---it is a distraction.

I do not mind a new proposal to do a documentation sweep, aiming for Git 3.0 timeframe, to examine all mentions of "git checkout" in the documentation and replace them with "git switch" or "git restore" when appropriate (there are of course ones that are not for obvious reasons, like the ones in "git checkout" documentation itself, and possibly in "git switch" and "git restore" documentation pages that may say things like "'git switch X' is similar to 'git checkout Y'").

But let's leave that outside this topic.
Thanks.
Karthik Nayak· Aug 14, 2025, 07:23 UTC · re: Junio C Hamano · lore

Re: [PATCH v4 1/5] doc: git-rebase: start with an example

Junio C Hamano <gitster@pobox.com> writes:
Show 25 quoted lines
> "D. Ben Knoble" <ben.knoble@gmail.com> writes:
>
>>> > Junio has already expressed a preference for "checkout" here c.f.
>>> > <xmqqldnte6h3.fsf@gitster.g>. I think that is technically correct as
>>> > "topic" can be a commitish and "git switch <object-id>" fails without
>>> > "--detach".
>
> I wanted the new documentation text to use what was already used in
> the parts of the document that are not touched; otherwise we end up
> with text that uses checkout in some places and switch in others,
> which would invite confusions among uninitiated readers, who
> rightfully would wonder what criteria were used to decide which one
> among these two different commands to use.  And teaching that these
> two commands are quasi-equivalent with possibly subtle differences
> is not what the documentation of "git rebase" needs to do---it is a
> distraction.
>
> I do not mind a new proposal to do a documentation sweep, aiming for
> Git 3.0 timeframe, to examine all mentions of "git checkout" in the
> documentation and replace them with "git switch" or "git restore"
> when appropriate (there are of course ones that are not for obvious
> reasons, like the ones in "git checkout" documentation itself, and
> possibly in "git switch" and "git restore" documentation pages that
> may say things like "'git switch X' is similar to 'git checkout Y'").
>
I think this is the best way to tackle this.
> But let's leave that outside this topic.
>
Agreed.
> Thanks.
Julia Evans via GitGitGadget· Aug 9, 2025, 01:14 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v4 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 50 +++++++++++++++--------------------
 1 file changed, 21 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +21 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 449f01fba560..e30b9535fff1 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -39,6 +39,27 @@ shortcut for `git checkout topic && git rebase master`.
     D---E---F---G master
 ------------
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -74,13 +95,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -183,28 +197,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Patrick Steinhardt· Aug 11, 2025, 08:46 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v4 2/5] doc: git rebase: dedup merge conflict discussion

On Sat, Aug 09, 2025 at 01:14:14AM +0000, Julia Evans via GitGitGadget wrote:
Show 32 quoted lines
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index 449f01fba560..e30b9535fff1 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -39,6 +39,27 @@ shortcut for `git checkout topic && git rebase master`.
>      D---E---F---G master
>  ------------
>  
> +If there is a merge conflict during this process, `git rebase` will stop at the
> +first problematic commit and leave conflict markers. If this happens, you can do
> +one of these things:
> +
> +1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
> +   and make edits to resolve the conflict. For each file you edit, you need to
> +   tell Git that the conflict has been resolved. You can mark the conflict as
> +   resolved with  `git add <filename>`. After resolving all of the conflicts,
> +   you can continue the rebasing process with
> +
> +   git rebase --continue
> +
> +2. Stop the `git rebase` and return your branch to its original state with
> +
> +   git rebase --abort
> +
> +3. Skip the commit that caused the merge conflict with
> +
> +   git rebase --skip
> +
> +
>  If `<branch>` is specified, `git rebase` will perform an automatic
>  `git switch <branch>` before doing anything else.  Otherwise
>  it remains on the current branch.
Yup, this reads a lot nicer.
Show 14 quoted lines
> @@ -74,13 +95,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
>  in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
>  with a different commit message or timestamp will be skipped).
>  
> -It is possible that a merge failure will prevent this process from being
> -completely automatic.  You will have to resolve any such merge failure
> -and run `git rebase --continue`.  Another option is to bypass the commit
> -that caused the merge failure with `git rebase --skip`.  To check out the
> -original `<branch>` and remove the `.git/rebase-apply` working files, use
> -the command `git rebase --abort` instead.
> -
>  If the upstream branch already contains a change you have made (e.g.,
>  because you mailed a patch which was applied upstream), then that commit
>  will be skipped and warnings will be issued (if the 'merge' backend is

We lose the bit about `.git/rebase-apply`, but I don't think that's a bad thing. The user shouldn't have to care how exactly a rebase looks on disk. All they should need to know is that `git rebase --abort` gets them out of the state.

Patrick
Phillip Wood· Aug 11, 2025, 13:02 UTC · re: Patrick Steinhardt · lore

Re: [PATCH v4 2/5] doc: git rebase: dedup merge conflict discussion

On 11/08/2025 09:46, Patrick Steinhardt wrote:
Show 16 quoted lines
> On Sat, Aug 09, 2025 at 01:14:14AM +0000, Julia Evans via GitGitGadget wrote:
>>   
>> -It is possible that a merge failure will prevent this process from being
>> -completely automatic.  You will have to resolve any such merge failure
>> -and run `git rebase --continue`.  Another option is to bypass the commit
>> -that caused the merge failure with `git rebase --skip`.  To check out the
>> -original `<branch>` and remove the `.git/rebase-apply` working files, use
>> -the command `git rebase --abort` instead.
>> -
>>   If the upstream branch already contains a change you have made (e.g.,
>>   because you mailed a patch which was applied upstream), then that commit
>>   will be skipped and warnings will be issued (if the 'merge' backend is
> 
> We lose the bit about `.git/rebase-apply`, but I don't think that's a
> bad thing. The user shouldn't have to care how exactly a rebase looks on
> disk.

Exactly, we don't want to encourage the user to poke about in the state directory. Also ".git/rebase-apply" wont exist unless the user requested the apply backend so mentioning it is misleading (the default is ".git/rebase-merge" these days).

Thanks
Phillip
Julia Evans via GitGitGadget· Aug 9, 2025, 01:14 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v4 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

Remove duplicate explanation of `git rebase <upstream> <branch>` which is already explained above.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
Show changes to Documentation/git-rebase.adoc +1 −6
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index e30b9535fff1..914f743ae00f 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -59,12 +59,7 @@ one of these things:
 
    git rebase --skip
 
-
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 9, 2025, 01:14 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v4 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Show changes to Documentation/git-rebase.adoc +87 −69
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 914f743ae00f..50c84f138212 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -111,87 +111,6 @@ will result in:
     D---E---A'---F master
 ------------
 
-Here is how you would transplant a topic branch based on one
-branch to another, to pretend that you forked the topic branch
-from the latter branch, using `rebase --onto`.
-
-First let's assume your 'topic' is based on branch 'next'.
-For example, a feature developed in 'topic' depends on some
-functionality which is found in 'next'.
-
-------------
-    o---o---o---o---o  master
-         \
-          o---o---o---o---o  next
-                           \
-                            o---o---o  topic
-------------
-
-We want to make 'topic' forked from branch 'master'; for example,
-because the functionality on which 'topic' depends was merged into the
-more stable 'master' branch. We want our tree to look like this:
-
-------------
-    o---o---o---o---o  master
-        |            \
-        |             o'--o'--o'  topic
-         \
-          o---o---o---o---o  next
-------------
-
-We can get this using the following command:
-
-    git rebase --onto master next topic
-
-
-Another example of --onto option is to rebase part of a
-branch.  If we have the following situation:
-
-------------
-                            H---I---J topicB
-                           /
-                  E---F---G  topicA
-                 /
-    A---B---C---D  master
-------------
-
-then the command
-
-    git rebase --onto master topicA topicB
-
-would result in:
-
-------------
-                 H'--I'--J'  topicB
-                /
-                | E---F---G  topicA
-                |/
-    A---B---C---D  master
-------------
-
-This is useful when topicB does not depend on topicA.
-
-A range of commits could also be removed with rebase.  If we have
-the following situation:
-
-------------
-    E---F---G---H---I---J  topicA
-------------
-
-then the command
-
-    git rebase --onto topicA~5 topicA~3 topicA
-
-would result in the removal of commits F and G:
-
-------------
-    E---H'---I'---J'  topicA
-------------
-
-This is useful if F and G were flawed in some way, or should not be
-part of topicA.  Note that the argument to `--onto` and the `<upstream>`
-parameter can be any valid commit-ish.
-
 MODE OPTIONS
 ------------
 
@@ -237,6 +156,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -1015,6 +936,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
+Here is how you would transplant a topic branch based on one
+branch to another, to pretend that you forked the topic branch
+from the latter branch, using `rebase --onto`.
+
+First let's assume your 'topic' is based on branch 'next'.
+For example, a feature developed in 'topic' depends on some
+functionality which is found in 'next'.
+
+------------
+    o---o---o---o---o  master
+         \
+          o---o---o---o---o  next
+                           \
+                            o---o---o  topic
+------------
+
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
+
+------------
+    o---o---o---o---o  master
+        |            \
+        |             o'--o'--o'  topic
+         \
+          o---o---o---o---o  next
+------------
+
+We can get this using the following command:
+
+    git rebase --onto master next topic
+
+
+Another example of --onto option is to rebase part of a
+branch.  If we have the following situation:
+
+------------
+                            H---I---J topicB
+                           /
+                  E---F---G  topicA
+                 /
+    A---B---C---D  master
+------------
+
+then the command
+
+    git rebase --onto master topicA topicB
+
+would result in:
+
+------------
+                 H'--I'--J'  topicB
+                /
+                | E---F---G  topicA
+                |/
+    A---B---C---D  master
+------------
+
+This is useful when topicB does not depend on topicA.
+
+A range of commits could also be removed with rebase.  If we have
+the following situation:
+
+------------
+    E---F---G---H---I---J  topicA
+------------
+
+then the command
+
+    git rebase --onto topicA~5 topicA~3 topicA
+
+would result in the removal of commits F and G:
+
+------------
+    E---H'---I'---J'  topicA
+------------
+
+This is useful if F and G were flawed in some way, or should not be
+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
+parameter can be any valid commit-ish.
+
+
 RECOVERING FROM UPSTREAM REBASE
 -------------------------------
 
-- 
gitgitgadget
D. Ben Knoble· Aug 9, 2025, 14:55 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v4 4/5] doc: git-rebase: move --onto explanation down

On Fri, Aug 8, 2025 at 9:14 PM Julia Evans via GitGitGadget <gitgitgadget@gmail.com> wrote:

Show 24 quoted lines
>
> From: Julia Evans <julia@jvns.ca>
>
> There's a very clear explanation with examples of using --onto which is
> currently buried in the very long DESCRIPTION section. This moves it to
> its own section, so that we can reference the explanation from the
> `--onto` option by name.
>
> Signed-off-by: Julia Evans <julia@jvns.ca>
> ---
>  Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
>  1 file changed, 87 insertions(+), 81 deletions(-)
>
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index 914f743ae00f..50c84f138212 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -111,87 +111,6 @@ will result in:
>      D---E---A'---F master
>  ------------
>
> -Here is how you would transplant a topic branch based on one
> -branch to another, to pretend that you forked the topic branch
> -from the latter branch, using `rebase --onto`.

I wonder if we should leave a pointer to the reader to the new section here, also? The onto mode is not quite as common in my workflow as the other modes, but when helping less experienced users out I often end up using it, so keeping some reference to it early might be nice. IDK where a natural point is, though.

Show 186 quoted lines
> -
> -First let's assume your 'topic' is based on branch 'next'.
> -For example, a feature developed in 'topic' depends on some
> -functionality which is found in 'next'.
> -
> -------------
> -    o---o---o---o---o  master
> -         \
> -          o---o---o---o---o  next
> -                           \
> -                            o---o---o  topic
> -------------
> -
> -We want to make 'topic' forked from branch 'master'; for example,
> -because the functionality on which 'topic' depends was merged into the
> -more stable 'master' branch. We want our tree to look like this:
> -
> -------------
> -    o---o---o---o---o  master
> -        |            \
> -        |             o'--o'--o'  topic
> -         \
> -          o---o---o---o---o  next
> -------------
> -
> -We can get this using the following command:
> -
> -    git rebase --onto master next topic
> -
> -
> -Another example of --onto option is to rebase part of a
> -branch.  If we have the following situation:
> -
> -------------
> -                            H---I---J topicB
> -                           /
> -                  E---F---G  topicA
> -                 /
> -    A---B---C---D  master
> -------------
> -
> -then the command
> -
> -    git rebase --onto master topicA topicB
> -
> -would result in:
> -
> -------------
> -                 H'--I'--J'  topicB
> -                /
> -                | E---F---G  topicA
> -                |/
> -    A---B---C---D  master
> -------------
> -
> -This is useful when topicB does not depend on topicA.
> -
> -A range of commits could also be removed with rebase.  If we have
> -the following situation:
> -
> -------------
> -    E---F---G---H---I---J  topicA
> -------------
> -
> -then the command
> -
> -    git rebase --onto topicA~5 topicA~3 topicA
> -
> -would result in the removal of commits F and G:
> -
> -------------
> -    E---H'---I'---J'  topicA
> -------------
> -
> -This is useful if F and G were flawed in some way, or should not be
> -part of topicA.  Note that the argument to `--onto` and the `<upstream>`
> -parameter can be any valid commit-ish.
> -
>  MODE OPTIONS
>  ------------
>
> @@ -237,6 +156,8 @@ As a special case, you may use "A\...B" as a shortcut for the
>  merge base of A and B if there is exactly one merge base. You can
>  leave out at most one of A and B, in which case it defaults to HEAD.
>
> +See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
> +
>  --keep-base::
>         Set the starting point at which to create the new commits to the
>         merge base of `<upstream>` and `<branch>`. Running
> @@ -1015,6 +936,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
>  after each commit, test, and amend the commit if fixes are necessary.
>
>
> +TRANSPLANTING A TOPIC BRANCH WITH --ONTO
> +----------------------------------------
> +
> +Here is how you would transplant a topic branch based on one
> +branch to another, to pretend that you forked the topic branch
> +from the latter branch, using `rebase --onto`.
> +
> +First let's assume your 'topic' is based on branch 'next'.
> +For example, a feature developed in 'topic' depends on some
> +functionality which is found in 'next'.
> +
> +------------
> +    o---o---o---o---o  master
> +         \
> +          o---o---o---o---o  next
> +                           \
> +                            o---o---o  topic
> +------------
> +
> +We want to make 'topic' forked from branch 'master'; for example,
> +because the functionality on which 'topic' depends was merged into the
> +more stable 'master' branch. We want our tree to look like this:
> +
> +------------
> +    o---o---o---o---o  master
> +        |            \
> +        |             o'--o'--o'  topic
> +         \
> +          o---o---o---o---o  next
> +------------
> +
> +We can get this using the following command:
> +
> +    git rebase --onto master next topic
> +
> +
> +Another example of --onto option is to rebase part of a
> +branch.  If we have the following situation:
> +
> +------------
> +                            H---I---J topicB
> +                           /
> +                  E---F---G  topicA
> +                 /
> +    A---B---C---D  master
> +------------
> +
> +then the command
> +
> +    git rebase --onto master topicA topicB
> +
> +would result in:
> +
> +------------
> +                 H'--I'--J'  topicB
> +                /
> +                | E---F---G  topicA
> +                |/
> +    A---B---C---D  master
> +------------
> +
> +This is useful when topicB does not depend on topicA.
> +
> +A range of commits could also be removed with rebase.  If we have
> +the following situation:
> +
> +------------
> +    E---F---G---H---I---J  topicA
> +------------
> +
> +then the command
> +
> +    git rebase --onto topicA~5 topicA~3 topicA
> +
> +would result in the removal of commits F and G:
> +
> +------------
> +    E---H'---I'---J'  topicA
> +------------
> +
> +This is useful if F and G were flawed in some way, or should not be
> +part of topicA.  Note that the argument to `--onto` and the `<upstream>`
> +parameter can be any valid commit-ish.
> +
> +
>  RECOVERING FROM UPSTREAM REBASE
>  -------------------------------
>
> --
> gitgitgadget
>
>
-- 
D. Ben Knoble
Julia Evans via GitGitGadget· Aug 9, 2025, 01:14 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v4 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about a multistep process
- give a more technically accurate description how rebase works with the
  merge backend.
- delete a duplicate explanation of how git rebase skips commits with
  the same textual changes (it's explained in more detail a few lines
  further down)
- remove the explanation of how exactly `--fork-point` and `--root`
  work since that information is in the OPTIONS section
- put all discussion of `ORIG_HEAD` inside the note
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)
Show changes to Documentation/git-rebase.adoc +17 −17
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 50c84f138212..c16ee37b46a7 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -65,31 +65,31 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
-in `<upstream>` are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`; or by
-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
-description on `--fork-point` below); or by `git log HEAD`, if the
-`--root` option is specified.
-
-The current branch is reset to `<upstream>` or `<newbase>` if the
-`--onto` option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
-to point at the tip of the branch before the reset.
+Here is a more detailed description of what `git rebase <upstream>` does:
+
+First, it makes a list of all commits in the current branch that are not in
+`<upstream>`. This is the same set of commits that would be shown by `git log
+<upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
+list of commits is constructed.
+
+Then it checks out `<upstream>` (or `<newbase>` if the `--onto` option was
+supplied) with the equivalent of `git switch --detach <upstream>`.
+
+Then it replays the commits, one by one, in order. This is similar to running
+`git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
+are handled.
+
+Finally, it updates your branch to point to the final commit with the equivalent
+of `git switch -C <branch>`.
 
 [NOTE]
+`ORIG_HEAD` is set to point at the tip of the branch before the rebase.
 `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
 at the end of the rebase if other commands that write that pseudo-ref
 (e.g. `git reset`) are used during the rebase. The previous branch tip,
 however, is accessible using the reflog of the current branch
 (i.e. `@{1}`, see linkgit:gitrevisions[7]).
 
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Phillip Wood· Aug 10, 2025, 15:42 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v4 5/5] doc: git-rebase: update discussion of internals

Hi Julia
On 09/08/2025 02:14, Julia Evans via GitGitGadget wrote:
Show 7 quoted lines
> From: Julia Evans <julia@jvns.ca>
> 
> +Here is a more detailed description of what `git rebase <upstream>` does:
> +
> +First, it makes a list of all commits in the current branch that are not in
> +`<upstream>`. This is the same set of commits that would be shown by `git log
> +<upstream>..HEAD`.

The existing text is not quite accurate here, it should really say `git log --cherry-pick --right-only <upstream>...HEAD` as we drop any commits from the branch that have already been cherry-picked to <upstream>.

> You can use `--fork-point` or `--root` to change how this
> +list of commits is constructed.

`--reapply-cherry-picks` also changes how the list is constructed so I think it would be worth adding that option here as well.

Thanks for working on this, it makes the description section much more readable.

Phillip
Show 28 quoted lines
> +
> +Then it checks out `<upstream>` (or `<newbase>` if the `--onto` option was
> +supplied) with the equivalent of `git switch --detach <upstream>`.
> +
> +Then it replays the commits, one by one, in order. This is similar to running
> +`git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
> +are handled.
> +
> +Finally, it updates your branch to point to the final commit with the equivalent
> +of `git switch -C <branch>`.
>   
>   [NOTE]
> +`ORIG_HEAD` is set to point at the tip of the branch before the rebase.
>   `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
>   at the end of the rebase if other commands that write that pseudo-ref
>   (e.g. `git reset`) are used during the rebase. The previous branch tip,
>   however, is accessible using the reflog of the current branch
>   (i.e. `@{1}`, see linkgit:gitrevisions[7]).
>   
> -The commits that were previously saved into the temporary area are
> -then reapplied to the current branch, one by one, in order. Note that
> -any commits in `HEAD` which introduce the same textual changes as a commit
> -in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
> -with a different commit message or timestamp will be skipped).
> -
>   If the upstream branch already contains a change you have made (e.g.,
>   because you mailed a patch which was applied upstream), then that commit
>   will be skipped and warnings will be issued (if the 'merge' backend is
D. Ben Knoble· Aug 13, 2025, 18:55 UTC · re: Phillip Wood · lore

symmetric difference with --left-only vs. range notation

On Sun, Aug 10, 2025 at 11:42 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
Show 15 quoted lines
>
> Hi Julia
>
> On 09/08/2025 02:14, Julia Evans via GitGitGadget wrote:
> > From: Julia Evans <julia@jvns.ca>
> >
> > +Here is a more detailed description of what `git rebase <upstream>` does:
> > +
> > +First, it makes a list of all commits in the current branch that are not in
> > +`<upstream>`. This is the same set of commits that would be shown by `git log
> > +<upstream>..HEAD`.
>
> The existing text is not quite accurate here, it should really say `git
> log --cherry-pick --right-only <upstream>...HEAD` as we drop any commits
> from the branch that have already been cherry-picked to <upstream>.

This reminds me, I've been meaning to ask: is there a meaningful difference between the following 2 commands?

    git rev-list --count --left-only @{u}...
    git rev-list --count ..@{u}

In my estimation, since we're not using --cherry-pick here, the first says "list (count) the commits on upstream but not in HEAD, since the merge-base (which is reachable from both)" while the second says "list (count) the commits on upstream but not in HEAD." Is there ever a situation where those sets aren't the same?

Of course the symmetric difference is not always the same as the range notation, but when we add --left-only [or --right-only, by symmetry ;)], does this collapse to the 2-dot notation?

I've been assuming the latter is more performant, too, but if that's not the case, that's also good to know.

Junio C Hamano· Aug 13, 2025, 21:40 UTC · re: D. Ben Knoble · lore

Re: symmetric difference with --left-only vs. range notation

"D. Ben Knoble" <ben.knoble@gmail.com> writes:
Show 8 quoted lines
>     git rev-list --count --left-only @{u}...
>     git rev-list --count ..@{u}
>
> In my estimation, since we're not using --cherry-pick here, the first
> says "list (count) the commits on upstream but not in HEAD, since the
> merge-base (which is reachable from both)" while the second says "list
> (count) the commits on upstream but not in HEAD." Is there ever a
> situation where those sets aren't the same?

I don't think of any; let us know when you find a case that the above does not hold true ;-).

Patrick Steinhardt· Aug 11, 2025, 08:46 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v4 5/5] doc: git-rebase: update discussion of internals

On Sat, Aug 09, 2025 at 01:14:17AM +0000, Julia Evans via GitGitGadget wrote:
Show 35 quoted lines
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index 50c84f138212..c16ee37b46a7 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -65,31 +65,31 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
>  assumed.  If you are currently not on any branch or if the current
>  branch does not have a configured upstream, the rebase will abort.
>  
> -All changes made by commits in the current branch but that are not
> -in `<upstream>` are saved to a temporary area.  This is the same set
> -of commits that would be shown by `git log <upstream>..HEAD`; or by
> -`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
> -description on `--fork-point` below); or by `git log HEAD`, if the
> -`--root` option is specified.
> -
> -The current branch is reset to `<upstream>` or `<newbase>` if the
> -`--onto` option was supplied.  This has the exact same effect as
> -`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
> -to point at the tip of the branch before the reset.
> +Here is a more detailed description of what `git rebase <upstream>` does:
> +
> +First, it makes a list of all commits in the current branch that are not in
> +`<upstream>`. This is the same set of commits that would be shown by `git log
> +<upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
> +list of commits is constructed.
> +
> +Then it checks out `<upstream>` (or `<newbase>` if the `--onto` option was
> +supplied) with the equivalent of `git switch --detach <upstream>`.
> +
> +Then it replays the commits, one by one, in order. This is similar to running
> +`git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
> +are handled.
> +
> +Finally, it updates your branch to point to the final commit with the equivalent
> +of `git switch -C <branch>`.

Would it make sense to convert this into a bulleted list to further highlight this multi-step process?

Show 7 quoted lines
>  [NOTE]
> +`ORIG_HEAD` is set to point at the tip of the branch before the rebase.
>  `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
>  at the end of the rebase if other commands that write that pseudo-ref
>  (e.g. `git reset`) are used during the rebase. The previous branch tip,
>  however, is accessible using the reflog of the current branch
>  (i.e. `@{1}`, see linkgit:gitrevisions[7]).

This information feels somewhat contradictory. Should we maybe say something like this:

    When starting the rebase, `ORIG_HEAD` is set to point to at the tip
    of the to-be-rebased branch. As `ORIG_HEAD` may be modified by
    various operations during the rebase, it is not guaranteed to still
    point to this branch at the end of the rebase. The previous branch
    tip, however, is accessible using the reflog of the current branch
    (i.e. `@{1}`, see linkgit:gitrevisions[7]).

Note that I'm also dropping the reference to "pseudo-ref". ORIG_HEAD is not a pseudo-ref, as we have clarified in 6fd8037564 (Documentation/glossary: redefine pseudorefs as special refs, 2024-05-15).

Patrick
Ben Knoble· Aug 11, 2025, 12:29 UTC · re: Patrick Steinhardt · lore

Re: [PATCH v4 5/5] doc: git-rebase: update discussion of internals

Show 41 quoted lines
> Le 11 août 2025 à 04:46, Patrick Steinhardt <ps@pks.im> a écrit :
> 
> On Sat, Aug 09, 2025 at 01:14:17AM +0000, Julia Evans via GitGitGadget wrote:
>> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
>> index 50c84f138212..c16ee37b46a7 100644
>> --- a/Documentation/git-rebase.adoc
>> +++ b/Documentation/git-rebase.adoc
>> @@ -65,31 +65,31 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
>> assumed.  If you are currently not on any branch or if the current
>> branch does not have a configured upstream, the rebase will abort.
>> 
>> -All changes made by commits in the current branch but that are not
>> -in `<upstream>` are saved to a temporary area.  This is the same set
>> -of commits that would be shown by `git log <upstream>..HEAD`; or by
>> -`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
>> -description on `--fork-point` below); or by `git log HEAD`, if the
>> -`--root` option is specified.
>> -
>> -The current branch is reset to `<upstream>` or `<newbase>` if the
>> -`--onto` option was supplied.  This has the exact same effect as
>> -`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
>> -to point at the tip of the branch before the reset.
>> +Here is a more detailed description of what `git rebase <upstream>` does:
>> +
>> +First, it makes a list of all commits in the current branch that are not in
>> +`<upstream>`. This is the same set of commits that would be shown by `git log
>> +<upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
>> +list of commits is constructed.
>> +
>> +Then it checks out `<upstream>` (or `<newbase>` if the `--onto` option was
>> +supplied) with the equivalent of `git switch --detach <upstream>`.
>> +
>> +Then it replays the commits, one by one, in order. This is similar to running
>> +`git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
>> +are handled.
>> +
>> +Finally, it updates your branch to point to the final commit with the equivalent
>> +of `git switch -C <branch>`.
> 
> Would it make sense to convert this into a bulleted list to further
> highlight this multi-step process?
Nit: ordered list, perhaps? Unless we don’t use those in our manuals (away from documentation at the moment). 
Patrick Steinhardt· Aug 11, 2025, 13:45 UTC · re: Ben Knoble · lore

Re: [PATCH v4 5/5] doc: git-rebase: update discussion of internals

On Mon, Aug 11, 2025 at 08:29:42AM -0400, Ben Knoble wrote:
Show 45 quoted lines
> 
> > Le 11 août 2025 à 04:46, Patrick Steinhardt <ps@pks.im> a écrit :
> > 
> > On Sat, Aug 09, 2025 at 01:14:17AM +0000, Julia Evans via GitGitGadget wrote:
> >> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> >> index 50c84f138212..c16ee37b46a7 100644
> >> --- a/Documentation/git-rebase.adoc
> >> +++ b/Documentation/git-rebase.adoc
> >> @@ -65,31 +65,31 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
> >> assumed.  If you are currently not on any branch or if the current
> >> branch does not have a configured upstream, the rebase will abort.
> >> 
> >> -All changes made by commits in the current branch but that are not
> >> -in `<upstream>` are saved to a temporary area.  This is the same set
> >> -of commits that would be shown by `git log <upstream>..HEAD`; or by
> >> -`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
> >> -description on `--fork-point` below); or by `git log HEAD`, if the
> >> -`--root` option is specified.
> >> -
> >> -The current branch is reset to `<upstream>` or `<newbase>` if the
> >> -`--onto` option was supplied.  This has the exact same effect as
> >> -`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
> >> -to point at the tip of the branch before the reset.
> >> +Here is a more detailed description of what `git rebase <upstream>` does:
> >> +
> >> +First, it makes a list of all commits in the current branch that are not in
> >> +`<upstream>`. This is the same set of commits that would be shown by `git log
> >> +<upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
> >> +list of commits is constructed.
> >> +
> >> +Then it checks out `<upstream>` (or `<newbase>` if the `--onto` option was
> >> +supplied) with the equivalent of `git switch --detach <upstream>`.
> >> +
> >> +Then it replays the commits, one by one, in order. This is similar to running
> >> +`git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
> >> +are handled.
> >> +
> >> +Finally, it updates your branch to point to the final commit with the equivalent
> >> +of `git switch -C <branch>`.
> > 
> > Would it make sense to convert this into a bulleted list to further
> > highlight this multi-step process?
> 
> Nit: ordered list, perhaps? Unless we don’t use those in our manuals
> (away from documentation at the moment). 

Ah, I actually wanted to propose using an ordered list, not bulleted list. Thanks for correcting me.

Patrick
Julia Evans· Aug 11, 2025, 19:34 UTC · re: Patrick Steinhardt · lore

Re: [PATCH v4 5/5] doc: git-rebase: update discussion of internals

> Would it make sense to convert this into a bulleted list to further
> highlight this multi-step process?

I like this idea. I think we can combine this with Phillip's point about "--reapply-cherry-picks" to expand the list a little more and remove the paragraph at the end about how duplicate commits are skipped. ("If the upstream branch already contains a change you have made...") I think probably the diagram can be removed too, I'm not sure how much value it's adding.

1. Make a list of all commits in the current branch that are not in
   `<upstream>`. This is the same set of commits that would be shown by `git log
   <upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
   list of commits is constructed.
2. Check whether any of those commits are duplicates of commits already
   in `<upstream>`, remove them from the list, and print out a warning about
   each removed commit. You can use `--reapply-cherry-picks` to include
   duplicate commits.
3. Check out `<upstream>` (or `<newbase>` if the `--onto` option was
   supplied) with the equivalent of `git checkout --detach <upstream>`.
4. Replay the commits, one by one, in order. This is similar to running
   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
   are handled.
5. Update your branch to point to the final commit with the equivalent
   of `git switch -C <branch>`.

I imagine actually #1 and #2 happen concurrently, but I split them up because it felt unwieldy to explain them both the same point.

Show 23 quoted lines
>
>>  [NOTE]
>> +`ORIG_HEAD` is set to point at the tip of the branch before the rebase.
>>  `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
>>  at the end of the rebase if other commands that write that pseudo-ref
>>  (e.g. `git reset`) are used during the rebase. The previous branch tip,
>>  however, is accessible using the reflog of the current branch
>>  (i.e. `@{1}`, see linkgit:gitrevisions[7]).
>
> This information feels somewhat contradictory. Should we maybe say
> something like this:
>
>     When starting the rebase, `ORIG_HEAD` is set to point to at the tip
>     of the to-be-rebased branch. As `ORIG_HEAD` may be modified by
>     various operations during the rebase, it is not guaranteed to still
>     point to this branch at the end of the rebase. The previous branch
>     tip, however, is accessible using the reflog of the current branch
>     (i.e. `@{1}`, see linkgit:gitrevisions[7]).
>
> Note that I'm also dropping the reference to "pseudo-ref". ORIG_HEAD is
> not a pseudo-ref, as we have clarified in 6fd8037564
> (Documentation/glossary: redefine pseudorefs as special refs,
> 2024-05-15).
I like that! Also very happy to remove the word "pseudo-ref".
- Julia
Julia Evans via GitGitGadget· Aug 11, 2025, 20:12 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v5 0/5] doc: git-rebase: clarify DESCRIPTION section

 * Add a note about how you can use git rebase to reorder or combine commits
 * Convert the explanation of how rebase works to an ordered list, make it
   more accurate (include how duplicate commits are removed), and remove the
   diagram showing how duplicate commits are removed. I'm happy to bring the
   diagram back if folks think it's important, but I felt like it made the
   section end in an awkward way and I'm not sure that "git rebase removes
   duplicate commits" really needs a diagram to explain it.
Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 305 ++++++++++++++++------------------
 1 file changed, 139 insertions(+), 166 deletions(-)
base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v5
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v5
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
Range-diff vs v4:
 1:  07a4bdb7ce5 ! 1:  c2f2e05078f doc: git-rebase: start with an example
     @@ Metadata
       ## Commit message ##
          doc: git-rebase: start with an example
      
     -    Start with an example that mirrors the example in the `git-merge` man
     -    page, to make it easier for folks to understand the difference between a
     -    rebase and a merge.
     +    - Start with an example that mirrors the example in the `git-merge` man
     +      page, to make it easier for folks to understand the difference between
     +      a rebase and a merge.
     +    - Mention that rebase can combine or reorder commits
      
          Signed-off-by: Julia Evans <julia@jvns.ca>
      
     @@ Documentation/git-rebase.adoc: SYNOPSIS
      +                 /
      +    D---E---F---G master
      +------------
     ++
     ++You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
     ++MODE below for how to do that.
      +
       If `<branch>` is specified, `git rebase` will perform an automatic
       `git switch <branch>` before doing anything else.  Otherwise
 2:  061790686b9 ! 2:  5459b7ff560 doc: git rebase: dedup merge conflict discussion
     @@ Commit message
      
       ## Documentation/git-rebase.adoc ##
      @@ Documentation/git-rebase.adoc: shortcut for `git checkout topic && git rebase master`.
     -     D---E---F---G master
     - ------------
     + You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
     + MODE below for how to do that.
       
      +If there is a merge conflict during this process, `git rebase` will stop at the
      +first problematic commit and leave conflict markers. If this happens, you can do
     @@ Documentation/git-rebase.adoc: shortcut for `git checkout topic && git rebase ma
      +3. Skip the commit that caused the merge conflict with
      +
      +   git rebase --skip
     -+
      +
       If `<branch>` is specified, `git rebase` will perform an automatic
       `git switch <branch>` before doing anything else.  Otherwise
 3:  fe9e161a51b ! 3:  948c205f1e6 doc: git rebase: clarify arguments syntax
     @@ Documentation/git-rebase.adoc: one of these things:
       
          git rebase --skip
       
     --
      -If `<branch>` is specified, `git rebase` will perform an automatic
      -`git switch <branch>` before doing anything else.  Otherwise
      -it remains on the current branch.
 4:  b37ebc8389d = 4:  e229b9fccb2 doc: git-rebase: move --onto explanation down
 5:  105a65e6e71 ! 5:  5ab235b067b doc: git-rebase: update discussion of internals
     @@ Commit message
          - make it clearer that we're talking about a multistep process
          - give a more technically accurate description how rebase works with the
            merge backend.
     -    - delete a duplicate explanation of how git rebase skips commits with
     -      the same textual changes (it's explained in more detail a few lines
     -      further down)
     +    - condense the explanation of how git rebase skips commits with the same
     +      textual changes into a single bullet point and remove the explanatory
     +      diagram. Lots of things which are more complicated are already being
     +      explained without a diagram.
          - remove the explanation of how exactly `--fork-point` and `--root`
            work since that information is in the OPTIONS section
          - put all discussion of `ORIG_HEAD` inside the note
     @@ Documentation/git-rebase.adoc: linkgit:git-config[1] for details) and the `--for
      -to point at the tip of the branch before the reset.
      +Here is a more detailed description of what `git rebase <upstream>` does:
      +
     -+First, it makes a list of all commits in the current branch that are not in
     -+`<upstream>`. This is the same set of commits that would be shown by `git log
     -+<upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
     -+list of commits is constructed.
     -+
     -+Then it checks out `<upstream>` (or `<newbase>` if the `--onto` option was
     -+supplied) with the equivalent of `git switch --detach <upstream>`.
     -+
     -+Then it replays the commits, one by one, in order. This is similar to running
     -+`git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
     -+are handled.
     -+
     -+Finally, it updates your branch to point to the final commit with the equivalent
     -+of `git switch -C <branch>`.
     ++1. Make a list of all commits in the current branch that are not in
     ++   `<upstream>`. This is the same set of commits that would be shown by `git log
     ++   <upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
     ++   list of commits is constructed.
     ++2. Check whether any of those commits are duplicates of commits already
     ++   in `<upstream>`, remove them from the list, and print out a warning about
     ++   each removed commit. You can use `--reapply-cherry-picks` to include
     ++   duplicate commits.
     ++3. Check out `<upstream>` (or `<newbase>` if the `--onto` option was
     ++   supplied) with the equivalent of `git checkout --detach <upstream>`.
     ++4. Replay the commits, one by one, in order. This is similar to running
     ++   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
     ++   are handled.
     ++5. Update your branch to point to the final commit with the equivalent
     ++   of `git switch -C <branch>`.
       
       [NOTE]
     -+`ORIG_HEAD` is set to point at the tip of the branch before the rebase.
     - `ORIG_HEAD` is not guaranteed to still point to the previous branch tip
     - at the end of the rebase if other commands that write that pseudo-ref
     - (e.g. `git reset`) are used during the rebase. The previous branch tip,
     - however, is accessible using the reflog of the current branch
     - (i.e. `@{1}`, see linkgit:gitrevisions[7]).
     - 
     +-`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
     +-at the end of the rebase if other commands that write that pseudo-ref
     +-(e.g. `git reset`) are used during the rebase. The previous branch tip,
     +-however, is accessible using the reflog of the current branch
     +-(i.e. `@{1}`, see linkgit:gitrevisions[7]).
     +-
      -The commits that were previously saved into the temporary area are
      -then reapplied to the current branch, one by one, in order. Note that
      -any commits in `HEAD` which introduce the same textual changes as a commit
      -in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
      -with a different commit message or timestamp will be skipped).
      -
     - If the upstream branch already contains a change you have made (e.g.,
     - because you mailed a patch which was applied upstream), then that commit
     - will be skipped and warnings will be issued (if the 'merge' backend is
     +-If the upstream branch already contains a change you have made (e.g.,
     +-because you mailed a patch which was applied upstream), then that commit
     +-will be skipped and warnings will be issued (if the 'merge' backend is
     +-used).  For example, running `git rebase master` on the following
     +-history (in which `A'` and `A` introduce the same set of changes, but
     +-have different committer information):
     +-
     +-------------
     +-          A---B---C topic
     +-         /
     +-    D---E---A'---F master
     +-------------
     +-
     +-will result in:
     +-
     +-------------
     +-                   B'---C' topic
     +-                  /
     +-    D---E---A'---F master
     +-------------
     ++When starting the rebase, `ORIG_HEAD` is set to point to the commit at the tip
     ++of the to-be-rebased branch. However, `ORIG_HEAD` is not guaranteed to still
     ++point to that commit at the end of the rebase if other commands that change
     ++`ORIG_HEAD` (like `git reset`) are used during the rebase. The previous branch
     ++tip, however, is accessible using the reflog of the current branch (i.e. `@{1}`,
     ++see linkgit:gitrevisions[7].
     + 
     + MODE OPTIONS
     + ------------
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 20:12 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v5 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>
- Start with an example that mirrors the example in the `git-merge` man
  page, to make it easier for folks to understand the difference between
  a rebase and a merge.
- Mention that rebase can combine or reorder commits
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +26 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..03d1b74a9a09 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,32 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+shortcut for `git checkout topic && git rebase master`.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
+You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
+MODE below for how to do that.
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +84,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Junio C Hamano· Aug 11, 2025, 20:50 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v5 1/5] doc: git-rebase: start with an example

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 6 quoted lines
> From: Julia Evans <julia@jvns.ca>
>
> - Start with an example that mirrors the example in the `git-merge` man
>   page, to make it easier for folks to understand the difference between
>   a rebase and a merge.
> - Mention that rebase can combine or reorder commits

The new comment added by this second point looks somewhat out of place. With this patch as-is, the text talks only about the best case of the basic usage, tell the reader to go elsewhere if they are not interested in learning the basic usage, and then switches back to the basic usage topic and talks about conflict resolution.

It may be easier to read if you covered the fact that there are two major use cases upfront, perhaps like:

    DESCRIPTION
    -----------
    Transplant a series of commits onto a different starting point.
    You can also use `git rebase` to reorder or combine commits: see
    INTERACTIVE MODE below for how to do that.
    For example, imagine ...
Julia Evans via GitGitGadget· Aug 11, 2025, 20:12 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v5 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +20 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 03d1b74a9a09..4ba74a8cf9ba 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -42,6 +42,26 @@ shortcut for `git checkout topic && git rebase master`.
 You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
 MODE below for how to do that.
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -77,13 +97,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -186,28 +199,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 20:12 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v5 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

Remove duplicate explanation of `git rebase <upstream> <branch>` which is already explained above.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Show changes to Documentation/git-rebase.adoc +1 −5
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 4ba74a8cf9ba..117c3f43719f 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -62,11 +62,7 @@ one of these things:
 
    git rebase --skip
 
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 20:12 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v5 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Show changes to Documentation/git-rebase.adoc +87 −69
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 117c3f43719f..750f5e67e4c3 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -114,87 +114,6 @@ will result in:
     D---E---A'---F master
 ------------
 
-Here is how you would transplant a topic branch based on one
-branch to another, to pretend that you forked the topic branch
-from the latter branch, using `rebase --onto`.
-
-First let's assume your 'topic' is based on branch 'next'.
-For example, a feature developed in 'topic' depends on some
-functionality which is found in 'next'.
-
-------------
-    o---o---o---o---o  master
-         \
-          o---o---o---o---o  next
-                           \
-                            o---o---o  topic
-------------
-
-We want to make 'topic' forked from branch 'master'; for example,
-because the functionality on which 'topic' depends was merged into the
-more stable 'master' branch. We want our tree to look like this:
-
-------------
-    o---o---o---o---o  master
-        |            \
-        |             o'--o'--o'  topic
-         \
-          o---o---o---o---o  next
-------------
-
-We can get this using the following command:
-
-    git rebase --onto master next topic
-
-
-Another example of --onto option is to rebase part of a
-branch.  If we have the following situation:
-
-------------
-                            H---I---J topicB
-                           /
-                  E---F---G  topicA
-                 /
-    A---B---C---D  master
-------------
-
-then the command
-
-    git rebase --onto master topicA topicB
-
-would result in:
-
-------------
-                 H'--I'--J'  topicB
-                /
-                | E---F---G  topicA
-                |/
-    A---B---C---D  master
-------------
-
-This is useful when topicB does not depend on topicA.
-
-A range of commits could also be removed with rebase.  If we have
-the following situation:
-
-------------
-    E---F---G---H---I---J  topicA
-------------
-
-then the command
-
-    git rebase --onto topicA~5 topicA~3 topicA
-
-would result in the removal of commits F and G:
-
-------------
-    E---H'---I'---J'  topicA
-------------
-
-This is useful if F and G were flawed in some way, or should not be
-part of topicA.  Note that the argument to `--onto` and the `<upstream>`
-parameter can be any valid commit-ish.
-
 MODE OPTIONS
 ------------
 
@@ -240,6 +159,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -1018,6 +939,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
+Here is how you would transplant a topic branch based on one
+branch to another, to pretend that you forked the topic branch
+from the latter branch, using `rebase --onto`.
+
+First let's assume your 'topic' is based on branch 'next'.
+For example, a feature developed in 'topic' depends on some
+functionality which is found in 'next'.
+
+------------
+    o---o---o---o---o  master
+         \
+          o---o---o---o---o  next
+                           \
+                            o---o---o  topic
+------------
+
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
+
+------------
+    o---o---o---o---o  master
+        |            \
+        |             o'--o'--o'  topic
+         \
+          o---o---o---o---o  next
+------------
+
+We can get this using the following command:
+
+    git rebase --onto master next topic
+
+
+Another example of --onto option is to rebase part of a
+branch.  If we have the following situation:
+
+------------
+                            H---I---J topicB
+                           /
+                  E---F---G  topicA
+                 /
+    A---B---C---D  master
+------------
+
+then the command
+
+    git rebase --onto master topicA topicB
+
+would result in:
+
+------------
+                 H'--I'--J'  topicB
+                /
+                | E---F---G  topicA
+                |/
+    A---B---C---D  master
+------------
+
+This is useful when topicB does not depend on topicA.
+
+A range of commits could also be removed with rebase.  If we have
+the following situation:
+
+------------
+    E---F---G---H---I---J  topicA
+------------
+
+then the command
+
+    git rebase --onto topicA~5 topicA~3 topicA
+
+would result in the removal of commits F and G:
+
+------------
+    E---H'---I'---J'  topicA
+------------
+
+This is useful if F and G were flawed in some way, or should not be
+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
+parameter can be any valid commit-ish.
+
+
 RECOVERING FROM UPSTREAM REBASE
 -------------------------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 20:12 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v5 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about a multistep process
- give a more technically accurate description how rebase works with the
  merge backend.
- condense the explanation of how git rebase skips commits with the same
  textual changes into a single bullet point and remove the explanatory
  diagram. Lots of things which are more complicated are already being
  explained without a diagram.
- remove the explanation of how exactly `--fork-point` and `--root`
  work since that information is in the OPTIONS section
- put all discussion of `ORIG_HEAD` inside the note
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 66 ++++++++++++-----------------------
 1 file changed, 23 insertions(+), 43 deletions(-)
Show changes to Documentation/git-rebase.adoc +23 −39
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 750f5e67e4c3..b4e5519d2839 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -68,51 +68,31 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
-in `<upstream>` are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`; or by
-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
-description on `--fork-point` below); or by `git log HEAD`, if the
-`--root` option is specified.
-
-The current branch is reset to `<upstream>` or `<newbase>` if the
-`--onto` option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
-to point at the tip of the branch before the reset.
+Here is a more detailed description of what `git rebase <upstream>` does:
+
+1. Make a list of all commits in the current branch that are not in
+   `<upstream>`. This is the same set of commits that would be shown by `git log
+   <upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
+   list of commits is constructed.
+2. Check whether any of those commits are duplicates of commits already
+   in `<upstream>`, remove them from the list, and print out a warning about
+   each removed commit. You can use `--reapply-cherry-picks` to include
+   duplicate commits.
+3. Check out `<upstream>` (or `<newbase>` if the `--onto` option was
+   supplied) with the equivalent of `git checkout --detach <upstream>`.
+4. Replay the commits, one by one, in order. This is similar to running
+   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
+   are handled.
+5. Update your branch to point to the final commit with the equivalent
+   of `git switch -C <branch>`.
 
 [NOTE]
-`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
-at the end of the rebase if other commands that write that pseudo-ref
-(e.g. `git reset`) are used during the rebase. The previous branch tip,
-however, is accessible using the reflog of the current branch
-(i.e. `@{1}`, see linkgit:gitrevisions[7]).
-
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
-If the upstream branch already contains a change you have made (e.g.,
-because you mailed a patch which was applied upstream), then that commit
-will be skipped and warnings will be issued (if the 'merge' backend is
-used).  For example, running `git rebase master` on the following
-history (in which `A'` and `A` introduce the same set of changes, but
-have different committer information):
-
-------------
-          A---B---C topic
-         /
-    D---E---A'---F master
-------------
-
-will result in:
-
-------------
-                   B'---C' topic
-                  /
-    D---E---A'---F master
-------------
+When starting the rebase, `ORIG_HEAD` is set to point to the commit at the tip
+of the to-be-rebased branch. However, `ORIG_HEAD` is not guaranteed to still
+point to that commit at the end of the rebase if other commands that change
+`ORIG_HEAD` (like `git reset`) are used during the rebase. The previous branch
+tip, however, is accessible using the reflog of the current branch (i.e. `@{1}`,
+see linkgit:gitrevisions[7].
 
 MODE OPTIONS
 ------------
-- 
gitgitgadget
Junio C Hamano· Aug 11, 2025, 21:14 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v5 5/5] doc: git-rebase: update discussion of internals

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 37 quoted lines
> From: Julia Evans <julia@jvns.ca>
>
> - make it clearer that we're talking about a multistep process
> - give a more technically accurate description how rebase works with the
>   merge backend.
> - condense the explanation of how git rebase skips commits with the same
>   textual changes into a single bullet point and remove the explanatory
>   diagram. Lots of things which are more complicated are already being
>   explained without a diagram.
> - remove the explanation of how exactly `--fork-point` and `--root`
>   work since that information is in the OPTIONS section
> - put all discussion of `ORIG_HEAD` inside the note
>
> Signed-off-by: Julia Evans <julia@jvns.ca>
> ---
>  Documentation/git-rebase.adoc | 66 ++++++++++++-----------------------
>  1 file changed, 23 insertions(+), 43 deletions(-)
>
> diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
> index 750f5e67e4c3..b4e5519d2839 100644
> --- a/Documentation/git-rebase.adoc
> +++ b/Documentation/git-rebase.adoc
> @@ -68,51 +68,31 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
>  assumed.  If you are currently not on any branch or if the current
>  branch does not have a configured upstream, the rebase will abort.
>  
> -All changes made by commits in the current branch but that are not
> -in `<upstream>` are saved to a temporary area.  This is the same set
> -of commits that would be shown by `git log <upstream>..HEAD`; or by
> -`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
> -description on `--fork-point` below); or by `git log HEAD`, if the
> -`--root` option is specified.
> -
> -The current branch is reset to `<upstream>` or `<newbase>` if the
> -`--onto` option was supplied.  This has the exact same effect as
> -`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
> -to point at the tip of the branch before the reset.
> +Here is a more detailed description of what `git rebase <upstream>` does:

Were there a sketchy description given elsewhere already? I personally feel that giving too much details here would not necessarily help readers' understanding. I'd prefer to see an introduction read more like "The command conceptually does these things in the following order", and leave the level of description also to match that introduction. It may be just me, but when somebody says "here is a detailed description", I would expect it to contain little or no white lies mixed in, even for simplicity.

But of course others may have different opinions ;-)
> +1. Make a list of all commits in the current branch that are not in
> +   `<upstream>`. This is the same set of commits that would be shown by `git log
> +   <upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
> +   list of commits is constructed.

Didn't somebody mention "git log --cherry-pick <upstream>..HEAD"? If omission of it is for simplicity, that is fine, but that is another reason why we do not want to say "more detaild description".

Also, shouldn't there be step #0 that says "If the <branch> to rebase is given, check out that branch and make it current", for the HEAD in this description to work correctly?

> +2. Check whether any of those commits are duplicates of commits already
> +   in `<upstream>`, remove them from the list, and print out a warning about
> +   each removed commit. You can use `--reapply-cherry-picks` to include
> +   duplicate commits.

This is done as part of #1 above as part of a single invocation of revision walk (i.e. a loop in sequencer.c:sequencer_make_script() that calls get_revision() repeatedly).

Show 7 quoted lines
> +3. Check out `<upstream>` (or `<newbase>` if the `--onto` option was
> +   supplied) with the equivalent of `git checkout --detach <upstream>`.
> +4. Replay the commits, one by one, in order. This is similar to running
> +   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
> +   are handled.
> +5. Update your branch to point to the final commit with the equivalent
> +   of `git switch -C <branch>`.

In step #3, you switched to <upstream> with "git checkout"; here you use "git switch". Uninitiated readers would wonder what criteria were used to decide which one among these two different commands to use in steps #3 and #5, even though either would work fine. Because this page is not where readers come to learn about the equivalence of these two commands that are not essential to learning "git rebase", it is better, so once you started with "git checkout", to stick to it throughout to reduce the mental burden to first-time learners.

Thanks.
Julia Evans via GitGitGadget· Aug 11, 2025, 21:51 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

 * move "You can also use git rebase to reorder or combine commits:" to the
   beginning
 * replace "detailed description" with "simplified description" -- I thought
   that I could write something that was relatively readable and also
   accurate, but as usual Git has proven me wrong :). I tried to leave in
   the details that I think seem relevant to using git: for example git
   checkout --detach is relevant because it explains why git reflog works
   well after a rebase.
 * replace the git switch with git checkout that I'd missed previously

I didn't use the git log --cherry-pick option in the explanation because I had personally never heard of that option before today, and I don't want people to have to read the git log man page to be able to understand the explanation. I also left out --reapply-cherry-picks just because I don't understand the use case so I couldn't evaluate how likely it is to be relevant to the person reading.

Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 302 +++++++++++++++-------------------
 1 file changed, 136 insertions(+), 166 deletions(-)
base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v6
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v6
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
Range-diff vs v5:
 1:  c2f2e05078f ! 1:  e7a8fbbe53c doc: git-rebase: start with an example
     @@ Documentation/git-rebase.adoc: SYNOPSIS
       DESCRIPTION
       -----------
      +Transplant a series of commits onto a different starting point.
     ++You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
     ++MODE below for how to do that.
      +
      +For example, imagine that you have been working on the `topic` branch in this
      +history, and you want to "catch up" to the work done on the `master` branch.
     @@ Documentation/git-rebase.adoc: SYNOPSIS
      +    D---E---F---G master
      +------------
      +
     -+You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
     -+MODE below for how to do that.
      +
       If `<branch>` is specified, `git rebase` will perform an automatic
       `git switch <branch>` before doing anything else.  Otherwise
 2:  5459b7ff560 ! 2:  ad63f69918d doc: git rebase: dedup merge conflict discussion
     @@ Commit message
      
       ## Documentation/git-rebase.adoc ##
      @@ Documentation/git-rebase.adoc: shortcut for `git checkout topic && git rebase master`.
     - You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
     - MODE below for how to do that.
     + ------------
     + 
       
      +If there is a merge conflict during this process, `git rebase` will stop at the
      +first problematic commit and leave conflict markers. If this happens, you can do
 3:  948c205f1e6 = 3:  7ee6b0afe88 doc: git rebase: clarify arguments syntax
 4:  e229b9fccb2 = 4:  4686417b28e doc: git-rebase: move --onto explanation down
 5:  5ab235b067b ! 5:  9c7f2716bc8 doc: git-rebase: update discussion of internals
     @@ Documentation/git-rebase.adoc: linkgit:git-config[1] for details) and the `--for
      -`--onto` option was supplied.  This has the exact same effect as
      -`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
      -to point at the tip of the branch before the reset.
     -+Here is a more detailed description of what `git rebase <upstream>` does:
     ++Here is a simplified description of what `git rebase <upstream>` does:
      +
     -+1. Make a list of all commits in the current branch that are not in
     -+   `<upstream>`. This is the same set of commits that would be shown by `git log
     -+   <upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
     -+   list of commits is constructed.
     ++1. Make a list of all new commits on your current branch since it branched
     ++   off from `<upstream>`. This is the same set of commits that would be shown
     ++   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
     ++   change how this list of commits is constructed.
      +2. Check whether any of those commits are duplicates of commits already
     -+   in `<upstream>`, remove them from the list, and print out a warning about
     -+   each removed commit. You can use `--reapply-cherry-picks` to include
     -+   duplicate commits.
     -+3. Check out `<upstream>` (or `<newbase>` if the `--onto` option was
     -+   supplied) with the equivalent of `git checkout --detach <upstream>`.
     ++   in `<upstream>` and remove them from the list.
     ++3. Check out `<upstream>` with the equivalent of `git checkout --detach <upstream>`.
      +4. Replay the commits, one by one, in order. This is similar to running
      +   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
      +   are handled.
      +5. Update your branch to point to the final commit with the equivalent
     -+   of `git switch -C <branch>`.
     ++   of `git checkout -C <branch>`.
       
       [NOTE]
      -`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 21:51 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v6 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>
- Start with an example that mirrors the example in the `git-merge` man
  page, to make it easier for folks to understand the difference between
  a rebase and a merge.
- Mention that rebase can combine or reorder commits
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +26 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..bb5a3ff7f828 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,32 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
+MODE below for how to do that.
+
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+shortcut for `git checkout topic && git rebase master`.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +84,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 21:51 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v6 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +20 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index bb5a3ff7f828..e82ceb9cbfce 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -42,6 +42,26 @@ shortcut for `git checkout topic && git rebase master`.
 ------------
 
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -77,13 +97,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -186,28 +199,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 21:51 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v6 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

Remove duplicate explanation of `git rebase <upstream> <branch>` which is already explained above.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Show changes to Documentation/git-rebase.adoc +1 −5
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index e82ceb9cbfce..6d02648a9b3c 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -62,11 +62,7 @@ one of these things:
 
    git rebase --skip
 
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 21:51 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v6 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Show changes to Documentation/git-rebase.adoc +87 −69
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 6d02648a9b3c..d041d87f270b 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -114,87 +114,6 @@ will result in:
     D---E---A'---F master
 ------------
 
-Here is how you would transplant a topic branch based on one
-branch to another, to pretend that you forked the topic branch
-from the latter branch, using `rebase --onto`.
-
-First let's assume your 'topic' is based on branch 'next'.
-For example, a feature developed in 'topic' depends on some
-functionality which is found in 'next'.
-
-------------
-    o---o---o---o---o  master
-         \
-          o---o---o---o---o  next
-                           \
-                            o---o---o  topic
-------------
-
-We want to make 'topic' forked from branch 'master'; for example,
-because the functionality on which 'topic' depends was merged into the
-more stable 'master' branch. We want our tree to look like this:
-
-------------
-    o---o---o---o---o  master
-        |            \
-        |             o'--o'--o'  topic
-         \
-          o---o---o---o---o  next
-------------
-
-We can get this using the following command:
-
-    git rebase --onto master next topic
-
-
-Another example of --onto option is to rebase part of a
-branch.  If we have the following situation:
-
-------------
-                            H---I---J topicB
-                           /
-                  E---F---G  topicA
-                 /
-    A---B---C---D  master
-------------
-
-then the command
-
-    git rebase --onto master topicA topicB
-
-would result in:
-
-------------
-                 H'--I'--J'  topicB
-                /
-                | E---F---G  topicA
-                |/
-    A---B---C---D  master
-------------
-
-This is useful when topicB does not depend on topicA.
-
-A range of commits could also be removed with rebase.  If we have
-the following situation:
-
-------------
-    E---F---G---H---I---J  topicA
-------------
-
-then the command
-
-    git rebase --onto topicA~5 topicA~3 topicA
-
-would result in the removal of commits F and G:
-
-------------
-    E---H'---I'---J'  topicA
-------------
-
-This is useful if F and G were flawed in some way, or should not be
-part of topicA.  Note that the argument to `--onto` and the `<upstream>`
-parameter can be any valid commit-ish.
-
 MODE OPTIONS
 ------------
 
@@ -240,6 +159,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -1018,6 +939,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
+Here is how you would transplant a topic branch based on one
+branch to another, to pretend that you forked the topic branch
+from the latter branch, using `rebase --onto`.
+
+First let's assume your 'topic' is based on branch 'next'.
+For example, a feature developed in 'topic' depends on some
+functionality which is found in 'next'.
+
+------------
+    o---o---o---o---o  master
+         \
+          o---o---o---o---o  next
+                           \
+                            o---o---o  topic
+------------
+
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
+
+------------
+    o---o---o---o---o  master
+        |            \
+        |             o'--o'--o'  topic
+         \
+          o---o---o---o---o  next
+------------
+
+We can get this using the following command:
+
+    git rebase --onto master next topic
+
+
+Another example of --onto option is to rebase part of a
+branch.  If we have the following situation:
+
+------------
+                            H---I---J topicB
+                           /
+                  E---F---G  topicA
+                 /
+    A---B---C---D  master
+------------
+
+then the command
+
+    git rebase --onto master topicA topicB
+
+would result in:
+
+------------
+                 H'--I'--J'  topicB
+                /
+                | E---F---G  topicA
+                |/
+    A---B---C---D  master
+------------
+
+This is useful when topicB does not depend on topicA.
+
+A range of commits could also be removed with rebase.  If we have
+the following situation:
+
+------------
+    E---F---G---H---I---J  topicA
+------------
+
+then the command
+
+    git rebase --onto topicA~5 topicA~3 topicA
+
+would result in the removal of commits F and G:
+
+------------
+    E---H'---I'---J'  topicA
+------------
+
+This is useful if F and G were flawed in some way, or should not be
+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
+parameter can be any valid commit-ish.
+
+
 RECOVERING FROM UPSTREAM REBASE
 -------------------------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 11, 2025, 21:51 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v6 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about a multistep process
- give a more technically accurate description how rebase works with the
  merge backend.
- condense the explanation of how git rebase skips commits with the same
  textual changes into a single bullet point and remove the explanatory
  diagram. Lots of things which are more complicated are already being
  explained without a diagram.
- remove the explanation of how exactly `--fork-point` and `--root`
  work since that information is in the OPTIONS section
- put all discussion of `ORIG_HEAD` inside the note
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 63 +++++++++++------------------------
 1 file changed, 20 insertions(+), 43 deletions(-)
Show changes to Documentation/git-rebase.adoc +20 −39
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index d041d87f270b..d4fc80ebb20c 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -68,51 +68,28 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
-in `<upstream>` are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`; or by
-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
-description on `--fork-point` below); or by `git log HEAD`, if the
-`--root` option is specified.
-
-The current branch is reset to `<upstream>` or `<newbase>` if the
-`--onto` option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
-to point at the tip of the branch before the reset.
+Here is a simplified description of what `git rebase <upstream>` does:
+
+1. Make a list of all new commits on your current branch since it branched
+   off from `<upstream>`. This is the same set of commits that would be shown
+   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
+   change how this list of commits is constructed.
+2. Check whether any of those commits are duplicates of commits already
+   in `<upstream>` and remove them from the list.
+3. Check out `<upstream>` with the equivalent of `git checkout --detach <upstream>`.
+4. Replay the commits, one by one, in order. This is similar to running
+   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
+   are handled.
+5. Update your branch to point to the final commit with the equivalent
+   of `git checkout -C <branch>`.
 
 [NOTE]
-`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
-at the end of the rebase if other commands that write that pseudo-ref
-(e.g. `git reset`) are used during the rebase. The previous branch tip,
-however, is accessible using the reflog of the current branch
-(i.e. `@{1}`, see linkgit:gitrevisions[7]).
-
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
-If the upstream branch already contains a change you have made (e.g.,
-because you mailed a patch which was applied upstream), then that commit
-will be skipped and warnings will be issued (if the 'merge' backend is
-used).  For example, running `git rebase master` on the following
-history (in which `A'` and `A` introduce the same set of changes, but
-have different committer information):
-
-------------
-          A---B---C topic
-         /
-    D---E---A'---F master
-------------
-
-will result in:
-
-------------
-                   B'---C' topic
-                  /
-    D---E---A'---F master
-------------
+When starting the rebase, `ORIG_HEAD` is set to point to the commit at the tip
+of the to-be-rebased branch. However, `ORIG_HEAD` is not guaranteed to still
+point to that commit at the end of the rebase if other commands that change
+`ORIG_HEAD` (like `git reset`) are used during the rebase. The previous branch
+tip, however, is accessible using the reflog of the current branch (i.e. `@{1}`,
+see linkgit:gitrevisions[7].
 
 MODE OPTIONS
 ------------
-- 
gitgitgadget
Junio C Hamano· Aug 11, 2025, 22:10 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v6 5/5] doc: git-rebase: update discussion of internals

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
> +Here is a simplified description of what `git rebase <upstream>` does:

Now this is a "this is roughly how it works", we can afford to give a simplified picture that may not exactly match the implementation, which is great freedom to have while writing documentation for first time users.

Show 6 quoted lines
> +1. Make a list of all new commits on your current branch since it branched
> +   off from `<upstream>`. This is the same set of commits that would be shown
> +   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
> +   change how this list of commits is constructed.
> +2. Check whether any of those commits are duplicates of commits already
> +   in `<upstream>` and remove them from the list.

So, I do not mind #2 described as a separate step. Conceptually, it is between "create a list of all commits in the range and filter out what have already been applied" and "create a list of all commits that are not in the upstream yet". We may be able to rephrase "all new commits on your current branch" somewhat to make it unnecessary to describe #2, though. If we are willing to stop talking about "This is the same set of ...", then the description becomes very simple:

    Make a list of all commits on your current branch since it
    branched off from `<upstream>` that do not have equivalent
    change in `<upstream>`.
> +3. Check out `<upstream>` with the equivalent of `git checkout --detach <upstream>`.

The line is getting overly long here and a few lines below. If your editor has the feature, tell it to auto-wrap at around 66-72 column.

Show 5 quoted lines
> +4. Replay the commits, one by one, in order. This is similar to running
> +   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
> +   are handled.
> +5. Update your branch to point to the final commit with the equivalent
> +   of `git checkout -C <branch>`.

Force-create-branch while checking out is `git checkout -B <branch>`, not -C.

Julia Evans· Aug 11, 2025, 22:42 UTC · re: Junio C Hamano · lore

Re: [PATCH v6 5/5] doc: git-rebase: update discussion of internals

Show 8 quoted lines
> So, I do not mind #2 described as a separate step.  Conceptually, it
> is between "create a list of all commits in the range and filter out
> what have already been applied" and "create a list of all commits
> that are not in the upstream yet".  We may be able to rephrase "all
> new commits on your current branch" somewhat to make it unnecessary
> to describe #2, though.  If we are willing to stop talking about
> "This is the same set of ...", then the description becomes very
> simple:

To me it feels relevant that `git rebase` is using two separate mechanisms to compare commits: the sha and (I think?) what `git patch-id` does. As a user it feels like an important distinction because normally when I look at my git commits I only use the sha (via something like `git log --graph`) to see what the new commits on a branch are.

Maybe the second part can be rephrased like this to emphasize that it's using a different mechanism than the SHA:

> 2. Check whether any of those commits contain the same changes (according to
   `git patch-id`) as a commit already in `<upstream>` and remove them from
   the list.
> The line is getting overly long here and a few lines below.  If your
> editor has the feature, tell it to auto-wrap at around 66-72 column.
Will fix, and I'll add a pre-commit hook to check for that.
> Force-create-branch while checking out is `git checkout -B
> <branch>`, not -C.
Will fix.
Junio C Hamano· Aug 11, 2025, 21:59 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 16 quoted lines
>  * move "You can also use git rebase to reorder or combine commits:" to the
>    beginning
>  * replace "detailed description" with "simplified description" -- I thought
>    that I could write something that was relatively readable and also
>    accurate, but as usual Git has proven me wrong :). I tried to leave in
>    the details that I think seem relevant to using git: for example git
>    checkout --detach is relevant because it explains why git reflog works
>    well after a rebase.
>  * replace the git switch with git checkout that I'd missed previously
>
> I didn't use the git log --cherry-pick option in the explanation because I
> had personally never heard of that option before today, and I don't want
> people to have to read the git log man page to be able to understand the
> explanation. I also left out --reapply-cherry-picks just because I don't
> understand the use case so I couldn't evaluate how likely it is to be
> relevant to the person reading.

I agree with the above decision to leave unnecessary implementation details out, and I also agree with the decision to talk about rebasing done on the detached HEAD. I will find out if I agree with the remainder of details that are kept (and left out) later by reading the patches ;-)

Thanks.
Julia Evans via GitGitGadget· Aug 12, 2025, 13:49 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v7 0/5] doc: git-rebase: clarify DESCRIPTION section

 * Rephrase "duplicates of commits" to clarify that in step 2, rebase is
   using git patch-id (or the equivalent) to compare commits instead of
   using the SHA.
 * wrap some text correctly
 * s/git checkout -C/git checkout -B/
Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 304 +++++++++++++++-------------------
 1 file changed, 138 insertions(+), 166 deletions(-)
base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v7
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v7
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
Range-diff vs v6:
 1:  e7a8fbbe53c = 1:  e7a8fbbe53c doc: git-rebase: start with an example
 2:  ad63f69918d = 2:  ad63f69918d doc: git rebase: dedup merge conflict discussion
 3:  7ee6b0afe88 = 3:  7ee6b0afe88 doc: git rebase: clarify arguments syntax
 4:  4686417b28e = 4:  4686417b28e doc: git-rebase: move --onto explanation down
 5:  9c7f2716bc8 ! 5:  79f29ad1e68 doc: git-rebase: update discussion of internals
     @@ Documentation/git-rebase.adoc: linkgit:git-config[1] for details) and the `--for
      +   off from `<upstream>`. This is the same set of commits that would be shown
      +   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
      +   change how this list of commits is constructed.
     -+2. Check whether any of those commits are duplicates of commits already
     -+   in `<upstream>` and remove them from the list.
     -+3. Check out `<upstream>` with the equivalent of `git checkout --detach <upstream>`.
     ++2. Check whether any of those commits contain the same changes (according to
     ++   `git patch-id`) as a commit already in `<upstream>` and remove them from
     ++   the list.
     ++3. Check out `<upstream>` with the equivalent of
     ++   `git checkout --detach <upstream>`.
      +4. Replay the commits, one by one, in order. This is similar to running
      +   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
      +   are handled.
      +5. Update your branch to point to the final commit with the equivalent
     -+   of `git checkout -C <branch>`.
     ++   of `git checkout -B <branch>`.
       
       [NOTE]
      -`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 12, 2025, 13:49 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v7 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>
- Start with an example that mirrors the example in the `git-merge` man
  page, to make it easier for folks to understand the difference between
  a rebase and a merge.
- Mention that rebase can combine or reorder commits
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +26 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..bb5a3ff7f828 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,32 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
+MODE below for how to do that.
+
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+shortcut for `git checkout topic && git rebase master`.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +84,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 12, 2025, 13:49 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v7 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +20 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index bb5a3ff7f828..e82ceb9cbfce 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -42,6 +42,26 @@ shortcut for `git checkout topic && git rebase master`.
 ------------
 
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -77,13 +97,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -186,28 +199,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 12, 2025, 13:49 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v7 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

Remove duplicate explanation of `git rebase <upstream> <branch>` which is already explained above.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Show changes to Documentation/git-rebase.adoc +1 −5
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index e82ceb9cbfce..6d02648a9b3c 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -62,11 +62,7 @@ one of these things:
 
    git rebase --skip
 
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 12, 2025, 13:49 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v7 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Show changes to Documentation/git-rebase.adoc +87 −69
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 6d02648a9b3c..d041d87f270b 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -114,87 +114,6 @@ will result in:
     D---E---A'---F master
 ------------
 
-Here is how you would transplant a topic branch based on one
-branch to another, to pretend that you forked the topic branch
-from the latter branch, using `rebase --onto`.
-
-First let's assume your 'topic' is based on branch 'next'.
-For example, a feature developed in 'topic' depends on some
-functionality which is found in 'next'.
-
-------------
-    o---o---o---o---o  master
-         \
-          o---o---o---o---o  next
-                           \
-                            o---o---o  topic
-------------
-
-We want to make 'topic' forked from branch 'master'; for example,
-because the functionality on which 'topic' depends was merged into the
-more stable 'master' branch. We want our tree to look like this:
-
-------------
-    o---o---o---o---o  master
-        |            \
-        |             o'--o'--o'  topic
-         \
-          o---o---o---o---o  next
-------------
-
-We can get this using the following command:
-
-    git rebase --onto master next topic
-
-
-Another example of --onto option is to rebase part of a
-branch.  If we have the following situation:
-
-------------
-                            H---I---J topicB
-                           /
-                  E---F---G  topicA
-                 /
-    A---B---C---D  master
-------------
-
-then the command
-
-    git rebase --onto master topicA topicB
-
-would result in:
-
-------------
-                 H'--I'--J'  topicB
-                /
-                | E---F---G  topicA
-                |/
-    A---B---C---D  master
-------------
-
-This is useful when topicB does not depend on topicA.
-
-A range of commits could also be removed with rebase.  If we have
-the following situation:
-
-------------
-    E---F---G---H---I---J  topicA
-------------
-
-then the command
-
-    git rebase --onto topicA~5 topicA~3 topicA
-
-would result in the removal of commits F and G:
-
-------------
-    E---H'---I'---J'  topicA
-------------
-
-This is useful if F and G were flawed in some way, or should not be
-part of topicA.  Note that the argument to `--onto` and the `<upstream>`
-parameter can be any valid commit-ish.
-
 MODE OPTIONS
 ------------
 
@@ -240,6 +159,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -1018,6 +939,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
+Here is how you would transplant a topic branch based on one
+branch to another, to pretend that you forked the topic branch
+from the latter branch, using `rebase --onto`.
+
+First let's assume your 'topic' is based on branch 'next'.
+For example, a feature developed in 'topic' depends on some
+functionality which is found in 'next'.
+
+------------
+    o---o---o---o---o  master
+         \
+          o---o---o---o---o  next
+                           \
+                            o---o---o  topic
+------------
+
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
+
+------------
+    o---o---o---o---o  master
+        |            \
+        |             o'--o'--o'  topic
+         \
+          o---o---o---o---o  next
+------------
+
+We can get this using the following command:
+
+    git rebase --onto master next topic
+
+
+Another example of --onto option is to rebase part of a
+branch.  If we have the following situation:
+
+------------
+                            H---I---J topicB
+                           /
+                  E---F---G  topicA
+                 /
+    A---B---C---D  master
+------------
+
+then the command
+
+    git rebase --onto master topicA topicB
+
+would result in:
+
+------------
+                 H'--I'--J'  topicB
+                /
+                | E---F---G  topicA
+                |/
+    A---B---C---D  master
+------------
+
+This is useful when topicB does not depend on topicA.
+
+A range of commits could also be removed with rebase.  If we have
+the following situation:
+
+------------
+    E---F---G---H---I---J  topicA
+------------
+
+then the command
+
+    git rebase --onto topicA~5 topicA~3 topicA
+
+would result in the removal of commits F and G:
+
+------------
+    E---H'---I'---J'  topicA
+------------
+
+This is useful if F and G were flawed in some way, or should not be
+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
+parameter can be any valid commit-ish.
+
+
 RECOVERING FROM UPSTREAM REBASE
 -------------------------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 12, 2025, 13:49 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v7 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about a multistep process
- give a more technically accurate description how rebase works with the
  merge backend.
- condense the explanation of how git rebase skips commits with the same
  textual changes into a single bullet point and remove the explanatory
  diagram. Lots of things which are more complicated are already being
  explained without a diagram.
- remove the explanation of how exactly `--fork-point` and `--root`
  work since that information is in the OPTIONS section
- put all discussion of `ORIG_HEAD` inside the note
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 65 ++++++++++++-----------------------
 1 file changed, 22 insertions(+), 43 deletions(-)
Show changes to Documentation/git-rebase.adoc +22 −39
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index d041d87f270b..cce2577a8ade 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -68,51 +68,30 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
-in `<upstream>` are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`; or by
-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
-description on `--fork-point` below); or by `git log HEAD`, if the
-`--root` option is specified.
-
-The current branch is reset to `<upstream>` or `<newbase>` if the
-`--onto` option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
-to point at the tip of the branch before the reset.
+Here is a simplified description of what `git rebase <upstream>` does:
+
+1. Make a list of all new commits on your current branch since it branched
+   off from `<upstream>`. This is the same set of commits that would be shown
+   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
+   change how this list of commits is constructed.
+2. Check whether any of those commits contain the same changes (according to
+   `git patch-id`) as a commit already in `<upstream>` and remove them from
+   the list.
+3. Check out `<upstream>` with the equivalent of
+   `git checkout --detach <upstream>`.
+4. Replay the commits, one by one, in order. This is similar to running
+   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
+   are handled.
+5. Update your branch to point to the final commit with the equivalent
+   of `git checkout -B <branch>`.
 
 [NOTE]
-`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
-at the end of the rebase if other commands that write that pseudo-ref
-(e.g. `git reset`) are used during the rebase. The previous branch tip,
-however, is accessible using the reflog of the current branch
-(i.e. `@{1}`, see linkgit:gitrevisions[7]).
-
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
-If the upstream branch already contains a change you have made (e.g.,
-because you mailed a patch which was applied upstream), then that commit
-will be skipped and warnings will be issued (if the 'merge' backend is
-used).  For example, running `git rebase master` on the following
-history (in which `A'` and `A` introduce the same set of changes, but
-have different committer information):
-
-------------
-          A---B---C topic
-         /
-    D---E---A'---F master
-------------
-
-will result in:
-
-------------
-                   B'---C' topic
-                  /
-    D---E---A'---F master
-------------
+When starting the rebase, `ORIG_HEAD` is set to point to the commit at the tip
+of the to-be-rebased branch. However, `ORIG_HEAD` is not guaranteed to still
+point to that commit at the end of the rebase if other commands that change
+`ORIG_HEAD` (like `git reset`) are used during the rebase. The previous branch
+tip, however, is accessible using the reflog of the current branch (i.e. `@{1}`,
+see linkgit:gitrevisions[7].
 
 MODE OPTIONS
 ------------
-- 
gitgitgadget
Junio C Hamano· Aug 14, 2025, 21:28 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v7 5/5] doc: git-rebase: update discussion of internals

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 9 quoted lines
> +Here is a simplified description of what `git rebase <upstream>` does:
> +
> +1. Make a list of all new commits on your current branch since it branched
> +   off from `<upstream>`. This is the same set of commits that would be shown
> +   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
> +   change how this list of commits is constructed.
> +2. Check whether any of those commits contain the same changes (according to
> +   `git patch-id`) as a commit already in `<upstream>` and remove them from
> +   the list.
I'd suggest three things
 * Rewrite the introductory text to
    Here is what "git rebase <upstream> [<branch>]" conceptually does:
 * Add step 0. to make "your current branch" in the next step valid.
    0. When <branch> is given, check it out and make it your current
    branch.
 * Combine the steps 1 & 2. and stop talking about "git log" whose
   invocation cannot be precisely described here anyway.

Other than that, the remainder of the series (v7 [1-4/5]) looked good.

THanks.
Julia Evans via GitGitGadget· Aug 15, 2025, 16:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v8 0/5] doc: git-rebase: clarify DESCRIPTION section

Combine point 1 and 2 in "a simplified description of what git rebase <upstream> does:" into a shorter summary.

Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 298 +++++++++++++++-------------------
 1 file changed, 133 insertions(+), 165 deletions(-)
base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v8
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v8
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
Range-diff vs v7:
 1:  e7a8fbbe53c = 1:  e7a8fbbe53c doc: git-rebase: start with an example
 2:  ad63f69918d = 2:  ad63f69918d doc: git rebase: dedup merge conflict discussion
 3:  7ee6b0afe88 = 3:  7ee6b0afe88 doc: git rebase: clarify arguments syntax
 4:  4686417b28e = 4:  4686417b28e doc: git-rebase: move --onto explanation down
 5:  79f29ad1e68 ! 5:  cb85642bb9d doc: git-rebase: update discussion of internals
     @@ Documentation/git-rebase.adoc: linkgit:git-config[1] for details) and the `--for
      -to point at the tip of the branch before the reset.
      +Here is a simplified description of what `git rebase <upstream>` does:
      +
     -+1. Make a list of all new commits on your current branch since it branched
     -+   off from `<upstream>`. This is the same set of commits that would be shown
     -+   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
     -+   change how this list of commits is constructed.
     -+2. Check whether any of those commits contain the same changes (according to
     -+   `git patch-id`) as a commit already in `<upstream>` and remove them from
     -+   the list.
     -+3. Check out `<upstream>` with the equivalent of
     ++1. Make a list of all commits on your current branch since it branched
     ++   off from `<upstream>` that do not have an equivalent commit in
     ++   `<upstream>`.
     ++2. Check out `<upstream>` with the equivalent of
      +   `git checkout --detach <upstream>`.
     -+4. Replay the commits, one by one, in order. This is similar to running
     ++3. Replay the commits, one by one, in order. This is similar to running
      +   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
      +   are handled.
     -+5. Update your branch to point to the final commit with the equivalent
     ++4. Update your branch to point to the final commit with the equivalent
      +   of `git checkout -B <branch>`.
       
       [NOTE]
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 15, 2025, 16:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v8 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>
- Start with an example that mirrors the example in the `git-merge` man
  page, to make it easier for folks to understand the difference between
  a rebase and a merge.
- Mention that rebase can combine or reorder commits
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +26 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..bb5a3ff7f828 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,32 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
+MODE below for how to do that.
+
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+shortcut for `git checkout topic && git rebase master`.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +84,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 15, 2025, 16:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v8 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +20 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index bb5a3ff7f828..e82ceb9cbfce 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -42,6 +42,26 @@ shortcut for `git checkout topic && git rebase master`.
 ------------
 
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -77,13 +97,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -186,28 +199,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 15, 2025, 16:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v8 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

Remove duplicate explanation of `git rebase <upstream> <branch>` which is already explained above.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Show changes to Documentation/git-rebase.adoc +1 −5
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index e82ceb9cbfce..6d02648a9b3c 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -62,11 +62,7 @@ one of these things:
 
    git rebase --skip
 
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 15, 2025, 16:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v8 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Show changes to Documentation/git-rebase.adoc +87 −69
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 6d02648a9b3c..d041d87f270b 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -114,87 +114,6 @@ will result in:
     D---E---A'---F master
 ------------
 
-Here is how you would transplant a topic branch based on one
-branch to another, to pretend that you forked the topic branch
-from the latter branch, using `rebase --onto`.
-
-First let's assume your 'topic' is based on branch 'next'.
-For example, a feature developed in 'topic' depends on some
-functionality which is found in 'next'.
-
-------------
-    o---o---o---o---o  master
-         \
-          o---o---o---o---o  next
-                           \
-                            o---o---o  topic
-------------
-
-We want to make 'topic' forked from branch 'master'; for example,
-because the functionality on which 'topic' depends was merged into the
-more stable 'master' branch. We want our tree to look like this:
-
-------------
-    o---o---o---o---o  master
-        |            \
-        |             o'--o'--o'  topic
-         \
-          o---o---o---o---o  next
-------------
-
-We can get this using the following command:
-
-    git rebase --onto master next topic
-
-
-Another example of --onto option is to rebase part of a
-branch.  If we have the following situation:
-
-------------
-                            H---I---J topicB
-                           /
-                  E---F---G  topicA
-                 /
-    A---B---C---D  master
-------------
-
-then the command
-
-    git rebase --onto master topicA topicB
-
-would result in:
-
-------------
-                 H'--I'--J'  topicB
-                /
-                | E---F---G  topicA
-                |/
-    A---B---C---D  master
-------------
-
-This is useful when topicB does not depend on topicA.
-
-A range of commits could also be removed with rebase.  If we have
-the following situation:
-
-------------
-    E---F---G---H---I---J  topicA
-------------
-
-then the command
-
-    git rebase --onto topicA~5 topicA~3 topicA
-
-would result in the removal of commits F and G:
-
-------------
-    E---H'---I'---J'  topicA
-------------
-
-This is useful if F and G were flawed in some way, or should not be
-part of topicA.  Note that the argument to `--onto` and the `<upstream>`
-parameter can be any valid commit-ish.
-
 MODE OPTIONS
 ------------
 
@@ -240,6 +159,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
@@ -1018,6 +939,91 @@ consistent (they compile, pass the testsuite, etc.) you should use
 after each commit, test, and amend the commit if fixes are necessary.
 
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
+Here is how you would transplant a topic branch based on one
+branch to another, to pretend that you forked the topic branch
+from the latter branch, using `rebase --onto`.
+
+First let's assume your 'topic' is based on branch 'next'.
+For example, a feature developed in 'topic' depends on some
+functionality which is found in 'next'.
+
+------------
+    o---o---o---o---o  master
+         \
+          o---o---o---o---o  next
+                           \
+                            o---o---o  topic
+------------
+
+We want to make 'topic' forked from branch 'master'; for example,
+because the functionality on which 'topic' depends was merged into the
+more stable 'master' branch. We want our tree to look like this:
+
+------------
+    o---o---o---o---o  master
+        |            \
+        |             o'--o'--o'  topic
+         \
+          o---o---o---o---o  next
+------------
+
+We can get this using the following command:
+
+    git rebase --onto master next topic
+
+
+Another example of --onto option is to rebase part of a
+branch.  If we have the following situation:
+
+------------
+                            H---I---J topicB
+                           /
+                  E---F---G  topicA
+                 /
+    A---B---C---D  master
+------------
+
+then the command
+
+    git rebase --onto master topicA topicB
+
+would result in:
+
+------------
+                 H'--I'--J'  topicB
+                /
+                | E---F---G  topicA
+                |/
+    A---B---C---D  master
+------------
+
+This is useful when topicB does not depend on topicA.
+
+A range of commits could also be removed with rebase.  If we have
+the following situation:
+
+------------
+    E---F---G---H---I---J  topicA
+------------
+
+then the command
+
+    git rebase --onto topicA~5 topicA~3 topicA
+
+would result in the removal of commits F and G:
+
+------------
+    E---H'---I'---J'  topicA
+------------
+
+This is useful if F and G were flawed in some way, or should not be
+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
+parameter can be any valid commit-ish.
+
+
 RECOVERING FROM UPSTREAM REBASE
 -------------------------------
 
-- 
gitgitgadget
Junio C Hamano· Aug 15, 2025, 21:05 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v8 4/5] doc: git-rebase: move --onto explanation down

"Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
Show 11 quoted lines
> From: Julia Evans <julia@jvns.ca>
>
> There's a very clear explanation with examples of using --onto which is
> currently buried in the very long DESCRIPTION section. This moves it to
> its own section, so that we can reference the explanation from the
> `--onto` option by name.
>
> Signed-off-by: Julia Evans <julia@jvns.ca>
> ---
>  Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
>  1 file changed, 87 insertions(+), 81 deletions(-)
Deduplicating is very good idea.

I gave a read-through over the result of the entire series, including the parts that did not change, to see if the new organization is easy to read and coherently tells the story we want to tell, and what I saw was mostly very pleasing, except for one thing.

The new location of this section on "--onto" felt a bit off. Perhaps it is just me, but in case others have different opinions, I'd raise it here.

The overall structure of the document with these patches becomes:
 - description that gives a simplified "what is achieved".
 - "mode options" that control what to do during a rebase once the
   user is given control back
 - "options" that is given upfront
 - notes about incompatible options
 - discussions about apply/merge backends and how they differ
 - overall notes on advanced topics
   - interactive mode basics
   - splitting commits
   - use of --onto
   - dealing with rebased upstream
   - rebasing merges

Is it so exotic to use "--onto" to replay a topic to somewhere other than the direct descendant of the fork point, to make it a part of advanced topics? I somehow doubt it. It is a very basic and common thing to do while correcting a mistake of choosing a wrong base commit. You often realize that your topic is basically good but has to work well with a different base commit.

I wonder if it gives the same understanding with a much shorter text and illustration if we get rid of that section, and mention --onto as a part of the early examples in the description section. That way, we can reuse the "set up" of user's brain and context we already made with the existing example.

For example, after showing the rebase of A..C on top of G, we can mention that the range can be transplanted on top of commit other than G, say D. Perhaps we can say that 'D' is still part of the maintenance track, and the topic being a fix for a bug that happened before D, it should not have forked from E that is a feature enhancement commit that is not eligible for being on the maintenance track. That would be a good reason why the user may want to move A..C on top of D instead of E.

Phillip Wood· Aug 18, 2025, 13:42 UTC · re: Junio C Hamano · lore

Re: [PATCH v8 4/5] doc: git-rebase: move --onto explanation down

On 15/08/2025 22:05, Junio C Hamano wrote:
Show 21 quoted lines
> "Julia Evans via GitGitGadget" <gitgitgadget@gmail.com> writes:
> 
>> From: Julia Evans <julia@jvns.ca>
>>
>> There's a very clear explanation with examples of using --onto which is
>> currently buried in the very long DESCRIPTION section. This moves it to
>> its own section, so that we can reference the explanation from the
>> `--onto` option by name.
>>
>> Signed-off-by: Julia Evans <julia@jvns.ca>
>> ---
>>   Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
>>   1 file changed, 87 insertions(+), 81 deletions(-)
> 
> Deduplicating is very good idea.
> 
> I gave a read-through over the result of the entire series,
> including the parts that did not change, to see if the new
> organization is easy to read and coherently tells the story
> we want to tell, and what I saw was mostly very pleasing, except for
> one thing.
Yes the reworked DESCRIPTION section is very good.
> The new location of this section on "--onto" felt a bit off.
> Perhaps it is just me, but in case others have different opinions,
> I'd raise it here.

I agree that "--onto" is a fairly commonly used option and so it might be nice to mention it in the general description. The existing examples are all good reasons why one might want to use "--onto" so I'm slightly wary of replacing them with a single example in the description. Maybe we could just add a sentence to the description explaining that it is possible to transplant the commits to a different base using "--onto". That would also keep the description fairly concise.

I've just built the html version and it would be nice if we could add a link to the TRANSPLANTING A TOPIC BRANCH WITH --ONTO when we mention it in the description of "--onto". The same goes for the mention of INTERACTIVE MODE in the DESCRIPTION section.

Thanks
Phillip
Show 46 quoted lines
> The overall structure of the document with these patches becomes:
> 
>   - description that gives a simplified "what is achieved".
> 
>   - "mode options" that control what to do during a rebase once the
>     user is given control back
> 
>   - "options" that is given upfront
> 
>   - notes about incompatible options
> 
>   - discussions about apply/merge backends and how they differ
> 
>   - overall notes on advanced topics
> 
>     - interactive mode basics
> 
>     - splitting commits
> 
>     - use of --onto
> 
>     - dealing with rebased upstream
> 
>     - rebasing merges
> 
> Is it so exotic to use "--onto" to replay a topic to somewhere other
> than the direct descendant of the fork point, to make it a part of
> advanced topics?  I somehow doubt it.  It is a very basic and common
> thing to do while correcting a mistake of choosing a wrong base
> commit.  You often realize that your topic is basically good but has
> to work well with a different base commit.
> 
> I wonder if it gives the same understanding with a much shorter text
> and illustration if we get rid of that section, and mention --onto
> as a part of the early examples in the description section.  That
> way, we can reuse the "set up" of user's brain and context we
> already made with the existing example.
> 
> For example, after showing the rebase of A..C on top of G, we can
> mention that the range can be transplanted on top of commit other
> than G, say D.  Perhaps we can say that 'D' is still part of the
> maintenance track, and the topic being a fix for a bug that happened
> before D, it should not have forked from E that is a feature
> enhancement commit that is not eligible for being on the maintenance
> track.  That would be a good reason why the user may want to move
> A..C on top of D instead of E.
Junio C Hamano· Aug 18, 2025, 17:06 UTC · re: Phillip Wood · lore

Re: [PATCH v8 4/5] doc: git-rebase: move --onto explanation down

Phillip Wood <phillip.wood123@gmail.com> writes:
Show 6 quoted lines
>> The new location of this section on "--onto" felt a bit off.
>> Perhaps it is just me, but in case others have different opinions,
>> I'd raise it here.
>
> I agree that "--onto" is a fairly commonly used option and so it might
> be nice to mention it in the general description.
That would independently be a good idea.
> The existing
> examples are all good reasons why one might want to use "--onto" so
> I'm slightly wary of replacing them with a single example in the
> description.

Then perhaps we should find a better place to put it. The section on advanced topics notes are mostly about operations using sequencer machinery, except for the onto section. Perhaps immediately after the apply/merge comparison?

Julia Evans· Aug 19, 2025, 15:03 UTC · re: Junio C Hamano · lore

Re: [PATCH v8 4/5] doc: git-rebase: move --onto explanation down

Show 9 quoted lines
>> The existing
>> examples are all good reasons why one might want to use "--onto" so
>> I'm slightly wary of replacing them with a single example in the
>> description.
>
> Then perhaps we should find a better place to put it.  The section
> on advanced topics notes are mostly about operations using sequencer
> machinery, except for the onto section.  Perhaps immediately after
> the apply/merge comparison?

I'm happy to move it anywhere: I couldn't figure out how the sections were meant to be organized (I didn't know that "operations about sequencer machinery" was meant to be a theme) so I chose where to put it pretty arbitrarily.

Junio C Hamano· Aug 19, 2025, 19:45 UTC · re: Julia Evans · lore

Re: [PATCH v8 4/5] doc: git-rebase: move --onto explanation down

"Julia Evans" <julia@jvns.ca> writes:
Show 14 quoted lines
>>> The existing
>>> examples are all good reasons why one might want to use "--onto" so
>>> I'm slightly wary of replacing them with a single example in the
>>> description.
>>
>> Then perhaps we should find a better place to put it.  The section
>> on advanced topics notes are mostly about operations using sequencer
>> machinery, except for the onto section.  Perhaps immediately after
>> the apply/merge comparison?
>
> I'm happy to move it anywhere: I couldn't figure out how the sections
> were meant to be organized (I didn't know that "operations about 
> sequencer machinery" was meant to be a theme) so I chose where
> to put it pretty arbitrarily.

I do not think it was meant to be a theme, but the topics there ended up being around it as they were placed there organically.

If we were moving it, how about somewhere fairly early, like before we start talking about mode options, where we teach the very basic concept "rebase is to transplant a range history on top of a commit that is different from where that history currently builds on"? The primary difference with and without "--onto" is if you explicitly specify where to transplant your history, independent from how you specify the range of history to be transplanted, or a single <upstream> implicitly specifies both.

Julia Evans via GitGitGadget· Aug 15, 2025, 16:52 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v8 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about a multistep process
- give a more technically accurate description how rebase works with the
  merge backend.
- condense the explanation of how git rebase skips commits with the same
  textual changes into a single bullet point and remove the explanatory
  diagram. Lots of things which are more complicated are already being
  explained without a diagram.
- remove the explanation of how exactly `--fork-point` and `--root`
  work since that information is in the OPTIONS section
- put all discussion of `ORIG_HEAD` inside the note
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 61 +++++++++++------------------------
 1 file changed, 18 insertions(+), 43 deletions(-)
Show changes to Documentation/git-rebase.adoc +18 −39
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index d041d87f270b..2a44f8a0ceda 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -68,51 +68,26 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
-in `<upstream>` are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`; or by
-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
-description on `--fork-point` below); or by `git log HEAD`, if the
-`--root` option is specified.
-
-The current branch is reset to `<upstream>` or `<newbase>` if the
-`--onto` option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
-to point at the tip of the branch before the reset.
+Here is a simplified description of what `git rebase <upstream>` does:
+
+1. Make a list of all commits on your current branch since it branched
+   off from `<upstream>` that do not have an equivalent commit in
+   `<upstream>`.
+2. Check out `<upstream>` with the equivalent of
+   `git checkout --detach <upstream>`.
+3. Replay the commits, one by one, in order. This is similar to running
+   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
+   are handled.
+4. Update your branch to point to the final commit with the equivalent
+   of `git checkout -B <branch>`.
 
 [NOTE]
-`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
-at the end of the rebase if other commands that write that pseudo-ref
-(e.g. `git reset`) are used during the rebase. The previous branch tip,
-however, is accessible using the reflog of the current branch
-(i.e. `@{1}`, see linkgit:gitrevisions[7]).
-
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
-If the upstream branch already contains a change you have made (e.g.,
-because you mailed a patch which was applied upstream), then that commit
-will be skipped and warnings will be issued (if the 'merge' backend is
-used).  For example, running `git rebase master` on the following
-history (in which `A'` and `A` introduce the same set of changes, but
-have different committer information):
-
-------------
-          A---B---C topic
-         /
-    D---E---A'---F master
-------------
-
-will result in:
-
-------------
-                   B'---C' topic
-                  /
-    D---E---A'---F master
-------------
+When starting the rebase, `ORIG_HEAD` is set to point to the commit at the tip
+of the to-be-rebased branch. However, `ORIG_HEAD` is not guaranteed to still
+point to that commit at the end of the rebase if other commands that change
+`ORIG_HEAD` (like `git reset`) are used during the rebase. The previous branch
+tip, however, is accessible using the reflog of the current branch (i.e. `@{1}`,
+see linkgit:gitrevisions[7].
 
 MODE OPTIONS
 ------------
-- 
gitgitgadget
Phillip Wood· Aug 18, 2025, 13:43 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v8 0/5] doc: git-rebase: clarify DESCRIPTION section

On 15/08/2025 17:52, Julia Evans via GitGitGadget wrote:
> Combine point 1 and 2 in "a simplified description of what git rebase
> <upstream> does:" into a shorter summary.

This looks great, I've left a couple of comments in reply to Junio but I'd be happy enough to see this merged as-is.

I'm going to be off the list for a week from tomorrow so I wont be commenting any more this week.

Thanks for working on this
Phillip
Show 50 quoted lines
> Julia Evans (5):
>    doc: git-rebase: start with an example
>    doc: git rebase: dedup merge conflict discussion
>    doc: git rebase: clarify arguments syntax
>    doc: git-rebase: move --onto explanation down
>    doc: git-rebase: update discussion of internals
> 
>   Documentation/git-rebase.adoc | 298 +++++++++++++++-------------------
>   1 file changed, 133 insertions(+), 165 deletions(-)
> 
> 
> base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v8
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v8
> Pull-Request: https://github.com/gitgitgadget/git/pull/1949
> 
> Range-diff vs v7:
> 
>   1:  e7a8fbbe53c = 1:  e7a8fbbe53c doc: git-rebase: start with an example
>   2:  ad63f69918d = 2:  ad63f69918d doc: git rebase: dedup merge conflict discussion
>   3:  7ee6b0afe88 = 3:  7ee6b0afe88 doc: git rebase: clarify arguments syntax
>   4:  4686417b28e = 4:  4686417b28e doc: git-rebase: move --onto explanation down
>   5:  79f29ad1e68 ! 5:  cb85642bb9d doc: git-rebase: update discussion of internals
>       @@ Documentation/git-rebase.adoc: linkgit:git-config[1] for details) and the `--for
>        -to point at the tip of the branch before the reset.
>        +Here is a simplified description of what `git rebase <upstream>` does:
>        +
>       -+1. Make a list of all new commits on your current branch since it branched
>       -+   off from `<upstream>`. This is the same set of commits that would be shown
>       -+   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
>       -+   change how this list of commits is constructed.
>       -+2. Check whether any of those commits contain the same changes (according to
>       -+   `git patch-id`) as a commit already in `<upstream>` and remove them from
>       -+   the list.
>       -+3. Check out `<upstream>` with the equivalent of
>       ++1. Make a list of all commits on your current branch since it branched
>       ++   off from `<upstream>` that do not have an equivalent commit in
>       ++   `<upstream>`.
>       ++2. Check out `<upstream>` with the equivalent of
>        +   `git checkout --detach <upstream>`.
>       -+4. Replay the commits, one by one, in order. This is similar to running
>       ++3. Replay the commits, one by one, in order. This is similar to running
>        +   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
>        +   are handled.
>       -+5. Update your branch to point to the final commit with the equivalent
>       ++4. Update your branch to point to the final commit with the equivalent
>        +   of `git checkout -B <branch>`.
>         
>         [NOTE]
> 
Julia Evans via GitGitGadget· Aug 23, 2025, 00:42 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v9 0/5] doc: git-rebase: clarify DESCRIPTION section

Move the "TRANSPLANTING A TOPIC BRANCH WITH --ONTO" back up: now it's in the exact same place it was before, just now with a section heading.

Julia Evans (5):
  doc: git-rebase: start with an example
  doc: git rebase: dedup merge conflict discussion
  doc: git rebase: clarify arguments syntax
  doc: git-rebase: move --onto explanation down
  doc: git-rebase: update discussion of internals
 Documentation/git-rebase.adoc | 149 +++++++++++++---------------------
 1 file changed, 58 insertions(+), 91 deletions(-)
base-commit: 64cbe5e2e8a7b0f92c780b210e602496bd5cad0f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v9
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v9
Pull-Request: https://github.com/gitgitgadget/git/pull/1949
Range-diff vs v8:
 1:  e7a8fbbe53c = 1:  ea1438e094e doc: git-rebase: start with an example
 2:  ad63f69918d = 2:  339b7a1bc5b doc: git rebase: dedup merge conflict discussion
 3:  7ee6b0afe88 = 3:  f42c2c794a9 doc: git rebase: clarify arguments syntax
 4:  4686417b28e ! 4:  9c2a54ab9fa doc: git-rebase: move --onto explanation down
     @@ Documentation/git-rebase.adoc: will result in:
           D---E---A'---F master
       ------------
       
     --Here is how you would transplant a topic branch based on one
     --branch to another, to pretend that you forked the topic branch
     --from the latter branch, using `rebase --onto`.
     --
     --First let's assume your 'topic' is based on branch 'next'.
     --For example, a feature developed in 'topic' depends on some
     --functionality which is found in 'next'.
     --
     --------------
     --    o---o---o---o---o  master
     --         \
     --          o---o---o---o---o  next
     --                           \
     --                            o---o---o  topic
     --------------
     --
     --We want to make 'topic' forked from branch 'master'; for example,
     --because the functionality on which 'topic' depends was merged into the
     --more stable 'master' branch. We want our tree to look like this:
     --
     --------------
     --    o---o---o---o---o  master
     --        |            \
     --        |             o'--o'--o'  topic
     --         \
     --          o---o---o---o---o  next
     --------------
     --
     --We can get this using the following command:
     --
     --    git rebase --onto master next topic
     --
     --
     --Another example of --onto option is to rebase part of a
     --branch.  If we have the following situation:
     --
     --------------
     --                            H---I---J topicB
     --                           /
     --                  E---F---G  topicA
     --                 /
     --    A---B---C---D  master
     --------------
     --
     --then the command
     --
     --    git rebase --onto master topicA topicB
     --
     --would result in:
     --
     --------------
     --                 H'--I'--J'  topicB
     --                /
     --                | E---F---G  topicA
     --                |/
     --    A---B---C---D  master
     --------------
     --
     --This is useful when topicB does not depend on topicA.
     --
     --A range of commits could also be removed with rebase.  If we have
     --the following situation:
     --
     --------------
     --    E---F---G---H---I---J  topicA
     --------------
     --
     --then the command
     --
     --    git rebase --onto topicA~5 topicA~3 topicA
     --
     --would result in the removal of commits F and G:
     --
     --------------
     --    E---H'---I'---J'  topicA
     --------------
     --
     --This is useful if F and G were flawed in some way, or should not be
     --part of topicA.  Note that the argument to `--onto` and the `<upstream>`
     --parameter can be any valid commit-ish.
     --
     - MODE OPTIONS
     - ------------
     - 
     ++TRANSPLANTING A TOPIC BRANCH WITH --ONTO
     ++----------------------------------------
     ++
     + Here is how you would transplant a topic branch based on one
     + branch to another, to pretend that you forked the topic branch
     + from the latter branch, using `rebase --onto`.
      @@ Documentation/git-rebase.adoc: As a special case, you may use "A\...B" as a shortcut for the
       merge base of A and B if there is exactly one merge base. You can
       leave out at most one of A and B, in which case it defaults to HEAD.
       
     -+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO below for examples.
     ++See TRANSPLANTING A TOPIC BRANCH WITH --ONTO above for examples.
      +
       --keep-base::
       	Set the starting point at which to create the new commits to the
       	merge base of `<upstream>` and `<branch>`. Running
     -@@ Documentation/git-rebase.adoc: consistent (they compile, pass the testsuite, etc.) you should use
     - after each commit, test, and amend the commit if fixes are necessary.
     - 
     - 
     -+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
     -+----------------------------------------
     -+
     -+Here is how you would transplant a topic branch based on one
     -+branch to another, to pretend that you forked the topic branch
     -+from the latter branch, using `rebase --onto`.
     -+
     -+First let's assume your 'topic' is based on branch 'next'.
     -+For example, a feature developed in 'topic' depends on some
     -+functionality which is found in 'next'.
     -+
     -+------------
     -+    o---o---o---o---o  master
     -+         \
     -+          o---o---o---o---o  next
     -+                           \
     -+                            o---o---o  topic
     -+------------
     -+
     -+We want to make 'topic' forked from branch 'master'; for example,
     -+because the functionality on which 'topic' depends was merged into the
     -+more stable 'master' branch. We want our tree to look like this:
     -+
     -+------------
     -+    o---o---o---o---o  master
     -+        |            \
     -+        |             o'--o'--o'  topic
     -+         \
     -+          o---o---o---o---o  next
     -+------------
     -+
     -+We can get this using the following command:
     -+
     -+    git rebase --onto master next topic
     -+
     -+
     -+Another example of --onto option is to rebase part of a
     -+branch.  If we have the following situation:
     -+
     -+------------
     -+                            H---I---J topicB
     -+                           /
     -+                  E---F---G  topicA
     -+                 /
     -+    A---B---C---D  master
     -+------------
     -+
     -+then the command
     -+
     -+    git rebase --onto master topicA topicB
     -+
     -+would result in:
     -+
     -+------------
     -+                 H'--I'--J'  topicB
     -+                /
     -+                | E---F---G  topicA
     -+                |/
     -+    A---B---C---D  master
     -+------------
     -+
     -+This is useful when topicB does not depend on topicA.
     -+
     -+A range of commits could also be removed with rebase.  If we have
     -+the following situation:
     -+
     -+------------
     -+    E---F---G---H---I---J  topicA
     -+------------
     -+
     -+then the command
     -+
     -+    git rebase --onto topicA~5 topicA~3 topicA
     -+
     -+would result in the removal of commits F and G:
     -+
     -+------------
     -+    E---H'---I'---J'  topicA
     -+------------
     -+
     -+This is useful if F and G were flawed in some way, or should not be
     -+part of topicA.  Note that the argument to `--onto` and the `<upstream>`
     -+parameter can be any valid commit-ish.
     -+
     -+
     - RECOVERING FROM UPSTREAM REBASE
     - -------------------------------
     - 
 5:  cb85642bb9d ! 5:  5a1dd8df29b doc: git-rebase: update discussion of internals
     @@ Documentation/git-rebase.adoc: linkgit:git-config[1] for details) and the `--for
      +tip, however, is accessible using the reflog of the current branch (i.e. `@{1}`,
      +see linkgit:gitrevisions[7].
       
     - MODE OPTIONS
     - ------------
     + TRANSPLANTING A TOPIC BRANCH WITH --ONTO
     + ----------------------------------------
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 23, 2025, 00:42 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v9 1/5] doc: git-rebase: start with an example

From: Julia Evans <julia@jvns.ca>
- Start with an example that mirrors the example in the `git-merge` man
  page, to make it easier for folks to understand the difference between
  a rebase and a merge.
- Mention that rebase can combine or reorder commits
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Show changes to Documentation/git-rebase.adoc +26 −22
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 956d3048f5a6..bb5a3ff7f828 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -16,6 +16,32 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
+Transplant a series of commits onto a different starting point.
+You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
+MODE below for how to do that.
+
+For example, imagine that you have been working on the `topic` branch in this
+history, and you want to "catch up" to the work done on the `master` branch.
+
+------------
+          A---B---C topic
+         /
+    D---E---F---G master
+------------
+
+You want to transplant the commits you made on `topic` since it diverged from
+`master` (i.e. A, B, and C), on top of the current `master`.  You can do this
+by running `git rebase master` while the `topic` branch is checked out.  If you
+want to rebase `topic` while on another branch, `git rebase master topic` is a
+shortcut for `git checkout topic && git rebase master`.
+
+------------
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -58,32 +84,6 @@ that caused the merge failure with `git rebase --skip`.  To check out the
 original `<branch>` and remove the `.git/rebase-apply` working files, use
 the command `git rebase --abort` instead.
 
-Assume the following history exists and the current branch is "topic":
-
-------------
-          A---B---C topic
-         /
-    D---E---F---G master
-------------
-
-From this point, the result of either of the following commands:
-
-
-    git rebase master
-    git rebase master topic
-
-would be:
-
-------------
-                  A'--B'--C' topic
-                 /
-    D---E---F---G master
-------------
-
-*NOTE:* The latter form is just a short-hand of `git checkout topic`
-followed by `git rebase master`. When rebase exits `topic` will
-remain the checked-out branch.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 23, 2025, 00:42 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v9 2/5] doc: git rebase: dedup merge conflict discussion

From: Julia Evans <julia@jvns.ca>

Previously there were two explanations, this combines them both into a single explanation.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Show changes to Documentation/git-rebase.adoc +20 −29
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index bb5a3ff7f828..e82ceb9cbfce 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -42,6 +42,26 @@ shortcut for `git checkout topic && git rebase master`.
 ------------
 
 
+If there is a merge conflict during this process, `git rebase` will stop at the
+first problematic commit and leave conflict markers. If this happens, you can do
+one of these things:
+
+1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<)
+   and make edits to resolve the conflict. For each file you edit, you need to
+   tell Git that the conflict has been resolved. You can mark the conflict as
+   resolved with  `git add <filename>`. After resolving all of the conflicts,
+   you can continue the rebasing process with
+
+   git rebase --continue
+
+2. Stop the `git rebase` and return your branch to its original state with
+
+   git rebase --abort
+
+3. Skip the commit that caused the merge conflict with
+
+   git rebase --skip
+
 If `<branch>` is specified, `git rebase` will perform an automatic
 `git switch <branch>` before doing anything else.  Otherwise
 it remains on the current branch.
@@ -77,13 +97,6 @@ any commits in `HEAD` which introduce the same textual changes as a commit
 in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
 with a different commit message or timestamp will be skipped).
 
-It is possible that a merge failure will prevent this process from being
-completely automatic.  You will have to resolve any such merge failure
-and run `git rebase --continue`.  Another option is to bypass the commit
-that caused the merge failure with `git rebase --skip`.  To check out the
-original `<branch>` and remove the `.git/rebase-apply` working files, use
-the command `git rebase --abort` instead.
-
 If the upstream branch already contains a change you have made (e.g.,
 because you mailed a patch which was applied upstream), then that commit
 will be skipped and warnings will be issued (if the 'merge' backend is
@@ -186,28 +199,6 @@ This is useful if F and G were flawed in some way, or should not be
 part of topicA.  Note that the argument to `--onto` and the `<upstream>`
 parameter can be any valid commit-ish.
 
-In case of conflict, `git rebase` will stop at the first problematic commit
-and leave conflict markers in the tree.  You can use `git diff` to locate
-the markers (<<<<<<) and make edits to resolve the conflict.  For each
-file you edit, you need to tell Git that the conflict has been resolved,
-typically this would be done with
-
-
-    git add <filename>
-
-
-After resolving the conflict manually and updating the index with the
-desired resolution, you can continue the rebasing process with
-
-
-    git rebase --continue
-
-
-Alternatively, you can undo the 'git rebase' with
-
-
-    git rebase --abort
-
 MODE OPTIONS
 ------------
 
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 23, 2025, 00:43 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v9 3/5] doc: git rebase: clarify arguments syntax

From: Julia Evans <julia@jvns.ca>

Remove duplicate explanation of `git rebase <upstream> <branch>` which is already explained above.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Show changes to Documentation/git-rebase.adoc +1 −5
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index e82ceb9cbfce..6d02648a9b3c 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -62,11 +62,7 @@ one of these things:
 
    git rebase --skip
 
-If `<branch>` is specified, `git rebase` will perform an automatic
-`git switch <branch>` before doing anything else.  Otherwise
-it remains on the current branch.
-
-If `<upstream>` is not specified, the upstream configured in
+If you don't specify an `<upstream>` to rebase onto, the upstream configured in
 `branch.<name>.remote` and `branch.<name>.merge` options will be used (see
 linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 23, 2025, 00:43 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v9 4/5] doc: git-rebase: move --onto explanation down

From: Julia Evans <julia@jvns.ca>

There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name.

Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 5 +++++
 1 file changed, 5 insertions(+)
Show changes to Documentation/git-rebase.adoc +5 −0
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index 6d02648a9b3c..b3354e0e4f82 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -114,6 +114,9 @@ will result in:
     D---E---A'---F master
 ------------
 
+TRANSPLANTING A TOPIC BRANCH WITH --ONTO
+----------------------------------------
+
 Here is how you would transplant a topic branch based on one
 branch to another, to pretend that you forked the topic branch
 from the latter branch, using `rebase --onto`.
@@ -240,6 +243,8 @@ As a special case, you may use "A\...B" as a shortcut for the
 merge base of A and B if there is exactly one merge base. You can
 leave out at most one of A and B, in which case it defaults to HEAD.
 
+See TRANSPLANTING A TOPIC BRANCH WITH --ONTO above for examples.
+
 --keep-base::
 	Set the starting point at which to create the new commits to the
 	merge base of `<upstream>` and `<branch>`. Running
-- 
gitgitgadget
Julia Evans via GitGitGadget· Aug 23, 2025, 00:43 UTC · re: Julia Evans via GitGitGadget · lore

[PATCH v9 5/5] doc: git-rebase: update discussion of internals

From: Julia Evans <julia@jvns.ca>
- make it clearer that we're talking about a multistep process
- give a more technically accurate description how rebase works with the
  merge backend.
- condense the explanation of how git rebase skips commits with the same
  textual changes into a single bullet point and remove the explanatory
  diagram. Lots of things which are more complicated are already being
  explained without a diagram.
- remove the explanation of how exactly `--fork-point` and `--root`
  work since that information is in the OPTIONS section
- put all discussion of `ORIG_HEAD` inside the note
Signed-off-by: Julia Evans <julia@jvns.ca>
---
 Documentation/git-rebase.adoc | 61 +++++++++++------------------------
 1 file changed, 18 insertions(+), 43 deletions(-)
Show changes to Documentation/git-rebase.adoc +18 −39
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index b3354e0e4f82..d2f760af6866 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -68,51 +68,26 @@ linkgit:git-config[1] for details) and the `--fork-point` option is
 assumed.  If you are currently not on any branch or if the current
 branch does not have a configured upstream, the rebase will abort.
 
-All changes made by commits in the current branch but that are not
-in `<upstream>` are saved to a temporary area.  This is the same set
-of commits that would be shown by `git log <upstream>..HEAD`; or by
-`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
-description on `--fork-point` below); or by `git log HEAD`, if the
-`--root` option is specified.
-
-The current branch is reset to `<upstream>` or `<newbase>` if the
-`--onto` option was supplied.  This has the exact same effect as
-`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
-to point at the tip of the branch before the reset.
+Here is a simplified description of what `git rebase <upstream>` does:
+
+1. Make a list of all commits on your current branch since it branched
+   off from `<upstream>` that do not have an equivalent commit in
+   `<upstream>`.
+2. Check out `<upstream>` with the equivalent of
+   `git checkout --detach <upstream>`.
+3. Replay the commits, one by one, in order. This is similar to running
+   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
+   are handled.
+4. Update your branch to point to the final commit with the equivalent
+   of `git checkout -B <branch>`.
 
 [NOTE]
-`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
-at the end of the rebase if other commands that write that pseudo-ref
-(e.g. `git reset`) are used during the rebase. The previous branch tip,
-however, is accessible using the reflog of the current branch
-(i.e. `@{1}`, see linkgit:gitrevisions[7]).
-
-The commits that were previously saved into the temporary area are
-then reapplied to the current branch, one by one, in order. Note that
-any commits in `HEAD` which introduce the same textual changes as a commit
-in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
-with a different commit message or timestamp will be skipped).
-
-If the upstream branch already contains a change you have made (e.g.,
-because you mailed a patch which was applied upstream), then that commit
-will be skipped and warnings will be issued (if the 'merge' backend is
-used).  For example, running `git rebase master` on the following
-history (in which `A'` and `A` introduce the same set of changes, but
-have different committer information):
-
-------------
-          A---B---C topic
-         /
-    D---E---A'---F master
-------------
-
-will result in:
-
-------------
-                   B'---C' topic
-                  /
-    D---E---A'---F master
-------------
+When starting the rebase, `ORIG_HEAD` is set to point to the commit at the tip
+of the to-be-rebased branch. However, `ORIG_HEAD` is not guaranteed to still
+point to that commit at the end of the rebase if other commands that change
+`ORIG_HEAD` (like `git reset`) are used during the rebase. The previous branch
+tip, however, is accessible using the reflog of the current branch (i.e. `@{1}`,
+see linkgit:gitrevisions[7].
 
 TRANSPLANTING A TOPIC BRANCH WITH --ONTO
 ----------------------------------------
-- 
gitgitgadget
Phillip Wood· Aug 13, 2025, 13:31 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

Hi Julia
On 11/08/2025 22:51, Julia Evans via GitGitGadget wrote:
>   * move "You can also use git rebase to reorder or combine commits:" to the
>     beginning
Great
Show 14 quoted lines
>   * replace "detailed description" with "simplified description" -- I thought
>     that I could write something that was relatively readable and also
>     accurate, but as usual Git has proven me wrong :). I tried to leave in
>     the details that I think seem relevant to using git: for example git
>     checkout --detach is relevant because it explains why git reflog works
>     well after a rebase.
>   * replace the git switch with git checkout that I'd missed previously
> 
> I didn't use the git log --cherry-pick option in the explanation because I
> had personally never heard of that option before today, and I don't want
> people to have to read the git log man page to be able to understand the
> explanation. I also left out --reapply-cherry-picks just because I don't
> understand the use case so I couldn't evaluate how likely it is to be
> relevant to the person reading.

The use case for --reapply-cherry-picks is mostly that it is faster to try picking a commit and then drop it if it results in a empty change than it is to do the patch-id comparisons to avoid picking the commit in the first place. This is especially true on partial clones where the cherry-pick detection is really slow. I'm happy to leave it out but I wonder if we should drop the references to --fork-point and --root as well given they're also both pretty niche. I'd also be very happy to go with Junio's suggestion to replace steps 1 & 2 with a general description that does not mention 'git log' at all.

Thanks
Phillip
Show 86 quoted lines
> 
> Julia Evans (5):
>    doc: git-rebase: start with an example
>    doc: git rebase: dedup merge conflict discussion
>    doc: git rebase: clarify arguments syntax
>    doc: git-rebase: move --onto explanation down
>    doc: git-rebase: update discussion of internals
> 
>   Documentation/git-rebase.adoc | 302 +++++++++++++++-------------------
>   1 file changed, 136 insertions(+), 166 deletions(-)
> 
> 
> base-commit: 2c2ba49d55ff26c1082b8137b1ec5eeccb4337d1
> Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1949%2Fjvns%2Fclarify-rebase-v6
> Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1949/jvns/clarify-rebase-v6
> Pull-Request: https://github.com/gitgitgadget/git/pull/1949
> 
> Range-diff vs v5:
> 
>   1:  c2f2e05078f ! 1:  e7a8fbbe53c doc: git-rebase: start with an example
>       @@ Documentation/git-rebase.adoc: SYNOPSIS
>         DESCRIPTION
>         -----------
>        +Transplant a series of commits onto a different starting point.
>       ++You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
>       ++MODE below for how to do that.
>        +
>        +For example, imagine that you have been working on the `topic` branch in this
>        +history, and you want to "catch up" to the work done on the `master` branch.
>       @@ Documentation/git-rebase.adoc: SYNOPSIS
>        +    D---E---F---G master
>        +------------
>        +
>       -+You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
>       -+MODE below for how to do that.
>        +
>         If `<branch>` is specified, `git rebase` will perform an automatic
>         `git switch <branch>` before doing anything else.  Otherwise
>   2:  5459b7ff560 ! 2:  ad63f69918d doc: git rebase: dedup merge conflict discussion
>       @@ Commit message
>        
>         ## Documentation/git-rebase.adoc ##
>        @@ Documentation/git-rebase.adoc: shortcut for `git checkout topic && git rebase master`.
>       - You can also use `git rebase` to reorder or combine commits: see INTERACTIVE
>       - MODE below for how to do that.
>       + ------------
>       +
>         
>        +If there is a merge conflict during this process, `git rebase` will stop at the
>        +first problematic commit and leave conflict markers. If this happens, you can do
>   3:  948c205f1e6 = 3:  7ee6b0afe88 doc: git rebase: clarify arguments syntax
>   4:  e229b9fccb2 = 4:  4686417b28e doc: git-rebase: move --onto explanation down
>   5:  5ab235b067b ! 5:  9c7f2716bc8 doc: git-rebase: update discussion of internals
>       @@ Documentation/git-rebase.adoc: linkgit:git-config[1] for details) and the `--for
>        -`--onto` option was supplied.  This has the exact same effect as
>        -`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
>        -to point at the tip of the branch before the reset.
>       -+Here is a more detailed description of what `git rebase <upstream>` does:
>       ++Here is a simplified description of what `git rebase <upstream>` does:
>        +
>       -+1. Make a list of all commits in the current branch that are not in
>       -+   `<upstream>`. This is the same set of commits that would be shown by `git log
>       -+   <upstream>..HEAD`. You can use `--fork-point` or `--root` to change how this
>       -+   list of commits is constructed.
>       ++1. Make a list of all new commits on your current branch since it branched
>       ++   off from `<upstream>`. This is the same set of commits that would be shown
>       ++   by `git log  <upstream>..HEAD`. You can use `--fork-point` or  `--root` to
>       ++   change how this list of commits is constructed.
>        +2. Check whether any of those commits are duplicates of commits already
>       -+   in `<upstream>`, remove them from the list, and print out a warning about
>       -+   each removed commit. You can use `--reapply-cherry-picks` to include
>       -+   duplicate commits.
>       -+3. Check out `<upstream>` (or `<newbase>` if the `--onto` option was
>       -+   supplied) with the equivalent of `git checkout --detach <upstream>`.
>       ++   in `<upstream>` and remove them from the list.
>       ++3. Check out `<upstream>` with the equivalent of `git checkout --detach <upstream>`.
>        +4. Replay the commits, one by one, in order. This is similar to running
>        +   `git cherry-pick <commit>` for each commit. See REBASING MERGES for how merges
>        +   are handled.
>        +5. Update your branch to point to the final commit with the equivalent
>       -+   of `git switch -C <branch>`.
>       ++   of `git checkout -C <branch>`.
>         
>         [NOTE]
>        -`ORIG_HEAD` is not guaranteed to still point to the previous branch tip
> 
Julia Evans· Aug 13, 2025, 15:33 UTC · re: Phillip Wood · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

Show 5 quoted lines
> The use case for --reapply-cherry-picks is mostly that it is faster to 
> try picking a commit and then drop it if it results in a empty change 
> than it is to do the patch-id comparisons to avoid picking the commit in 
> the first place. This is especially true on partial clones where the 
> cherry-pick detection is really slow.
That makes sense, thank you!
Show 5 quoted lines
> I'm happy to leave it out but I 
> wonder if we should drop the references to --fork-point and --root as 
> well given they're also both pretty niche. I'd also be very happy to go 
> with Junio's suggestion to replace steps 1 & 2 with a general 
> description that does not mention 'git log' at all.
I like the idea of leaving out `--fork-point` and `--root`.

Now that I know the use case for `--reapply-cherry-picks`: what I like about leaving in the `git log` description is that I think it makes it easier for folks to build a mental model of why a `git rebase` might be slow: there's a "fast step" (the `git log` step) and a "slow step" (the `git patch-id` step). Then even if we don't mention `--reapply-cherry-picks` in this section, a user could infer that there might be a way to speed up the "slow step", and find the `--reapply-cherry-picks` option to speed it up. Maybe we could mention that the `git patch-id` step can be slow in some cases.

(also I might have misunderstood the "fast step" and the "slow step" thing, I'd be interested to know if so)

Junio C Hamano· Aug 14, 2025, 21:18 UTC · re: Julia Evans · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

"Julia Evans" <julia@jvns.ca> writes:
Show 10 quoted lines
>> well given they're also both pretty niche. I'd also be very happy to go 
>> with Junio's suggestion to replace steps 1 & 2 with a general 
>> description that does not mention 'git log' at all.
>
> I like the idea of leaving out `--fork-point` and `--root`.
>
> Now that I know the use case for `--reapply-cherry-picks`: what I like about
> leaving in the `git log` description is that I think it makes it easier for
> folks to build a mental model of why a `git rebase` might be slow: there's a
> "fast step" (the `git log` step) and a "slow step" (the `git patch-id` step).

But that is not what goes on, is it? What you wrote as if they were two separate steps (1 to enumerate, 2 to filter) is not what happens in practice. Whether it is done via the "format-patch --stdout | am" pipeline in run_am(), or via the "rev-list --reverse | xargs -n1 cherry-pick" pipeline in run_sequencer_rebase(), the upstream of these conceptual pipelines that enumerates what is to be replayed is run just once, i.e. there is only one step that "enumerates what is to be replayed", without a separate filtering step.

In other words, there is no "a fast step followed by a slow step".

Perhaps squashing the first two steps into one and phrasing them as a single step is sufficient to give a conceptual overview (what you have in v7 as "a simplified description of what the command does").

 1. Make a list of all commits on your current branch since it
    branched off from `<upstream>` that do not have equivalent
    change in `<upstream>`.

If you want to keep 1 & 2 separate, then rephrase the introductory sentence to clarify that we are giving a white lie for the sake of easier understanding, e.g.

    Here is what conceptually happens in "git rebase":
or something.
Phillip Wood· Aug 15, 2025, 10:25 UTC · re: Junio C Hamano · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

On 14/08/2025 22:18, Junio C Hamano wrote:
Show 12 quoted lines
> "Julia Evans" <julia@jvns.ca> writes:
> 
>>> well given they're also both pretty niche. I'd also be very happy to go
>>> with Junio's suggestion to replace steps 1 & 2 with a general
>>> description that does not mention 'git log' at all.
>>
>> I like the idea of leaving out `--fork-point` and `--root`.
>>
>> Now that I know the use case for `--reapply-cherry-picks`: what I like about
>> leaving in the `git log` description is that I think it makes it easier for
>> folks to build a mental model of why a `git rebase` might be slow: there's a
>> "fast step" (the `git log` step) and a "slow step" (the `git patch-id` step).
 >
Show 10 quoted lines
> But that is not what goes on, is it?  What you wrote as if they were
> two separate steps (1 to enumerate, 2 to filter) is not what happens
> in practice.  Whether it is done via the "format-patch --stdout | am"
> pipeline in run_am(), or via the "rev-list --reverse | xargs -n1
> cherry-pick" pipeline in run_sequencer_rebase(), the upstream of
> these conceptual pipelines that enumerates what is to be replayed is
> run just once, i.e. there is only one step that "enumerates what is
> to be replayed", without a separate filtering step.
> 
> In other words, there is no "a fast step followed by a slow step".

Although the cherry-pick detection happens inside "git log" that command has a fast step (find the commits on both sides of the merge base) and a slow step (detect cherry-picks) so I think it depends where one draws the step boundaries. The cherry-pick detection is known to be slow when there are a lot of new upstream commits which was the motivation for adding --reapply-cherry-picks in 0fcb4f6b62 (rebase --merge: optionally skip upstreamed commits, 2020-04-11)

Show 13 quoted lines
> Perhaps squashing the first two steps into one and phrasing them as
> a single step is sufficient to give a conceptual overview (what you
> have in v7 as "a simplified description of what the command does").
> 
>   1. Make a list of all commits on your current branch since it
>      branched off from `<upstream>` that do not have equivalent
>      change in `<upstream>`.
> 
> If you want to keep 1 & 2 separate, then rephrase the introductory
> sentence to clarify that we are giving a white lie for the sake of
> easier understanding, e.g.
> 
>      Here is what conceptually happens in "git rebase":
Either of those sounds reasonable to me
Thanks
Phillip
Junio C Hamano· Aug 15, 2025, 15:45 UTC · re: Phillip Wood · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

Phillip Wood <phillip.wood123@gmail.com> writes:
Show 7 quoted lines
> Although the cherry-pick detection happens inside "git log" that
> command has a fast step (find the commits on both sides of the merge
> base) and a slow step (detect cherry-picks) so I think it depends
> where one draws the step boundaries. The cherry-pick detection is
> known to be slow when there are a lot of new upstream commits which
> was the motivation for adding --reapply-cherry-picks in 0fcb4f6b62
> (rebase --merge: optionally skip upstreamed commits, 2020-04-11)

Correct, in the description of "reapply-cherry-picks", it may need to be discussed to guide the readers decide when to use the option.

But would it really help understanding of readers to give such level of detail in "here is roughly how it works" description? I am not sure about that.

Phillip Wood· Aug 15, 2025, 15:54 UTC · re: Junio C Hamano · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

On 15/08/2025 16:45, Junio C Hamano wrote:
Show 16 quoted lines
> Phillip Wood <phillip.wood123@gmail.com> writes:
> 
>> Although the cherry-pick detection happens inside "git log" that
>> command has a fast step (find the commits on both sides of the merge
>> base) and a slow step (detect cherry-picks) so I think it depends
>> where one draws the step boundaries. The cherry-pick detection is
>> known to be slow when there are a lot of new upstream commits which
>> was the motivation for adding --reapply-cherry-picks in 0fcb4f6b62
>> (rebase --merge: optionally skip upstreamed commits, 2020-04-11)
> 
> Correct, in the description of "reapply-cherry-picks", it may need
> to be discussed to guide the readers decide when to use the option.
> 
> But would it really help understanding of readers to give such level
> of detail in "here is roughly how it works" description?  I am not
> sure about that.

I'd certainly be happy to see these two steps in the description simplified and combined as you've suggested elsewhere.

Thanks
Phillip
Julia Evans· Aug 15, 2025, 15:56 UTC · re: Phillip Wood · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

Show 17 quoted lines
>>> Although the cherry-pick detection happens inside "git log" that
>>> command has a fast step (find the commits on both sides of the merge
>>> base) and a slow step (detect cherry-picks) so I think it depends
>>> where one draws the step boundaries. The cherry-pick detection is
>>> known to be slow when there are a lot of new upstream commits which
>>> was the motivation for adding --reapply-cherry-picks in 0fcb4f6b62
>>> (rebase --merge: optionally skip upstreamed commits, 2020-04-11)
>> 
>> Correct, in the description of "reapply-cherry-picks", it may need
>> to be discussed to guide the readers decide when to use the option.
>> 
>> But would it really help understanding of readers to give such level
>> of detail in "here is roughly how it works" description?  I am not
>> sure about that.
>
> I'd certainly be happy to see these two steps in the description 
> simplified and combined as you've suggested elsewhere.
I'll combine them then: that seems like the simplest solution.
best,
- Julia
Phillip Wood· Aug 15, 2025, 10:25 UTC · re: Julia Evans · lore

Re: [PATCH v6 0/5] doc: git-rebase: clarify DESCRIPTION section

On 13/08/2025 16:33, Julia Evans wrote:
Show 16 quoted lines
> 
>> I'm happy to leave it out but I
>> wonder if we should drop the references to --fork-point and --root as
>> well given they're also both pretty niche. I'd also be very happy to go
>> with Junio's suggestion to replace steps 1 & 2 with a general
>> description that does not mention 'git log' at all.
> 
> I like the idea of leaving out `--fork-point` and `--root`.
> 
> Now that I know the use case for `--reapply-cherry-picks`: what I like about
> leaving in the `git log` description is that I think it makes it easier for
> folks to build a mental model of why a `git rebase` might  be slow: there's a
> "fast step" (the `git log` step) and a "slow step" (the `git patch-id` step).
> Then even if we don't mention `--reapply-cherry-picks` in this section, a user
> could infer that there might be a way to speed up the "slow step", and find the
> `--reapply-cherry-picks` option to speed it up. 

Possibly though I think they'd need a reasonably good understanding of how the cherry-pick detection works - do most folks really know what a patch-id is and that detecting cherry-picks means generating a diff for each commit on either side of the merge base?

> Maybe we could mention that the
> `git patch-id` step can be slow in some cases.

That might be worth it depending on how much detail we want. I think it is only really a problem on large fast-moving repositories where a lot of upstream commits get added between rebases and on partial clones. The latter is due to a sub-optimal implementation that does not batch the fetches for missing blobs, though I guess if your repository is big enough to warrant a partial clone you'd be likely to hit the first issue even if the fetching was more efficient. If we say it can be slow we should perhaps mention that this step can be skipped

> (also I might have misunderstood the "fast step" and the "slow step" thing,
> I'd be interested to know if so)

I've commented on this in my reply to Junio - I think it depends where you draw the stop boundaries.

Thanks
Phillip
D. Ben Knoble· Aug 9, 2025, 15:04 UTC · re: Julia Evans via GitGitGadget · lore

Re: [PATCH v2 0/5] doc: git-rebase: clarify DESCRIPTION section

On Fri, Aug 8, 2025 at 3:15 PM Julia Evans via GitGitGadget <gitgitgadget@gmail.com> wrote:

Show 18 quoted lines
>
> Thanks for the review comments, here are the new changes which:
>
>  * make the intro to the man page less dry, with the suggested wording
>  * clarify the merge conflict resolution explanation & fix the HTML
>    formatting issues
>  * move the explanation of the git rebase <upstream> <branch> syntax up into
>    the intro
>
> I'm still curious about the intention for the git rebase master topic
> syntax, since I'd never heard of it before. Is it just to save on typing,
> since it's fewer characters than git switch topic and then git rebase
> master? I ask because someone mentioned to me on Mastodon
> (https://hachyderm.io/@simontatham/114988051822317920) that they sometimes
> use git rebase HEAD main as part of their workflow, which is not equivalent
> to git checkout main && git rebase HEAD. That made me think that there might
> be some broader intent to enable rebases that wouldn't otherwise be possible
> without that syntax.

I think the intent really is "shortcut." It's existed since the first version of rebase (59e6b23ace ([PATCH] git-rebase-script: rebase local commits to new upstream head., 2005-06-25), https://lore.kernel.org/git/7v4qboejp6.fsf_-_@assigned-by-dhcp.cox.net/). I didn't look too closely at that mailing list thread for any justification of the shortcut, though.

The example mentioned on Mastodon is still a shortcut, it's just more like a function than a macro (that is, the arguments are evaluated first, then the shortcut applied):

    git rebase HEAD main
becomes (in shell syntax)
    head=$(git rev-parse HEAD)
    git switch --detach main
    git rebase $head
rather than
    git switch --detach main
    git rebase HEAD # too late, HEAD has changed

← back to recent threads