Home Explore Blog CI



git

15th chunk of `Documentation/git-rebase.adoc`
b3306cf23fd89110243f5e82f9e62c9dec54cf1bbb93e7fd0000000100000ad8
 from the todo list, as the developer may have merged the
then-current `master` while working on the branch, only to rebase
all the commits onto `master` eventually (skipping the merge
commits).

However, there are legitimate reasons why a developer may want to
recreate merge commits: to keep the branch structure (or "commit
topology") when working on multiple, inter-related branches.

In the following example, the developer works on a topic branch that
refactors the way buttons are defined, and on another topic branch
that uses that refactoring to implement a "Report a bug" button. The
output of `git log --graph --format=%s -5` may look like this:

------------
*   Merge branch 'report-a-bug'
|\
| * Add the feedback button
* | Merge branch 'refactor-button'
|\ \
| |/
| * Use the Button class for all buttons
| * Extract a generic Button class from the DownloadButton one
------------

The developer might want to rebase those commits to a newer `master`
while keeping the branch topology, for example when the first topic
branch is expected to be integrated into `master` much earlier than the
second one, say, to resolve merge conflicts with changes to the
DownloadButton class that made it into `master`.

This rebase can be performed using the `--rebase-merges` option.
It will generate a todo list looking like this:

------------
label onto

# Branch: refactor-button
reset onto
pick 123456 Extract a generic Button class from the DownloadButton one
pick 654321 Use the Button class for all buttons
label refactor-button

# Branch: report-a-bug
reset refactor-button # Use the Button class for all buttons
pick abcdef Add the feedback button
label report-a-bug

reset onto
merge -C a1b2c3 refactor-button # Merge 'refactor-button'
merge -C 6f5e4d report-a-bug # Merge 'report-a-bug'
------------

In contrast to a regular interactive rebase, there are `label`, `reset`
and `merge` commands in addition to `pick` ones.

The `label` command associates a label with the current HEAD when that
command is executed. These labels are created as worktree-local refs
(`refs/rewritten/<label>`) that will be deleted when the rebase
finishes. That way, rebase operations in multiple worktrees linked to
the same repository do not interfere with one another. If the `label`
command fails, it is rescheduled immediately, with a helpful message how
to proceed.

The `reset` command resets the HEAD, index and worktree to the specified
revision. It is similar to an `exec git reset --hard <label>`, but
refuses to overwrite untracked files. If the `reset` command fails, it is
rescheduled immediately, with a helpful message how to edit the todo list
(this typically happens when a `reset` command was inserted into the todo
list manually and contains a typo).

The `merge`

Title: Rebasing Merges with --rebase-merges Option
Summary
This section explains how to rebase commits while preserving the branch structure, including merge commits, using the `--rebase-merges` option, which generates a todo list with `label`, `reset`, and `merge` commands in addition to `pick` commands, allowing developers to recreate merge commits and maintain the commit topology when working on multiple inter-related branches.