Skip to contentSkip to conversation

doc: git-rebase: clarify DESCRIPTION section

PATCH Superseded Julia Evans via GitGitGadget 7 participants 103 messages Aug 8, 2025 – Aug 23, 2025 Documentation

lore
Share & tools
lore
#0 lore raw

cover doc: git-rebase: clarify DESCRIPTION section

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

Signature · 1 line
gitgitgadget
#1 lore raw

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

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 46 +++++++++++++++--------------------
 1 file changed, 20 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +20 -26
index 956d3048f5a6..fee73623990d 100644
@@ -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
Signature · 1 line
gitgitgadget
#2 lore raw

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

Quoted 16 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 46 +++++++++++++++--------------------
 1 file changed, 20 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +0 -0
index 956d3048f5a6..fee73623990d 100644

Documentation/git-rebase.adoc SYNOPSIS · line 19

Quoted 4 lines
Documentation/git-rebase.adoc +1 -0
@@ -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.

Documentation/git-rebase.adoc SYNOPSIS · line 21

Quoted 1 line
Documentation/git-rebase.adoc +1 -0
+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.

Quoted 52 lines
Documentation/git-rebase.adoc +16 -26
+------------
+          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
#3 lore raw

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

Quoted 26 lines · Junio C Hamano
Quoted 16 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 46 +++++++++++++++--------------------
 1 file changed, 20 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +0 -0
index 956d3048f5a6..fee73623990d 100644

Documentation/git-rebase.adoc SYNOPSIS · line 19

Quoted 4 lines
Documentation/git-rebase.adoc +1 -0
@@ -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.

Quoted 5 lines

Documentation/git-rebase.adoc SYNOPSIS · line 21

Quoted 1 line
Documentation/git-rebase.adoc +1 -0
+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.

Quoted 4 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: 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.

#4 lore raw

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

Quoted 4 lines · Julia Evans

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].

Quoted 6 lines
Quoted 4 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.

#5 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 52 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +23 -29
index fee73623990d..3087e558b509 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#6 lore raw

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

Documentation/git-rebase.adoc from `master` and copy the changes in each of those commits on top of the · line 40

Quoted 2 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +2 -0
+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.

Documentation/git-rebase.adoc from `master` and copy the changes in each of those commits on top of the · line 51

Quoted 10 lines

+1. Resolve the conflict. You can use git diff to find the markers (<<<<<<)

Documentation/git-rebase.adoc +9 -0
+   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?

Documentation/git-rebase.adoc from `master` and copy the changes in each of those commits on top of the · line 59

Quoted 7 lines

+2. Stop the git rebase and return your branch to its original state with

Documentation/git-rebase.adoc +6 -0
+
+   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.

#7 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
Documentation/git-rebase.adoc +3 -5
index 3087e558b509..ada9f6b2614b 100644
@@ -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
Signature · 1 line
gitgitgadget
#8 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +87 -81
index ada9f6b2614b..c63d67f340a0 100644
@@ -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
 -------------------------------
 
Signature · 1 line
gitgitgadget
#9 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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.

---
 Documentation/git-rebase.adoc | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
Documentation/git-rebase.adoc +7 -8
index c63d67f340a0..6b79cd0daca9 100644
@@ -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
Signature · 1 line
gitgitgadget
#10 lore raw

v2 cover doc: git-rebase: clarify DESCRIPTION section

In reply to Julia Evans via GitGitGadget

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

## 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>`

## 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
Signature · 1 line
gitgitgadget
#11 lore raw

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

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +23 -26
index 956d3048f5a6..6dacf693bd71 100644
@@ -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
Signature · 1 line
gitgitgadget
#12 lore raw

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

Quoted 6 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +6 -0
+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.
+
+------------

Documentation/git-rebase.adoc SYNOPSIS · line 34

Quoted 10 lines
Documentation/git-rebase.adoc +10 -0
+          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.

Documentation/git-rebase.adoc SYNOPSIS · line 41

Quoted 6 lines

+------------

Documentation/git-rebase.adoc +5 -0
+                  A'--B'--C' topic
+                 /
+    D---E---F---G master
+------------
+

Other than that, looks great.

#13 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 50 +++++++++++++++--------------------
 1 file changed, 21 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +21 -29
