Guides: Changing a series of commits or patches.
So, you’ve cloned a repository, and hacked away at it; separated it into logical chunks, and it’s now ready to submit!
So you send your patch series, or publish your branch, and ask for a pull, but a quick review reveals that there are some errors in these patches!
Now, the maintainer may send these patches back to you, and ask you to fix these, this guide shows several ways on how this can be accomplished1.
Before you start, make sure you have a clean working tree (i.e. no modified files).
Using rebase -i
This is the most general (and easiest) way to edit history.
Invocation
The syntax is:
git rebase -i
For example:
git rebase -i master
This will then take you into your $EDITOR with a file that looks like this:
pick 2394755 FocusedTextEdit: Removed the textCursor function. pick 36369cd Remove Focused* classes in focusedwidgets. pick 3064f94 FocusedTextEdit: Remove the clipboard handling. pick b4d39e3 FocusedTextEdit: Removed the createPopupMenu function. pick 8c0a5eb FocusedTextEdit: fixed constructor. pick 2ea70f5 FocusedEdit: Rewrote wheelEvent to work with the new QAbstractScrollArea
- Rebase 96ded8d..2ea70f5 onto 96ded8d
#- Commands:
- pick = use commit
- edit = use commit, but stop for amending
- squash = use commit, but meld into previous commit
#- If you remove a line here THAT COMMIT WILL BE LOST.
- However, if you remove everything, the rebase will be aborted.
#
If you change the order of the lines, the commits will be re-ordered. We want to edit a patch, so we mark the commits we want to change as “edit”, and if we want to combine two commits, we mark them as squash2.
pick 2394755 FocusedTextEdit: Removed the textCursor function.
pick 36369cd Remove Focused* classes in focusedwidgets.
edit 3064f94 FocusedTextEdit: Remove the clipboard handling.
squash b4d39e3 FocusedTextEdit: Removed the createPopupMenu function.
edit 8c0a5eb FocusedTextEdit: fixed constructor.
pick 2ea70f5 FocusedEdit: Rewrote wheelEvent to work with the new QAbstractScrollArea
Note: “squash” means squash with the commit above it.
Editing and splitting commits
To edit or split commits:
- Mark the commit as “edit”
- Close your editor (the rebase will begin)
- When rebase reaches a commit marked “edit”, it will stop with a message like this:
Rebasing (3/6)
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
- Make your changes to the commit, or split the commits
- add them, and commit with git commit —amend (or use git-gui)
- type git rebase —continue
Addendum on splitting commits
I have personally found that the easiest way to split commits is to use “git-gui”.
(I should put up a screencast of this)
- Open up git gui
- Click “Amend to last commit”
- Remove all the files from the commit
- Click on a file you want to add
- Right click on the part you want to add in the diff view
- Click “stage hunk for commit”
- Repeat for each hunk you want to commit
- Write a commit message and commit
- Go to step 3, and repeat until you’ve re-added everything
Example: squashing “fix” commits.
If your workflow is anything like mine, you’ll find that you’ll find several errors in your commits that you haven’t published yet.
In that case, I create a series of fix commits; say I have three commits, Patch A, Patch B, and Patch C; and I see an error in patches A and B:
$ edit file1
$ git add file1
$ git commit -m "Fix for Patch A"
$ edit file2
$ git add file2
$ git commit -m "Fix for Patch B"
$ git rebase -i master
This will take me to my text editor with the following file:
pick aaaaaa Patch A
pick bbbbbb Patch B
pick cccccc Patch C
pick faaaaa Fix for Patch A
pick fbbbbb Fix for Patch B
To squash these fixes into your patches A and B (so it looks like you’ve never made the mistake in the first place!), change the file to look like this:
pick aaaaaa Patch A
squash faaaaa Fix for Patch A
pick bbbbbb Patch B
squash fbbbbb Fix for Patch B
pick cccccc Patch C
When rebase —interactive hits a “squash” item, it will send you to your editor to change the commit message (generally, you just have to remove the second commit message)
Now you can format your patches again and send them upstream!
Footnotes
1 If others have branched off of the work you have doing, do not modify any of the commits. The rule in Git is that if you have work that people are working off of, you will make it hell for them if you change it. Rebasing and amending are only for commits where you know no one is working off of.
2 In the upcoming 1.5.6, there will be new rebase -i commands “tag”, “merge”, and “reset”, as well.

