Merge branch 'je/doc-rebase'

Documentation for "git rebase" has been updated.

* je/doc-rebase:
  doc: git-rebase: update discussion of internals
  doc: git-rebase: move --onto explanation down
  doc: git rebase: clarify arguments syntax
  doc: git rebase: dedup merge conflict discussion
  doc: git-rebase: start with an example
This commit is contained in:
Junio C Hamano
2025-08-28 11:28:57 -07:00

View File

@@ -16,49 +16,12 @@ SYNOPSIS
DESCRIPTION
-----------
If `<branch>` is specified, `git rebase` will perform an automatic
`git switch <branch>` before doing anything else. Otherwise
it remains on the current branch.
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.
If `<upstream>` is not specified, 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
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.
[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).
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.
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
@@ -66,13 +29,11 @@ Assume the following history exists and the current branch is "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:
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
@@ -80,30 +41,56 @@ would be:
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
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):
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:
------------
A---B---C topic
/
D---E---A'---F master
------------
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
will result in:
git rebase --continue
------------
B'---C' topic
/
D---E---A'---F master
------------
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 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
branch does not have a configured upstream, the rebase will abort.
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]
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
----------------------------------------
Here is how you would transplant a topic branch based on one
branch to another, to pretend that you forked the topic branch
@@ -186,28 +173,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
------------
@@ -253,6 +218,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