index 6dacf693bd71..a93c616f38b1 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#14 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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>

---
 Documentation/git-rebase.adoc | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
Documentation/git-rebase.adoc +1 -6
index a93c616f38b1..e700b92e35ac 100644
@@ -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
Signature · 1 line
gitgitgadget
#15 lore raw

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

Quoted 5 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

Quoted 23 lines
---
 Documentation/git-rebase.adoc | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
Documentation/git-rebase.adoc +1 -6
index a93c616f38b1..e700b92e35ac 100644
@@ -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
#16 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +87 -81
index e700b92e35ac..6a4b3dbd5960 100644
@@ -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
 -------------------------------
 
Signature · 1 line
gitgitgadget
#17 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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.

---
 Documentation/git-rebase.adoc | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
Documentation/git-rebase.adoc +7 -8
index 6a4b3dbd5960..5a49e4f2de9a 100644
@@ -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
Signature · 1 line
gitgitgadget
#18 lore raw

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

Quoted 3 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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.

Quoted 3 lines

- 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.

Quoted 2 lines

- 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.

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 75

Quoted 9 lines
Documentation/git-rebase.adoc +3 -1
-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.

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 80

Quoted 5 lines
Documentation/git-rebase.adoc +1 -1
-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.

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 83

Quoted 2 lines
Documentation/git-rebase.adoc +2 -0
+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.

#19 lore raw

v3 cover doc: git-rebase: clarify DESCRIPTION section

In reply to Julia Evans via GitGitGadget

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.

 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

@@ 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]).

Signature · 1 line
gitgitgadget
#20 lore raw

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

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +23 -26
index 956d3048f5a6..6dacf693bd71 100644
@@ -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
Signature · 1 line
gitgitgadget
#21 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 50 +++++++++++++++--------------------
 1 file changed, 21 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +21 -29
index 6dacf693bd71..a93c616f38b1 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#22 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
Documentation/git-rebase.adoc +1 -6
index a93c616f38b1..e700b92e35ac 100644
@@ -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
Signature · 1 line
gitgitgadget
#23 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +87 -81
index e700b92e35ac..6a4b3dbd5960 100644
@@ -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
 -------------------------------
 
Signature · 1 line
gitgitgadget
#24 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)
Documentation/git-rebase.adoc +17 -17
index 6a4b3dbd5960..df77bbdecfec 100644
@@ -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
Signature · 1 line
gitgitgadget
#25 lore raw

v4 cover doc: git-rebase: clarify DESCRIPTION section

In reply to Julia Evans via GitGitGadget

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 <[email protected]>
      
       ## 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
Signature · 1 line
gitgitgadget
#26 lore raw

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

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +23 -26
index 956d3048f5a6..449f01fba560 100644
@@ -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
Signature · 1 line
gitgitgadget
#27 lore raw

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

Hi Julia

Quoted 5 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

Quoted 72 lines
---
  Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
  1 file changed, 23 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +23 -26
index 956d3048f5a6..449f01fba560 100644
@@ -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
#28 lore raw

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

In reply to Julia Evans via GitGitGadget
Quoted 5 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

Documentation/git-rebase.adoc SYNOPSIS · line 19

Quoted 9 lines
Documentation/git-rebase.adoc +1 -0
index 956d3048f5a6..449f01fba560 100644
@@ -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

#29 lore raw

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

In reply to Julia Evans via GitGitGadget
Quoted 6 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

Quoted 20 lines
---
 Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------
 1 file changed, 23 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +7 -0
index 956d3048f5a6..449f01fba560 100644
@@ -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

Documentation/git-rebase.adoc SYNOPSIS · line 35

Quoted 10 lines
Documentation/git-rebase.adoc +10 -0
+         /
+    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]

#30 lore raw

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

Quoted 31 lines · Karthik Nayak
Quoted 27 lines · "Julia Evans via GitGitGadget

---
Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------

1 file changed, 23 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +0 -0
index 956d3048f5a6..449f01fba560 100644
@@ -16,6 +16,29 @@ SYNOPSIS
 

DESCRIPTION
-----------

Documentation/git-rebase.adoc +13 -0
+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
Quoted 8 lines

Documentation/git-rebase.adoc SYNOPSIS · line 35

