Rebase by dragging
Take a branch of eight "wip" commits and turn it into three that explain themselves. You will reorder commits by dragging them, squash fixups into the commit they fix, reword messages and drop a commit you no longer need, all in one sheet, then start the rebase and handle the one place it stops.
Open the sheet
There are three ways in, and they all open the same "Interactive rebase" sheet.
- In History, right-click the oldest commit you want to change and choose "Interactive rebase from here…". The plan includes that commit and everything after it on your branch.
- Right-click a branch in the sidebar and choose "Interactive rebase onto…" to replay your branch on top of it, editing as you go.
- Press ⌘K and type the branch or commit; the same two commands are in the palette.
The sheet's first line tells you the scope: "8 commits on feat/search after main, oldest first. Drag to reorder; squash and fixup join the commit above."
Make the plan
- Drag a row by its grip to move it. Alternatively select a row and press ⌥↑ or ⌥↓. Order is oldest first, so the top row is applied first.
- Change a row's action with its menu, or press a letter with the row selected: p pick, r reword, s squash, f fixup, d drop, e edit.
- To fold a "fix typo" commit into the commit it fixes, drag it directly under that commit and mark it fixup. Its changes join the commit above and its message is discarded. Use squash instead when you want to keep or combine the messages; a field appears for the result, and leaving it empty combines both messages.
- Mark a commit reword and type its new message in the field that opens under the row.
- Mark a commit drop to leave it out of the rewritten branch, and edit to have the rebase pause there so you can change the files.
- When the plan differs from the original order and actions, "Start rebase" turns on. Click it.
The sheet guards against plans Git would refuse. The first row cannot be squash or fixup, because there is no commit above it to join, and you cannot drop every commit. If a guard is on, the sheet says why.
While it runs
The button reads "Rebasing…" and a banner appears across the top of the views: "Rebasing onto main, step 3 of 8: Add the search index". Most rebases finish in a second or two and History redraws with the new commits.
Two things can stop it.
You chose edit. The rebase pauses at that commit with a toast: "Stopped to edit a1b2c3d. Change what you need, then continue." Make your changes, stage them in ⌘1, then press "Continue rebase" in the banner. When Git needs a message to go on, as it does for a squash, a small sheet shows it for editing; ⌘⏎ confirms.
Two commits conflict. Reordering can put a change before the change it depended on. The banner reads "2 files still have conflicts." with Show conflicts, Skip and Abort. Resolve them as Resolve merge conflicts describes, then Continue rebase. Skip drops the commit that conflicts and carries on; Abort puts the branch back exactly as it was, and the toast says so: "Aborted the rebase. Everything is as it was."
Check the result
Press ⌘2. The branch now has the commits you planned, with new hashes. Click each to read its diff in the inspector and confirm the squashes landed where you meant. If you had already pushed the branch, the next push needs to replace the remote's history; Mergepond runs a plain git push, so do that from Terminal with git push --force-with-lease once you are sure.
Get more from it
- Rebase before you open a pull request, not after review has started. Reviewers lose their place when the commits under their comments change.
- Fixup commits as you go. A commit named "fixup: tests" dragged under "Add tests" and marked fixup takes two seconds, where editing history by hand takes ten minutes.
- For a one-commit tidy, "Amend" in the Changes view is quicker than a rebase. See Stage and commit precisely.
- The plan is yours until you click "Start rebase". Press Esc to throw it away and nothing has happened to the branch.