inkel

Software programmer interested in SRE, DevOps, Machine Learning and Augmented Reality.

Change several Git commits' author easily

4min.

Recently I’ve changed jobs, and that meant, among many other things, that my work email address changed, which means that my commits are now using the wrong email address! I need to fix that, but of course I’ve already committed stuff using my old email address. How can I fix that?

Luckily the solution isn’t difficult, though it took me a while to properly figure it out.

The first thing I needed to do was to configure my repository to use my work email address:

path/to/work-repo $ git config user.name "Leandro López (inkel)"
path/to/work-repo $ git config user.email "work@example.com"

Note that I’m doing this only for my work related repositories, so all of my other work (e.g. public or open source) uses my personal email address.

Next I want to know which commits SHA1s are using my personal email address. I can use the --author flag of git-log(1) and get that information easily:

$ git log --pretty=format:"%h - %aN <%ae> - %s" --abbrev-commit --author=personal@example.com
86b860dcc - inkel <personal@example.com> - Use stringSet for collecting child modules
9822062a9 - inkel <personal@example.com> - Use stringSet for collecting top root modules
d6d397f3c - inkel <personal@example.com> - Add stringSet type to collect unique set of strings

Now what I want to do is to reset the author to use the one I configured for this repository without editing the commit message; additionally I want to add a Signed off by line at the end of each commit message. One way to do this is to manually execute the following for every commit:

$ git commit --amend --signoff --author="Leandro López (inkel) <work@example.com>" $COMMITSHA

But as you can figure out, this becomes tedious if you have multiple commits. So let’s use the power of git-rebase(1) and automate this:

$ git rebase --exec='git commit --no-edit --amend -s --reset-author' d6d397f3c^
Executing: git commit --no-edit --amend -s --reset-author
[detached HEAD f29b70ad2] Add stringSet type to collect unique set of strings
 2 files changed, 120 insertions(+)
 create mode 100644 docker/terraform/automation/stringset.go
 create mode 100644 docker/terraform/automation/stringset_test.go
Executing: git commit --no-edit --amend -s --reset-author
[detached HEAD 3ca17042b] Use stringSet for collecting root modules
 1 file changed, 7 insertions(+), 21 deletions(-)
Executing: git commit --no-edit --amend -s --reset-author
[detached HEAD 5d168a566] Use stringSet to collect modules
 1 file changed, 3 insertions(+), 14 deletions(-)
Successfully rebased and updated refs/heads/foo.

And that’s it! All the commits got fixed to use my work email address instead.

What is going on?! Let’s dig into it

First is the --exec flag. This tells Git that for the given list of commits it needs to execute that command after each commit. In this case the command to execute is git commit --no-edit --amend -s --reset-author which amends the commit (--amend) without changing the commit message (--no-edit) except by adding a Signed off by line at the end of the message (-s which is short for --signoff) and changing the author to the one this repository should use (--reset-author, remember we add a custom configuration for it).

Then comes the commit list, in this case d6d397f3c^. Look again at the list of commits above. If you see, the SHA is the same as the one at the bottom of the list, which is the first commit of the list (they are shown in reverse order). The ^ at the end of the SHA instructs Git to go through the current list of commits until the parent of that commit, without including it.

And that’s it! Once this is done, I pull the list of commits again and it looks right:

$ git log --pretty=format:"%h - %aN <%ae> - %s (%cr)' --abbrev-commit --date=relative" --author=work@example.com
5d168a566 - Leandro López (inkel) <work@example.com> - Use stringSet for collecting child modules
3ca17042b - Leandro López (inkel) <work@example.com> - Use stringSet for collecting top root modules
f29b70ad2 - Leandro López (inkel) <work@example.com> - Add stringSet type to collect unique set of strings

This is a very particular use case, but what else we could do with it? Well, you can pass anything to the exec flag, not only Git commands, so you could say run your test suite for each commit and if the command fails then it will stop executing the rebase, allowing you to fix things before continuing. Definitely a very powerful tool to have in your toolbox!


Hello, Grafana Labs!

2min.

It’s been a while since my last post here, not because I’m lazy (which I am), but because as you know I recently changed jobs. It’s been almost a month at my new place, and now I feel confident to say that I joined Grafana Labs as an SRE for the internal cloud platform!

For most of my career I worked as a backend developer, only dabbling sporadically into an operations role, so I would be lying if I said that impostor syndrome didn’t kick in during my first few days at this new role, but luckily my team is super friendly, helping, and understanding, and my confidence is getting bigger as days pass. I think I made the right decision deciding to jump into this new adventure.

Switching jobs is never easy, specially after almost a decade at my previous work, and thus some of my schedules were affected, like the weekly cadence of newsletter or writing into this blog. I hope to get back into rhythm soon.

This past month I’ve spent it mostly going through the onboarding process, getting to know my team, some other teams' leaders, and familiarizing with the codebase and tools like Grafana, Loki, and Tanka. And I’ve even found the time to add a performance contribution to a third-party library!

There are still lots of things to learn, but for now I’ll continue to learn more about this amazing company and the work I’ll be doing, improving my skills, and learning a few more tricks. The future looks really bright!