Quoted 4 lines
Documentation/git-rebase.adoc +4 -0
+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)?

#31 lore raw

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

Quoted 39 lines · Ben Knoble
Quoted 30 lines · Karthik Nayak
Quoted 27 lines · "Julia Evans via GitGitGadget

---
Documentation/git-rebase.adoc | 49 ++++++++++++++++-------------------

1 file changed, 23 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +0 -0
index 956d3048f5a6..449f01fba560 100644
@@ -16,6 +16,29 @@ SYNOPSIS
 

DESCRIPTION
-----------

Documentation/git-rebase.adoc +13 -0
+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
Quoted 8 lines

Documentation/git-rebase.adoc SYNOPSIS · line 35

Quoted 4 lines
Documentation/git-rebase.adoc +4 -0
+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?

Quoted 1 line

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!

#32 lore raw

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

Quoted 3 lines · Karthik Nayak
Quoted 3 lines
Quoted 3 lines

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.

#33 lore raw

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

In reply to Karthik Nayak
Quoted 12 lines · Karthik Nayak

Documentation/git-rebase.adoc SYNOPSIS · line 35

Quoted 7 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +7 -0
+
+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. <[email protected]>. 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

#34 lore raw

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

Quoted 14 lines · Phillip Wood
Quoted 12 lines · Karthik Nayak

Documentation/git-rebase.adoc SYNOPSIS · line 35

Quoted 7 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +7 -0
+
+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?

Quoted 7 lines

Junio has already expressed a preference for "checkout" here c.f. <[email protected]>. 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.

Quoted 3 lines

Thanks

Phillip

#35 lore raw

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

Quoted 25 lines · Karthik Nayak
Quoted 14 lines · Phillip Wood
Quoted 12 lines · Karthik Nayak

Documentation/git-rebase.adoc SYNOPSIS · line 35

Quoted 7 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +7 -0
+
+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?

Quoted 7 lines

Junio has already expressed a preference for "checkout" here c.f. <[email protected]>. 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).

Quoted 2 lines

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.)

Signature · 1 line
D. Ben Knoble
#36 lore raw

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

Quoted 4 lines · D. Ben Knoble
Quoted 4 lines
Quoted 4 lines

Junio has already expressed a preference for "checkout" here c.f. <[email protected]>. 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.

#37 lore raw

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

Quoted 17 lines · Junio C Hamano
Quoted 4 lines · D. Ben Knoble
Quoted 4 lines
Quoted 4 lines

Junio has already expressed a preference for "checkout" here c.f. <[email protected]>. 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.

Quoted 8 lines

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.

Quoted 2 lines

But let's leave that outside this topic.

Agreed.

Quoted 1 line

Thanks.

#38 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 50 +++++++++++++++--------------------
 1 file changed, 21 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +21 -29
index 449f01fba560..e30b9535fff1 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#39 lore raw

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

Quoted 22 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +14 -0
index 449f01fba560..e30b9535fff1 100644
@@ -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
+

Documentation/git-rebase.adoc shortcut for `git checkout topic && git rebase master`. · line 65

Quoted 10 lines
Documentation/git-rebase.adoc +7 -0
+   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.

Quoted 4 lines
Documentation/git-rebase.adoc +0 -0
@@ -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).
 

Documentation/git-rebase.adoc any commits in `HEAD` which introduce the same textual changes as a commit · line 100

Quoted 10 lines
Documentation/git-rebase.adoc +0 -7
-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

#40 lore raw

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

Quoted 16 lines · Patrick Steinhardt

Documentation/git-rebase.adoc any commits in `HEAD` which introduce the same textual changes as a commit · line 100

Quoted 11 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +0 -7
-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

#41 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)
Documentation/git-rebase.adoc +1 -6
index e30b9535fff1..914f743ae00f 100644
@@ -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
Signature · 1 line
gitgitgadget
#42 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +87 -81
index 914f743ae00f..50c84f138212 100644
@@ -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
 -------------------------------
 
Signature · 1 line
gitgitgadget
#43 lore raw

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

Quoted 18 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +0 -0
index 914f743ae00f..50c84f138212 100644

Documentation/git-rebase.adoc will result in: · line 116

Quoted 6 lines
Documentation/git-rebase.adoc +0 -3
@@ -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.

