Editing a commit allows you to make changes to an existing commit which includes editing the subject, body, and associated files. Even better, editing a commit allows you to break up a large commit into smaller commits which allows you to reverse a Git Rebase Fixup and/or Git Rebase Squash if necessary.
That said — and as a rule of thumb — you are better off creating smaller commits that you fixup and/or squash into other commits rather than split a large commit into smaller commits via Git Rebase Edit. The reason is that splitting apart a larger commit can be more time consuming than fixing and/or squashing. Not to mention an increased chance of merge conflicts. This is especially true when a commit isn’t atomic as discussed in the Git Commit Anatomy article or an entire ball of mess which is usually due to bad — and abusive — Git Rebase Squash practices.
Workflow
Now that you’ve got a sense of what editing a commit means, let’s learn how to apply this in practice. We can start by creating a Git repository for demonstration purposes:
mkdir demo
cd demo
git init
Next, we can add a few commits:
# First.
printf "%s\n" "3.4.3" > .ruby-version
git add .
git commit --message "Added Ruby version" \
--message "Necessary specify the version of Ruby used."
# Second.
printf "%s\n\n" "# frozen_string_literal: true" > calc.rb
printf "%s\n" 'puts "TODO...' >> calc.rb
printf "%s\n\n" "# 0.0.0 ($(date +%Y-%m-%d))" > CHANGES.adoc
printf "%s\n" "Initial version." >> CHANGES.adoc
git add .
git commit --message "Added calculator implementation" \
--message "Necessary for basic addition."
# Third.
printf "%s\n\n" "= Demo" > README.adoc
printf "%s\n\n" "Welcome! This is a simple project for adding numbers." >> README.adoc
git add .
git commit --message "Added project documentation" \
--message "Explains what the project is, why it is useful, and how to use it."
At this point you should have three commits in your newly created repository. This can be confirmed by running the following:
git log --oneline
The result should look like this:
58799bb484e5 (HEAD -> main) Added project documentation a7e52b82517c Added calculator implementation e47441cc2b33 Added Ruby version
Unfortunately, there are a couple of problems with this implementation:
-
We didn’t provide a proper implementation for adding two numbers when we committed the
calc.rbfile. -
We didn’t make an atomic commit because our change log (i.e.
CHANGES.adoc) is not related to the work in ourcalc.rbfile. That should be a separate commit.
We’ll start by addressing the first issue by editing the problematic commit. If you are thinking: "Hey, wait, can’t I fixup the first commit instead?" Normally, you’d be correct but we also need to edit the commit message to make it more clear so editing the commit as a single operation will save us time. You might have also noticed that we can’t amend the commit since the commit is the second out of three. This is another reason why being able to edit a commit is useful because you can go back in time and target specific commits.
⚠️ Please note that we’ll be rebasing our main (default) branch. In practice, Git Rebase should only be performed on a feature branch but since this repository isn’t shared with anyone, we can rebase without harming our team. By this way, this is a powerful — and encouraged — workflow to use before sharing your project with others in order to keep your Git history clean.
OK, let’s make our first edit by interactive rebasing to our root commit (i.e. first commit):
git rebase --interactive --root
You should now see the following in your Git Rebase Editor (this also assumes you have Git Rebase Abbreviations enabled):
p e47441cc2b33 Added Ruby version p a7e52b82517c Added calculator implementation p 58799bb484e5 Added project documentation
We only need to inform Git that we want to edit the second commit, like this:
p e47441cc2b33 Added Ruby version e a7e52b82517c Added calculator implementation p 58799bb484e5 Added project documentation
Great, now save and exit to continue the rebase. At this point, you should see the following in your console:
Stopped at a7e52b82517c... Added calculator implementation You can amend the commit now, with git commit --amend '-S' Once you are satisfied with your changes, run git rebase --continue
Git is being helpful by giving you hints on how to edit and finish (continue) the rebase once you are done editing. In this case, we’re going to amend the commit. Please note that the -S flag is for signing your commit but if you automatically have Git configured via your global Git Configuration then, kudos, you can ignore -S. 🎉
💡 Should you forget where you are in the rebase process, you can always use git rebase --show-current-patch to see what you are working on in terms of commit message and associated changes.
First, let’s fix our commit by providing an implementation:
printf "%s\n" 'ARGV.then { |a, b| puts "#{a} plus #{b} equals #{a.to_i + b.to_i}." }' > calc.rb
…and we can confirm the implementation works as follows:
ruby calc.rb 1 2
# 1 plus 2 equals 3.
Now we can apply our changes by amending our commit:
git commit --amend --all
You should see the following in your Git Rebase Editor:
Added calculator implementation Necessary for basic addition.
We can modify the commit message so it looks like this:
Added calculator implementation Necessary to perform basic addition. Usage: `ruby calc.rb <number> <number>`.
Now you can save and exit your Git Rebase Editor. You are still in the middle of the rebase, though, so you’ll need to instruct Git to finish the rebase as follows:
git rebase --continue
You can confirm all changes are applied by running:
git log --oneline
git show "<sha>"
The <sha> would be the SHA of the "Added calculator implementation" commit which should look like the following:
commit ae3c1635b4bcb1e9c67dab9dc1d29ef2006cd6cc
Author: Brooke Kuhlmann <brooke@demo.io>
Date: Fri May 9 10:42:14 2025 -0600
Added calculator implementation
Necessary to perform basic addition. Usage: `ruby calc.rb <number> <number>`.
added: CHANGES.adoc
# 0.0.0 (2025-05-09)
Initial version.
added: calc.rb
ARGV.then { |a, b| puts "#{a} plus #{b} equals #{a.to_i + b.to_i}." }
Perfect, we’ve solved the first issue by making changes to our calculator implementation but we still have a problem with CHANGES.adoc being included which we definitely don’t want since the commit isn’t atomic. To fix, we’ll rebase to edit our commit one last time by splitting the changes into two commits.
💡 Ideally, we should have performed all of these operations during the first rebase but I split this out into two rebases to better highlight the different ways you can edit commits.
Once again, we can kick off the process by interactively rebasing:
git rebase --interactive --root
You’ll also want to edit the same commit again which should like this in your Git Rebase Editor:
p e47441cc2b33 Added Ruby version e ae3c1635b4bc Added calculator implementation p ece41e951fad Added project documentation
Now, when you save and exit, you’ll be back at this prompt:
Stopped at ae3c1635b4bc... Added calculator implementation You can amend the commit now, with git commit --amend '-S' Once you are satisfied with your changes, run git rebase --continue
For this situation we don’t want to amend at all. We need to split the commit in two by using a soft reset to undo the commit and unstage both files:
git reset --soft HEAD^
git reset
The above should yield the following in your console:
## HEAD (no branch) ?? CHANGES.adoc ?? calc.rb
This is one of the greatest powers of editing a commit because we’ve made our original commit "Added calculator implementation" go away and unstaged both the CHANGES.adoc and calc.rb files so we can commit them as separate files! We’ll start with calc.rb as follows:
git add calc.rb
git commit --message "Added calculator implementation" \
--message "Necessary to perform basic addition. Usage: ruby calc.rb <number> <number>."
Next, we can commit CHANGES.adoc:
git add CHANGES.adoc
git commit --message "Added version history documentation" \
--message "Necessary to detail each version release."
Finally, we can finish the rebase and inspect our history:
git rebase --continue
git log --oneline
# 0f906855bd67 (HEAD -> main) Added project documentation
# a6b61fb9c306 Added version history documentation
# 6d35b40022cd Added calculator implementation
# e47441cc2b33 Added Ruby version
Notice we have four commits in our history with two newly atomic commits:
-
Added calculator implementation (i.e.
calc.rb) -
Added version history documentation (i.e.
CHANGES.adoc)
Much better and our Git history is cleaner because of this.
Conclusion
Here’s what I love about editing commits:
-
Only requires a single interactive rebase.
-
Can quickly modify the original implementation and commit message while erasing all mistakes.
-
Can split large commits into smaller commits for improved readability and understanding.
-
Reviewers (and your future self) will have a high signal to noise when providing feedback.
-
Our implementation looks as if it was crafted perfectly the first time.
May your Git commit messages be a joy to read, learn from, and inspiration for others. Enjoy!