I have created a commit in my local Git repository that includes a functional change and a refactoring. In retrospect, it would have been better if I had created a separate commit for the refactoring: The refactoring was a rename, and hence caused diffs in many files. Between all these rename diffs, it is hard to see the functional changes. This e.g. makes a code review harder than it needs to be.
So, is there an easy way to fix this? I.e. is it possible to split the commit into a refactoring commit and a commit with the functional changes?
I tried to split the commit through a manual triage of the diffs - as proposed in the answers to Break a previous commit into multiple commits - but this was really tedious. Isn't there an easier way?
Yes, there is an easy way - assuming that you can easily repeat the refactoring. The approach is to create a commit with only the refactoring, and then "subtract" it from the mixed commit.
You can do this in the following way:
git branch
. For the remaining steps, we'll assume that you start on branch master
git branch backup
git checkout HEAD^
git add --all && git commit
Create the commit that contains the remaining changes by "subtracting" the refactoring commit from the mixed commit:
git reset --hard master
git reset --soft HEAD@{1}
git commit -c HEAD@{1}
git branch -f master
git checkout master
(Optional) Verify that the two new commits in fact contain the same modifications: git diff backup
should show no diffs.
git reset --hard backup
) and start over. Otherwise, delete the backput branch: git branch -D backup