Source control tools give users many powers and one of the big ones is traceability. With traceability tools you can know exactly who made each change and when they made it. In Git, you use the git blame command for this. Despite its negative-sounding name, it is a crucial command for you to know.
In this post, we’ll give you the ultimate guide on git blame. Among other things, you’ll learn the following:
- what the command does
- how to use it
- how to interpret its output
- auxiliary tools that can be of help
Let’s begin!
Does your team struggle with software audits? Is it a mess of screenshots and spreadsheets?
Learn how to automate itRequirements
We assume you have Git installed on your machine. It’d be helpful if you knew at least a few basic commands. We don’t make any assumptions regarding your operating system and shell choice. Surprises can happen, but all the commands we’ll show should work regardless of your platform preferences.
git blame 101
Let’s start by covering some fundamental questions about the command.
What Is git blame?
git blame is a command that displays authorship information regarding the latest changes to every line in a file. Given a specific file, for each line of the file, git blame will show you the author and commit hash that modified that line most recently.
As such, git blame is an incredibly useful command regarding traceability. For instance, if you’re investigating a bug, the command lets you know which commits last touched the lines you’re looking at and who made those changes. Using git blame along with other commands, such as git diff, can significantly improve your odds of understanding the changes made to a codebase.
How Do You Use git blame?
As is the case with most commands in Git, git blame offers a lot of options. The simplest way to use it, though, is to simply execute it, followed by the path to the file you want to blame. For instance, suppose your repository contains a file called file.txt with the following content:
hello
second line
To blame the file, you’d run:
$ git blame file.txt
And the output should be something like this:
^9e49b29 (Some User 2022-10-14 19:33:45 -0300 1) hello
5fa94671 (Some User 2022-10-14 19:35:26 -0300 2) second line
The output above displays each line of the file, prefixed by the hash of the last commit that changed that line, each commit’s author, and the timestamp.
Why Is It called git blame?
“Blame” is a strong word, and often people object to it. So, why is it called that?
It seems that Git simply copied the name from its predecessors, such as Subversion, which already had a blame command. Scott Furman, a former developer at Netscape, claims to be possibly the creator of the term “blame.” In 1997, he created a utility called cvsblame, which annotated authors and revision numbers for each line of a file.
How Do I Get Out Of git blame?
By default, the result of git blame will be paginated, even if there’s not enough input for that. To quit and return to the normal shell, press q (for quit) in the terminal.
Let’s look at git blame examples
Now that you know the basics about git blame, let’s deepen your understanding of the command with some examples.
To make the git blame example feel more realistic, we’ll use a real repository from an open-source project on GitHub called AutoFixture.
So, start by cloning the project and accessing the resulting folder:
$ git clone https://github.com/AutoFixture/AutoFixture
$ cd AutoFixture
Basic git blame Example and Understanding the Output
For the first example, let’s blame a file and analyze the output:
$ git blame appveyor.yml
This is part of the result:
23faee15c (Alex Povar 2020-06-26 16:53:45 +0200 1) image: Visual Studio 2019
3dd611242 (Alex Povar 2017-04-10 21:30:33 +0300 2)
3f644ad2e (Alex Povar 2017-04-10 12:42:06 +0300 3) environment:
3f644ad2e (Alex Povar 2017-04-10 12:42:06 +0300 4) NUGET_API_KEY:
Here, we have four lines being annotated. As you can see, Alex Povar was the last one to touch all of the lines displayed. Lines 3 and 4 were last changed by the same commit (3f644ad2e) on April 10, 2017, at around 1 p.m. in a time zone three hours ahead of UTC. Line 2 was changed later the same day. Alex, however, modified line 1 for the last time on June 26, 2020.
git blame Example With Range of Lines
You often want to blame a file, but you’re interested in just a subset of its lines. When that’s the case, you can use the -L option to specify the desired range of lines:
$ git blame README.md -L 3,5
In the git blame example above, we target the file README.md, but specify only the lines from 3 to 5 (inclusive on both ends.) Here’s the result:
579564223 (Andrei Ivascu 2020-10-26 16:03:19 +0200 3) [![Build status](https://ci.appveyor.com/api/projects/status/qlmobf6rt05pmt7e/branch/master?svg=true)](https://ci.appveyor.com/project/AutoFixture/autofixture/branch/master)
579564223 (Andrei Ivascu 2020-10-26 16:03:19 +0200 4) [![NuGet version](https://img.shields.io/nuget/vpre/AutoFixture.svg)](https://www.nuget.org/packages/AutoFixture)
a9a1479dc (Andrei Ivascu 2021-11-09 00:34:29 +0200 5) [![MyGet (with prereleases)](https://img.shields.io/myget/autofixture/vpre/autofixture?color=blue&label=myget)](https://www.myget.org/gallery/autofixture)
(END)
Showing the Author’s Email Address
By default, git blame only shows the author’s name. If you’d rather it show the author’s email address, you can use the -e flag. Let’s combine this option with the -L option we just saw:
$ git blame README.md -L 3,5 -e
Here are the results:
579564223 (<7030530+aivascu@users.noreply.github.com> 2020-10-26 16:03:19 +0200 3) [![Build status](https://ci.appveyor.com/api/projects/status/qlmobf6rt05pmt7e/branch/master?svg=true)](https://ci.appveyor.com/project/AutoFixture/autofixture/branch/master)
579564223 (<7030530+aivascu@users.noreply.github.com> 2020-10-26 16:03:19 +0200 4) [![NuGet version](https://img.shields.io/nuget/vpre/AutoFixture.svg)](https://www.nuget.org/packages/AutoFixture)
a9a1479dc (<7030530+aivascu@users.noreply.github.com> 2021-11-09 00:34:29 +0200 5) [![MyGet (with prereleases)](https://img.shields.io/myget/autofixture/vpre/autofixture?color=blue&label=myget)](https://www.myget.org/gallery/autofixture)
Rapidly pinpoint and understand changes and events in your infrastructure and applications
Learn howDisplaying the Full Commit Hash
By default, git blame only shows the short version of commit hashes. If you want to see the full hashes, append -l (that’s a lowercase L) to the command. For instance:
$ git blame README.md -l
Blaming Across Branches
You might need to blame a file’s version from another branch (or maybe a file that only exists on that other branch!). Nothing stops you from checking that branch out using git blame on the file before going back to the original branch.Â
But there’s an easier solution for that. You can use this syntax:
$ git blame <BRANCH-NAME> -- <PATH-TO-FILE>
To illustrate that, let’s quickly create and checkout a new branch:
$ git checkout -b new
Now, let’s create a new file:
$ echo hello > newfile
Time to commit the file:
$ git add .
$ git commit -m "add new file"
Now, if you go back to the original branch and try to run git blame newfile, you’ll get an error message. And that makes perfect sense, since it doesn’t exist in this branch.
However, we can easily blame across branches by running this command:
$ git blame new -- newfile
Doing that will result in the file newfile being blamed, and your name will appear as the sole editor of the file.
If that happens, it means you’ve successfully blamed across branches.
Detecting Lines Moved or Copied
git blame, by default, doesn’t take into account lines that were either copied or moved. In other words, if a line that was originally line 3 was moved to line 10, the person blamed as the author for line 10 would be the one who made the move, not the original author for line 3.
It’s possible to change this behavior by using the -M option (for lines copied or moved inside the same file) or -C (for lines from different files).
git blame and Code Editors
When developing software, it’d be nice if you could git blame without having to leave your code editor. Fortunately, this is also possible through the use of plugins.
If you use the popular Visual Studio Code (or simply VSCode) editor, you can leverage the GitLens plugin. Besides blame functionality, this plugin gives you many other interesting and useful Git-related features.
Vim is a screen-based text editor famous for (among other things) counting with a massive array of available plugins. Fugitive.vim is a plugin that makes it easier to work with Git while on Vim, and it offers git blame as a feature.
Conclusion
There are lots of good reasons for using a source control tool. One of the most important ones is traceability. With the help of Git, we can learn who made certain changes and when.Â
This post was all about git blame, a super valuable and often misunderstood command. With the help of git blame, you can learn who was the last person to change each line of a given file. This knowledge can be vital, especially when you’re investigating the causes of bugs.
Like many Git commands, git blame accepts many options and arguments. In this post, we’ve covered some that allow you to: filter for a specific range of lines, change the output format to include email, replace a short commit hash with the longer version, and more.
Finally, we mentioned how plugins can make your life easier when working with a code editor, such as VSCode or Vim. We hope this guide helps you to push incredible software to your users!