Git Advanced: History, Workflows and Automation
Interactive Rebase and Clean History
In this lesson you will
- Reorder, squash and reword commits with interactive rebase
- Use fixup commits to tidy work as you go
- Know the limits and risks of rewriting history
Introduction
While you work, commits often look like "wip", "fix typo", "oops". Before others review your branch, you can turn this into a clean series where each commit tells one clear step. Interactive rebase is the tool.
This applies only to commits you have not shared, or on a branch only you use.
The simple explanation
Interactive rebase lets you edit a list of your recent commits, then replays them as you instructed.
Starting it
To edit the last four commits:
Terminal
git rebase -i HEAD~4Git opens your editor with a list, oldest first:
pick a1b2c3d Add login form
pick e4f5a6b wip
pick 7c8d9e0 Fix typo in login form
pick 1a2b3c4 Add validationChange the word at the start of a line to tell Git what to do:
| Command | What it does |
|---|---|
pick | Keep the commit as it is |
reword | Keep the changes, edit the message |
edit | Pause so you can change the commit |
squash | Merge into the previous commit, and combine messages |
fixup | Merge into the previous commit, and discard its message |
drop | Remove the commit |
You can also reorder by moving lines. For the list above, you might turn the second and third lines into fixup, so everything folds into "Add login form".
Quick quiz
You want to merge a small typo-fix commit into the commit before it and discard its message. Which command do you use?
Save and close the editor. Git replays the commits. If a conflict appears, fix it, run git add, then git rebase --continue. To abandon, run git rebase --abort.
Fixup commits as you work
You can plan the cleanup in advance. When you spot a mistake in an earlier commit, make a fixup commit that points at it:
Terminal
git commit --fixup a1b2c3dLater, tidy everything automatically:
Terminal
git rebase -i --autosquash mainGit arranges the fixup commits next to their targets and marks them fixup, so you only need to save the list.
Splitting a commit
Mark the commit edit. When the rebase pauses, undo the commit but keep the changes, then commit in parts:
Terminal
git reset HEAD~1
git add -p # choose pieces of changes to stage
git commit -m "First part"
git add .
git commit -m "Second part"
git rebase --continuegit add -p lets you stage individual chunks of a file.
Rules and risks
- Rewriting makes new commits with new hashes. Never do it to commits others already have.
- After rewriting a branch you already pushed, you need a force push. Use
git push --force-with-lease, and only for your own branch. - Make a safety copy first if you are nervous:
git branch backup. - If it goes wrong,
git reflogcan usually get you back.
A good commit
- Does one logical thing
- Has a short, clear message in the imperative mood: "Add login form"
- Leaves the project in a working state, so tools like bisect can use it
Try it yourself
On a practice branch, make four small commits including a "wip" and a "typo". Run git rebase -i HEAD~4, squash them into two clean commits with good messages, and check git log --oneline.
Summary
git rebase -ilets you pick, reword, squash, fixup, reorder and drop commits.git commit --fixupwith--autosquashtidies as you go.- Rewrite only unshared history, and keep
reflogand a backup branch as safety nets.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading