Quick 4 am blog on something I learned today.
Scenario
Let’s say you have 7 commits in your branch with a pull request open.
Someone reviewed your PR and found an issue in the 3rd commit’s files. Turns out you were testing if your secret token works for the backdoor you were programming into the CAAIA. What a noob move but a human error, happens to everyone.
You left that secret token in one of those files and committed it. You might have fixed it later when you saw it or it got left behind in the commit history.
How to fix it?
What are your options.
- Destructive rewrite – You can perform an interactive rebase and drop (or delete) the 3rd commit if the other changes weren’t important and could be sacrificed.
- Surgery – What if you could rewrite the history and make it so that files committed never had the token in the first place. Here’s what you could do in that scenario.
Enter, interactive edits
Assuming you know your way around, git rebase. You start with an interactive rebase as you always do.
git rebase -i HEAD^7
# You can replace 7 with however many commits you want to rebase over
In the editor that popped up, swap p
or pick for the commit you want to change to
`e` or edit. This will checkout your selected commit from your branch and bring the workspace to the point when the commit in question had already been committed.
In our scenario, we will be editing the 3rd commit since that’s where we committed the token into the files. Now, there are several ways of doing this but I especially like making changes to the committed file by unstaging everything using.
git reset @~
This will reset the commit & unstage all files part of the commit. What next? You make changes to your files. Restore, delete or even add new files. After your surgery of git history is complete, let’s stitch it all back up with a
git add files/you/want/to/commit
git commit --amend --no-edit
After you stage the file to be committed, this will commit all the files back in the same commit having the same message. You can choose to change the commit message as well by committing without using the --no-edit
flag. If you intend to create a new commit. Then go for using git commit -m "NEW COMMIT MESSAGE"
After the changes have been committed, finish the work:
git rebase --continue
for interactive rebase to go over the remaining commands and finish rebasing.
Voila! Surgery Complete
If you followed all that correctly you will get the same commit tree as before but on a force push to your pull request you will find the third commit will have no mention of the secret token anymore. Your backdoor is fully secure again.
Bonus: Going faster with changes requested
Now, you have pushed your branch but someone has requested new changes to be done to your PR but those changes don’t need a new commit then what you would do? Here’s what I like to do in that case in the past and now.
Past:
git add . # stage the changes made on HEAD git commit -m "NEW COMMIT" git rebase -i HEAD^2 # fixup the commits and complete rebase
Result: New changes committed into the last commit without an extra commit.
Now:
git add . git commit --amend --no-edit
This will commit all the files in the directory back into the same commit.
Result: New changes committed into the last commit without an extra commit.
That’s it for now, live in the mix.