Adam K Dean

Rewriting History in Git

Published on 21 January 2020 at 09:43 by Adam

Sometimes, there may be situations where you or a colleague of yours is in a rush, perhaps something bad happened in production and a quick patch is needed, or, in the case of a few days ago, a couple of syntax errors brought a halt to a few monitoring services.

An esteemed colleague of mine found themselves in this situation recently, having made some changes to one of our Prometheus services, but unfortunately introduced a slight syntax error which brought it down. In the rush of getting a fix out, a couple of commit messages simply became fix, which was definitely not the standard format.

After making some changes to the repository this morning, to my horror, I noticed the commit messages, something I hold sacred.

* 2297d22 feat: example commit message (Adam K Dean, 10 minutes ago)
* 6feeed4 fix (Esteemed Colleague, 2 days ago)
* 87cad2f fix (Esteemed Colleague, 2 days ago)
* 5c86540 fix: remove trailing , (Esteemed Colleague, 2 days ago)
* cbe8235 chore: last release commit (Adam K Dean, 2 months ago)

But there is no need to worry. There are ways of fixing issues like this. If the repository is used by a lot of people, and is very busy, then this approach won't work, but for smaller, less visited repositories, such as misc system services rarely changed, we can safely rewrite history.

The first thing we want to do is backup the branch:

$ git checkout -b hold-this-for-me

Next we reset the branch back to the last acceptable commit:

$ git reset --hard cbe8235

Then, we go through the commits from oldest to newest, cherry picking them and amending their commit messages as necessary:

$ git cherry-pick 5c86540
$ git commit --amend -m "fix: remove trailing comma"
$ git cherry-pick 87cad2f
$ git commit --amend -m "fix: add missing bracket"
$ git cherry-pick 6feeed4
$ git commit --amend -m "fix: remove the bit that breaks everything"
$ git cherry-pick 2297d22

Notice that the last commit we cherry-pick was ours, so we don't need to amend it. Now we should have a tidier commit history:

* 8649516 feat: add nodeexporter deploy (Adam K Dean, 10 minutes ago)
* b6cac88 fix: remove the bit that breaks everything (Esteemed Colleague, 2 days ago)
* 8322e9a fix: add missing bracket (Esteemed Colleague, 2 days ago)
* 007bbe0 fix: remove trailing comma (Esteemed Colleague, 2 days ago)
* cbe8235 chore: last release commit (Adam K Dean, 2 months ago)

We can now proceed to push this upstream. Just bear in mind, because we've rewritten history, we're going to have to forcefully push this branch. Before doing this, you should fully understand the consequences of rewriting history, which in the case of this repository and its subsequent deployment, is fine. For further reading, see rewriting history over at git-scm.

So, let's push this upstream, forcefully.

$ git push --force

Finally, if everything works as expected, clean up the backup branch.

$ git branch -D hold-this


This post was first published on 21 January 2020 at 09:43. It was filed under archive with tags git, scm.