TL;DR git blame
rarely gives helpful results. Instead use specific flags on git log
to find the true author of a change.
What Does git blame
Actually Do?
git blame
searches the commit history to find the last person who modified a line of code. Some editors have this feature integrated into the interface, but the easiest way is at the command line:
git blame path/to/file
It prints an annotated list of lines to stdout
with the commit hash and author of the last person to change each line:
e45ad3 (Tim 2016-01-01) 1) import x from y;
8890d2 (Jeremy 2016-01-13) 2) import z from h;
e73ab4 (Michelle 2015-12-26) 3) public static...
What's Wrong with git blame
?
git blame
only shows the last person to modify a line. This is rarely what you want. More often what you want is the original author of a line. Here's a list of things which changes who git blame
shows as the author of a line:
- Changing line formatting or indenting
- Moving a block of code around in the file
- Renaming a file
- Any trivial change to the line
- Moving a file (god help you)
Do you want to find the person who changed all project tabs to spaces? Probably not. You probably want to find out who wrote the weird piece of logic you're looking at.
The Solution: git log
Knowledge
Here's the swiss army knife command to start with:
git log -p -M --follow --stat -- path/to/your/file
If you rely on your code editor program to manage git history, you're missing out on an important part of your codebase. It's important to understand each flag:
git log
General command to show multiple commits-p
Show patches, as in show what actually changed for each commit.-M
Show file renames in a readable way. A file rename now looks like this in the logs:path/to/{oldName.css => newName.css}
--follow
I'm not sure why this isn't turned on by default. If you specify a single file forgit log
(as we do here), and that file is renamed, this will keep following changes through the old file. Without this flag,git log
would end where the file was renamed. You won't be able to see the original author of a line, because it will be in old file name.--stat
Optional: show a summary of the total additions and removals for that commit. Can be useful for getting a big picture idea.-- path/to/file
(Two dashes and a space) The--
is the convention for Git (and some other bash commands) to specify a single file. Remember we're using--follow
so git will still treat any renames as a single file to follow.
Now What?
Now you're in a searchable list of commits being displayed through your shell's pager program (this is usually the less
program).
For example, let's say you want to find the author of this line of the Three.js source code:
this.quad.material.stencilTest = maskActive;
We want to search the output of the git log
command for this line. Copy part of the line that's likely to be unique, like this.quad.material.stencilTest
, then search for it in the pager output by pressing /
(forward slash), then paste, then Enter
to jump to the first result for that line.
Now, a trick is to press G
(shift-g) to jump to the end of the log results, then press N
(shift-n) to search backward from the end of the logs to the previous match. This will usually be the original change!
If not, you can bounce around the matches with n
and N
to keep looking.
To find the author of this commit, once your pager is focused on this line, a simple trick is to search backwards for the word commit
. To make sure you don't lose your place, start a backwards search using ?
instead of /
. Just type ?commit
then Enter
.
Ta-da, our commit author!
I chose this specific example because in this case, git blame
would have shown the commit which changed the indenting of this line which isn't helpful.
Now You Can Yell At Someone!
You can now ping the commit author with the commit hash and ask them your question!
That's It!
If this post helped you improve your Git fu, consider following me on Twitter or buying me a coffee :).