Quoted 186 lines
Documentation/git-rebase.adoc +87 -79
-
-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

Signature · 1 line
D. Ben Knoble
#44 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)
Documentation/git-rebase.adoc +17 -17
index 50c84f138212..c16ee37b46a7 100644
@@ -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
Signature · 1 line
gitgitgadget
#45 lore raw

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

Hi Julia

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is

Quoted 7 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

Documentation/git-rebase.adoc +5 -0
+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>.

Quoted 2 lines

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

Quoted 28 lines
Documentation/git-rebase.adoc +11 -6
+
+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
#46 lore raw

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

Quoted 6 lines · Phillip Wood

Hi Julia

Quoted 2 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

Quoted 9 lines

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is

Quoted 5 lines
Documentation/git-rebase.adoc +5 -0
+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.

#47 lore raw

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

Quoted 8 lines · D. Ben Knoble
    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 ;-).

#48 lore raw

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

In reply to Julia Evans via GitGitGadget
Quoted 25 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +6 -11
index 50c84f138212..c16ee37b46a7 100644
@@ -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.

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 83

Quoted 10 lines
Documentation/git-rebase.adoc +10 -0
+
+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?

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 91

Quoted 7 lines
Documentation/git-rebase.adoc +1 -0
 [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

#49 lore raw

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

Quoted 34 lines · Patrick Steinhardt
Quoted 30 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +0 -0
index 50c84f138212..c16ee37b46a7 100644
@@ -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.

Documentation/git-rebase.adoc +11 -11
-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
Quoted 8 lines

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 83

Quoted 5 lines

+git cherry-pick <commit> for each commit. See REBASING MERGES for how merges

Documentation/git-rebase.adoc +4 -0
+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).

#50 lore raw

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

Quoted 43 lines · Ben Knoble
Quoted 34 lines · Patrick Steinhardt
Quoted 30 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +0 -0
index 50c84f138212..c16ee37b46a7 100644
@@ -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.

Documentation/git-rebase.adoc +11 -11
-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
Quoted 8 lines

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 83

Quoted 5 lines

+git cherry-pick <commit> for each commit. See REBASING MERGES for how merges

Documentation/git-rebase.adoc +4 -0
+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?

Quoted 2 lines

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

#51 lore raw

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

In reply to Patrick Steinhardt
Quoted 2 lines

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.

Quoted 19 lines
Quoted 8 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]).

Quoted 4 lines

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

#52 lore raw

v5 cover doc: git-rebase: clarify DESCRIPTION section

In reply to Julia Evans via GitGitGadget

* 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

@@ 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
+ ------------

Signature · 1 line
gitgitgadget
#53 lore raw

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

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +26 -26
index 956d3048f5a6..03d1b74a9a09 100644
@@ -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
Signature · 1 line
gitgitgadget
#54 lore raw

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

Quoted 6 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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 ...

#55 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +20 -29
index 03d1b74a9a09..4ba74a8cf9ba 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#56 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Documentation/git-rebase.adoc +1 -5
index 4ba74a8cf9ba..117c3f43719f 100644
@@ -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
Signature · 1 line
gitgitgadget
#57 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +87 -81
index 117c3f43719f..750f5e67e4c3 100644
@@ -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
 -------------------------------
 
Signature · 1 line
gitgitgadget
#58 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 66 ++++++++++++-----------------------
 1 file changed, 23 insertions(+), 43 deletions(-)
Documentation/git-rebase.adoc +23 -43
index 750f5e67e4c3..b4e5519d2839 100644
@@ -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
 ------------
Signature · 1 line
gitgitgadget
#59 lore raw

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

Quoted 31 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 66 ++++++++++++-----------------------
 1 file changed, 23 insertions(+), 43 deletions(-)
Documentation/git-rebase.adoc +0 -5
index 750f5e67e4c3..b4e5519d2839 100644
@@ -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

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 74

