git rebase --interactive
is the command you want.
Example:
The current status is this:
bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git status
On branch master
nothing to commit, working tree clean
bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git log --oneline
a6e3c6a (HEAD -> master) Fourth commit
9a24b81 Third commit
7bdfb68 Second commit
186d1e0 First commit
I want to reorder commits 9a24b81
(Third commit) and 7bdfb68
(Second commit). To do this, I first find the commit before the first commit we want to change. This is commit 186d1e0
(First commit).
The command to execute is git rebase --interactive COMMIT-BEFORE-FIRST-COMMIT-WE-WANT-TO-CHANGE
, in this case:
bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git rebase --interactive 186d1e0
This opens up a file in the default editor with the following contents:
pick 7bdfb68 Second commit
pick 9a24b81 Third commit
pick a6e3c6a Fourth commit
# Rebase 186d1e0..a6e3c6a onto 186d1e0 (3 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
Note that the ordering of commits in the file is opposite the one used for git log. In git log, the most recent commit is at the top. In this file, the most recent commit is at the bottom.
As the comment at the bottom of the file explains there are various things I can do, like squashing, dropping and reordering commits. To re-order commits, I edit the file so it looks like this (the bottom comments not displayed):
pick 9a24b81 Third commit
pick 7bdfb68 Second commit
pick a6e3c6a Fourth commit
The pick
command at the start of each line means "use (i.e. include) this commit" and when I save the file containing the rebase commands and exit the editor, git will execute the commands and update the repository and working directory:
$ git rebase --interactive 186d1e0
Successfully rebased and updated refs/heads/master.
bernt@le3180:~/src/stackoverflow/reordering_of_commits
$ git log --oneline
ba48fc9 (HEAD -> master) Fourth commit
119639c Second commit
9716581 Third commit
186d1e0 First commit
Note the rewritten commit history.
Links: