From e7a8fbbe53c9cf5cb7b8d822e72ff4219de37e1c Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Wed, 6 Aug 2025 15:53:47 -0400 Subject: [PATCH 1/5] 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. - Mention that rebase can combine or reorder commits Signed-off-by: Julia Evans --- Documentation/git-rebase.adoc | 52 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index 956d3048f5a618..bb5a3ff7f82860 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -16,6 +16,32 @@ SYNOPSIS DESCRIPTION ----------- +Transplant a series of commits onto a different starting point. +You can also use `git rebase` to reorder or combine commits: see INTERACTIVE +MODE below for how to do that. + +For example, imagine that you have been working on the `topic` branch in this +history, and you want to "catch up" to the work done on the `master` branch. + +------------ + A---B---C topic + / + D---E---F---G master +------------ + +You want to transplant the commits you made on `topic` since it diverged from +`master` (i.e. A, B, and C), on top of the current `master`. You can do this +by running `git rebase master` while the `topic` branch is checked out. If you +want to rebase `topic` while on another branch, `git rebase master topic` is a +shortcut for `git checkout topic && git rebase master`. + +------------ + A'--B'--C' topic + / + D---E---F---G master +------------ + + If `` is specified, `git rebase` will perform an automatic `git switch ` 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 `` 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 From ad63f69918df0130b6b0236d04e27f8529115cd4 Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Wed, 6 Aug 2025 15:56:08 -0400 Subject: [PATCH 2/5] doc: git rebase: dedup merge conflict discussion Previously there were two explanations, this combines them both into a single explanation. Signed-off-by: Julia Evans --- Documentation/git-rebase.adoc | 49 ++++++++++++++--------------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index bb5a3ff7f82860..e82ceb9cbfcefa 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -42,6 +42,26 @@ shortcut for `git checkout topic && git rebase master`. ------------ +If there is a merge conflict during this process, `git rebase` will stop at the +first problematic commit and leave conflict markers. If this happens, you can do +one of these things: + +1. Resolve the conflict. You can use `git diff` to find the markers (<<<<<<) + and make edits to resolve the conflict. For each file you edit, you need to + tell Git that the conflict has been resolved. You can mark the conflict as + resolved with `git add `. 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 `` is specified, `git rebase` will perform an automatic `git switch ` 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..` 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 `` 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 `` 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 - - -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 ------------ From 7ee6b0afe88fe4f5346776192a0df99c6b64de19 Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Wed, 6 Aug 2025 16:00:37 -0400 Subject: [PATCH 3/5] doc: git rebase: clarify arguments syntax Remove duplicate explanation of `git rebase ` which is already explained above. Signed-off-by: Julia Evans --- Documentation/git-rebase.adoc | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index e82ceb9cbfcefa..6d02648a9b3cee 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -62,11 +62,7 @@ one of these things: git rebase --skip -If `` is specified, `git rebase` will perform an automatic -`git switch ` before doing anything else. Otherwise -it remains on the current branch. - -If `` is not specified, the upstream configured in +If you don't specify an `` to rebase onto, the upstream configured in `branch..remote` and `branch..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 From 4686417b28e4ab386983ad68e4d4d4798a467811 Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Wed, 6 Aug 2025 16:06:01 -0400 Subject: [PATCH 4/5] doc: git-rebase: move --onto explanation down There's a very clear explanation with examples of using --onto which is currently buried in the very long DESCRIPTION section. This moves it to its own section, so that we can reference the explanation from the `--onto` option by name. Signed-off-by: Julia Evans --- Documentation/git-rebase.adoc | 168 ++++++++++++++++++---------------- 1 file changed, 87 insertions(+), 81 deletions(-) diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index 6d02648a9b3cee..d041d87f270b4b 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -114,87 +114,6 @@ will result in: D---E---A'---F master ------------ -Here is how you would transplant a topic branch based on one -branch to another, to pretend that you forked the topic branch -from the latter branch, using `rebase --onto`. - -First let's assume your 'topic' is based on branch 'next'. -For example, a feature developed in 'topic' depends on some -functionality which is found in 'next'. - ------------- - o---o---o---o---o master - \ - o---o---o---o---o next - \ - o---o---o topic ------------- - -We want to make 'topic' forked from branch 'master'; for example, -because the functionality on which 'topic' depends was merged into the -more stable 'master' branch. We want our tree to look like this: - ------------- - o---o---o---o---o master - | \ - | o'--o'--o' topic - \ - o---o---o---o---o next ------------- - -We can get this using the following command: - - git rebase --onto master next topic - - -Another example of --onto option is to rebase part of a -branch. If we have the following situation: - ------------- - H---I---J topicB - / - E---F---G topicA - / - A---B---C---D master ------------- - -then the command - - git rebase --onto master topicA topicB - -would result in: - ------------- - H'--I'--J' topicB - / - | E---F---G topicA - |/ - A---B---C---D master ------------- - -This is useful when topicB does not depend on topicA. - -A range of commits could also be removed with rebase. If we have -the following situation: - ------------- - E---F---G---H---I---J topicA ------------- - -then the command - - git rebase --onto topicA~5 topicA~3 topicA - -would result in the removal of commits F and G: - ------------- - E---H'---I'---J' topicA ------------- - -This is useful if F and G were flawed in some way, or should not be -part of topicA. Note that the argument to `--onto` and the `` -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 `` and ``. 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 `` +parameter can be any valid commit-ish. + + RECOVERING FROM UPSTREAM REBASE ------------------------------- From cb85642bb9df3fcf9792fd18f2dcf448839eae2c Mon Sep 17 00:00:00 2001 From: Julia Evans Date: Wed, 6 Aug 2025 22:21:10 -0400 Subject: [PATCH 5/5] doc: git-rebase: update discussion of internals - make it clearer that we're talking about a multistep process - give a more technically accurate description how rebase works with the merge backend. - condense the explanation of how git rebase skips commits with the same textual changes into a single bullet point and remove the explanatory diagram. Lots of things which are more complicated are already being explained without a diagram. - remove the explanation of how exactly `--fork-point` and `--root` work since that information is in the OPTIONS section - put all discussion of `ORIG_HEAD` inside the note Signed-off-by: Julia Evans --- Documentation/git-rebase.adoc | 61 +++++++++++------------------------ 1 file changed, 18 insertions(+), 43 deletions(-) diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc index d041d87f270b4b..2a44f8a0cedaa6 100644 --- a/Documentation/git-rebase.adoc +++ b/Documentation/git-rebase.adoc @@ -68,51 +68,26 @@ linkgit:git-config[1] for details) and the `--fork-point` option is assumed. If you are currently not on any branch or if the current branch does not have a configured upstream, the rebase will abort. -All changes made by commits in the current branch but that are not -in `` are saved to a temporary area. This is the same set -of commits that would be shown by `git log ..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 `` or `` if the -`--onto` option was supplied. This has the exact same effect as -`git reset --hard ` (or ``). `ORIG_HEAD` is set -to point at the tip of the branch before the reset. +Here is a simplified description of what `git rebase ` does: + +1. Make a list of all commits on your current branch since it branched + off from `` that do not have an equivalent commit in + ``. +2. Check out `` with the equivalent of + `git checkout --detach `. +3. Replay the commits, one by one, in order. This is similar to running + `git cherry-pick ` 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 `. [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..` 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 ------------