Rebasing interactively means that you have a chance to edit the
commits which are rebased. You can reorder the commits, and you
can remove them (weeding out bad or otherwise unwanted patches).
The interactive mode is meant for this type of workflow:
1. have a wonderful idea
2. hack on the code
3. prepare a series for submission
4. submit
where point 2. consists of several instances of
a) regular use
1. finish something worthy of a commit
2. commit
b) independent fixup
1. realize that something does not work
2. fix that
3. commit it
Sometimes the thing fixed in b.2. cannot be amended to the
not-quite perfect commit it fixes, because that commit is buried
deeply in a patch series. That is exactly what interactive rebase
is for: use it after plenty of "a"s and "b"s, by rearranging and
editing commits, and squashing multiple commits into one.
Start it with the last commit you want to retain as-is:
git rebase -i <after-this-commit>
An editor will be fired up with all the commits in your current
branch (ignoring merge commits), which come after the given
commit. You can reorder the commits in this list to your heart's
content, and you can remove them. The list looks more or less
like this:
pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...
The oneline descriptions are purely for your pleasure; git rebase
will not look at them but at the commit names ("deadbee" and
"fa1afe1" in this example), so do not delete or edit the names.
By replacing the command "pick" with the command "edit", you can
tell git rebase to stop after applying that commit, so that you
can edit the files and/or the commit message, amend the commit,
and continue rebasing.
To interrupt the rebase (just like an "edit" command would do,
but without cherry-picking any commit first), use the "break"
command.
If you just want to edit the commit message for a commit, replace
the command "pick" with the command "reword".
To drop a commit, replace the command "pick" with "drop", or just
delete the matching line.
If you want to fold two or more commits into one, replace the
command "pick" for the second and subsequent commits with
"squash" or "fixup". If the commits had different authors, the
folded commit will be attributed to the author of the first
commit. The suggested commit message for the folded commit is the
concatenation of the first commit's message with those identified
by "squash" commands, omitting the messages of commits identified
by "fixup" commands, unless "fixup -c" is used. In that case the
suggested commit message is only the message of the "fixup -c"
commit, and an editor is opened allowing you to edit the message.
The contents (patch) of the "fixup -c" commit are still
incorporated into the folded commit. If there is more than one
"fixup -c" commit, the message from the final one is used. You
can also use "fixup -C" to get the same behavior as "fixup -c"
except without opening an editor.
git rebase will stop when "pick" has been replaced with "edit" or
when a command fails due to merge errors. When you are done
editing and/or resolving conflicts you can continue with git
rebase --continue
.
For example, if you want to reorder the last 5 commits, such that
what was HEAD~4 becomes the new HEAD. To achieve that, you would
call git rebase like this:
$ git rebase -i HEAD~5
And move the first patch to the end of the list.
You might want to recreate merge commits, e.g. if you have a
history like this:
X
\
A---M---B
/
---o---O---P---Q
Suppose you want to rebase the side branch starting at "A" to
"Q". Make sure that the current HEAD is "B", and call
$ git rebase -i -r --onto Q O
Reordering and editing commits usually creates untested
intermediate steps. You may want to check that your history
editing did not break anything by running a test, or at least
recompiling at intermediate points in history by using the "exec"
command (shortcut "x"). You may do so by creating a todo list
like this one:
pick deadbee Implement feature XXX
fixup f1a5c00 Fix to feature XXX
exec make
pick c0ffeee The oneline of the next commit
edit deadbab The oneline of the commit after
exec cd subdir; make test
...
The interactive rebase will stop when a command fails (i.e. exits
with non-0 status) to give you an opportunity to fix the problem.
You can continue with git rebase --continue
.
The "exec" command launches the command in a shell (the one
specified in $SHELL
, or the default shell if $SHELL
is not set),
so you can use shell features (like "cd", ">", ";" ...). The
command is run from the root of the working tree.
$ git rebase -i --exec "make test"
This command lets you check that intermediate commits are
compilable. The todo list becomes like that:
pick 5928aea one
exec make test
pick 04d0fda two
exec make test
pick ba46169 three
exec make test
pick f4593f9 four
exec make test