Quoted 10 lines
Documentation/git-rebase.adoc +1 -6
-`--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 ;-)

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 76

Quoted 4 lines
Documentation/git-rebase.adoc +4 -0
+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?

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 80

Quoted 4 lines
Documentation/git-rebase.adoc +4 -0
+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).

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 87

Quoted 7 lines
Documentation/git-rebase.adoc +7 -0
+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.

#60 lore raw

v6 cover doc: git-rebase: clarify DESCRIPTION section

In reply to Julia Evans via GitGitGadget

* 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

Signature · 1 line
gitgitgadget
#61 lore raw

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

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +26 -26
index 956d3048f5a6..bb5a3ff7f828 100644
@@ -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
Signature · 1 line
gitgitgadget
#62 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +20 -29
index bb5a3ff7f828..e82ceb9cbfce 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#63 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Documentation/git-rebase.adoc +1 -5
index e82ceb9cbfce..6d02648a9b3c 100644
@@ -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
Signature · 1 line
gitgitgadget
#64 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +87 -81
index 6d02648a9b3c..d041d87f270b 100644
@@ -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
 -------------------------------
 
Signature · 1 line
gitgitgadget
#65 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 63 +++++++++++------------------------
 1 file changed, 20 insertions(+), 43 deletions(-)
Documentation/git-rebase.adoc +20 -43
index d041d87f270b..d4fc80ebb20c 100644
@@ -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
 ------------
Signature · 1 line
gitgitgadget
#66 lore raw

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

Quoted 1 line · Julia Evans via GitGitGadget

+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.

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 78

Quoted 6 lines

+1. Make a list of all new commits on your current branch since it branched

Documentation/git-rebase.adoc +5 -0
+   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>.

Quoted 1 line

+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.

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 84

Quoted 5 lines

+4. Replay the commits, one by one, in order. This is similar to running

Documentation/git-rebase.adoc +4 -0
+   `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.

#67 lore raw

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

Quoted 8 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:

Quoted 1 line

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.

Quoted 2 lines

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.

Quoted 2 lines

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

Will fix.

#68 lore raw
In reply to Julia Evans via GitGitGadget
Quoted 10 lines · Julia Evans via GitGitGadget

* 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

Quoted 6 lines

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.

#69 lore raw

v7 cover doc: git-rebase: clarify DESCRIPTION section

In reply to Julia Evans via GitGitGadget

* 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

Signature · 1 line
gitgitgadget
#70 lore raw

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

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +26 -26
index 956d3048f5a6..bb5a3ff7f828 100644
@@ -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
Signature · 1 line
gitgitgadget
#71 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +20 -29
index bb5a3ff7f828..e82ceb9cbfce 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#72 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Documentation/git-rebase.adoc +1 -5
index e82ceb9cbfce..6d02648a9b3c 100644
@@ -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
Signature · 1 line
gitgitgadget
#73 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +87 -81
index 6d02648a9b3c..d041d87f270b 100644
@@ -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
 -------------------------------
 
Signature · 1 line
gitgitgadget
#74 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 65 ++++++++++++-----------------------
 1 file changed, 22 insertions(+), 43 deletions(-)
Documentation/git-rebase.adoc +22 -43
index d041d87f270b..cce2577a8ade 100644
@@ -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
 ------------
Signature · 1 line
gitgitgadget
#75 lore raw

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

Documentation/git-rebase.adoc linkgit:git-config[1] for details) and the `--fork-point` option is · line 79

Quoted 9 lines · Julia Evans via GitGitGadget
Documentation/git-rebase.adoc +9 -0
+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.

#76 lore raw

v8 cover doc: git-rebase: clarify DESCRIPTION section

In reply to Julia Evans via GitGitGadget

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]

Signature · 1 line
gitgitgadget
#77 lore raw

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

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +26 -26
index 956d3048f5a6..bb5a3ff7f828 100644
@@ -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
Signature · 1 line
gitgitgadget
#78 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +20 -29
index bb5a3ff7f828..e82ceb9cbfce 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#79 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Documentation/git-rebase.adoc +1 -5
index e82ceb9cbfce..6d02648a9b3c 100644
@@ -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
Signature · 1 line
gitgitgadget
#80 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
 1 file changed, 87 insertions(+), 81 deletions(-)
Documentation/git-rebase.adoc +87 -81
index 6d02648a9b3c..d041d87f270b 100644
@@ -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
 -------------------------------
 
Signature · 1 line
gitgitgadget
#81 lore raw

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

Quoted 11 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 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.

#82 lore raw

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

