Git: Modifying Previous Commits with Fixup
Scenario: Amending a Commit in the Middle of Your History
If you've already made several commits and realize you need to modify a file in an earlier commit, you can use git commit --fixup combined with an interactive rebase.
Example History:
abc1234 feat: add configuration system
def5678 feat: add monitoring setup ← you want to modify this one
ghi9012 chore: update documentation
jkl3456 feat: add new feature (HEAD)
Steps:
-
Make your changes to the file:
Edit the file you want to modify:
nano your-file.txt -
Stage the changes:
git add your-file.txt -
Create a fixup commit:
git commit --fixup <commit-hash>Example:
git commit --fixup def5678This creates a new commit with the message
fixup! feat: add monitoring setup. -
View your current history:
git log --onelineYou'll see something like:
mno7890 fixup! feat: add monitoring setup
jkl3456 feat: add new feature
ghi9012 chore: update documentation
def5678 feat: add monitoring setup
abc1234 feat: add configuration system -
Perform an interactive rebase with autosquash:
git rebase -i --autosquash <parent-commit>The
<parent-commit>is the commit before the one you want to modify:git rebase -i --autosquash abc1234Alternative: Use
HEAD~4to rebase the last 4 commits:git rebase -i --autosquash HEAD~4 -
Git will automatically arrange the commits:
The editor will open showing:
pick def5678 feat: add monitoring setup
fixup mno7890 fixup! feat: add monitoring setup
pick ghi9012 chore: update documentation
pick jkl3456 feat: add new featureNotice that:
- The
fixup!commit is placed right after the original commit - It's already set to
fixup(notpick)
- The
-
Save and close the editor:
Git will automatically merge the fixup commit into the original commit.
-
Verify the result:
git log --onelineYou should now see a clean history without the fixup commit:
pqr4567 feat: add new feature
stu8901 chore: update documentation
vwx2345 feat: add monitoring setup ← your changes are here
abc1234 feat: add configuration system -
Push the updated branch (if already pushed):
Since you've rewritten history, you need to force push:
git push --force-with-lease origin <branch-name>
Important Notes:
- Parent Commit: When using
git rebase -i, always specify the commit before the one you want to modify - Commit Hashes Change: After rebasing, all affected commits will have new hashes
- Force Push Warning: Only use
--force-with-leaseon branches where you're the sole contributor, or coordinate with your team first - Autosquash: The
--autosquashflag automatically arranges fixup commits correctly
Tips:
Enable autosquash by default:
git config --global rebase.autosquash true
Then you can simply run:
git rebase -i abc1234
Multiple fixups for the same commit:
You can create multiple fixup commits for the same original commit. They will all be squashed together during rebase.
Fixup vs. Squash:
--fixup: Merges changes without prompting for a new commit message--squash: Merges changes but allows you to edit the commit message
Example with squash:
git commit --squash def5678