Quoted 14 lines · Junio C Hamano
Quoted 11 lines · Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
  Documentation/git-rebase.adoc | 168 ++++++++++++++++++----------------
  1 file changed, 87 insertions(+), 81 deletions(-)
Quoted 7 lines

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.

Quoted 3 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. 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

Quoted 46 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.

#83 lore raw

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

Quoted 6 lines · Phillip Wood
Quoted 3 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.

Quoted 4 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?

#84 lore raw

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

Quoted 9 lines
Quoted 4 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.

#85 lore raw

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

Quoted 10 lines · Julia Evans
Quoted 9 lines
Quoted 4 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?

Quoted 4 lines

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.

#86 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 61 +++++++++++------------------------
 1 file changed, 18 insertions(+), 43 deletions(-)
Documentation/git-rebase.adoc +18 -43
index d041d87f270b..2a44f8a0ceda 100644
@@ -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
 ------------
Signature · 1 line
gitgitgadget
#87 lore raw
In reply to Julia Evans via GitGitGadget
Quoted 2 lines · Julia Evans via GitGitGadget

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

Quoted 50 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]

#88 lore raw

v9 cover doc: git-rebase: clarify DESCRIPTION section

In reply to Julia Evans via GitGitGadget

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
+ ----------------------------------------

Signature · 1 line
gitgitgadget
#89 lore raw

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

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------
 1 file changed, 26 insertions(+), 26 deletions(-)
Documentation/git-rebase.adoc +26 -26
index 956d3048f5a6..bb5a3ff7f828 100644
@@ -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
Signature · 1 line
gitgitgadget
#90 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 49 ++++++++++++++---------------------
 1 file changed, 20 insertions(+), 29 deletions(-)
Documentation/git-rebase.adoc +20 -29
index bb5a3ff7f828..e82ceb9cbfce 100644
@@ -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
 ------------
 
Signature · 1 line
gitgitgadget
#91 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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

---
 Documentation/git-rebase.adoc | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
Documentation/git-rebase.adoc +1 -5
index e82ceb9cbfce..6d02648a9b3c 100644
@@ -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
Signature · 1 line
gitgitgadget
#92 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

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.

---
 Documentation/git-rebase.adoc | 5 +++++
 1 file changed, 5 insertions(+)
Documentation/git-rebase.adoc +5 -0
index 6d02648a9b3c..b3354e0e4f82 100644
@@ -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
Signature · 1 line
gitgitgadget
#93 lore raw

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

In reply to Julia Evans via GitGitGadget

From: Julia Evans <[email protected]>

- 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

---
 Documentation/git-rebase.adoc | 61 +++++++++++------------------------
 1 file changed, 18 insertions(+), 43 deletions(-)
Documentation/git-rebase.adoc +18 -43
index b3354e0e4f82..d2f760af6866 100644
@@ -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
 ----------------------------------------
Signature · 1 line
gitgitgadget
#94 lore raw
In reply to Julia Evans via GitGitGadget

Hi Julia

Quoted 2 lines · Julia Evans via GitGitGadget

* move "You can also use git rebase to reorder or combine commits:" to the beginning

Great

Quoted 8 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

Quoted 6 lines

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

Quoted 86 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

#95 lore raw
Quoted 5 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!

Quoted 5 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)

#96 lore raw
Quoted 10 lines · Julia Evans
Quoted 3 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.

#97 lore raw
Quoted 22 lines · Junio C Hamano
Quoted 10 lines · Julia Evans
Quoted 3 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.

Quoted 1 line

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)

Quoted 8 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>.

Quoted 5 lines

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

#98 lore raw
Quoted 7 lines · Phillip Wood

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.

#99 lore raw
Quoted 10 lines · Junio C Hamano
Quoted 7 lines · Phillip Wood

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)

Quoted 6 lines

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

#100 lore raw
Quoted 11 lines
Quoted 11 lines
Quoted 7 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.

Quoted 6 lines
Quoted 3 lines

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

#101 lore raw
In reply to Julia Evans
Quoted 9 lines · Julia Evans
Quoted 6 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.

Quoted 7 lines

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?

Quoted 2 lines

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

Quoted 2 lines

(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

#102 lore raw
In reply to Julia Evans via GitGitGadget
Quoted 9 lines · Julia Evans via GitGitGadget

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

Quoted 9 lines

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/[email protected]/).
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