Git Blame Explained With Examples: Who Touched the Code?

7 min read
Stay connected

Version control tools are great at a variety of things, one of which is recording authorship of changes. Git, of course, isn’t an exception—among the various Git commands you should be aware of is git blame.

With this command, you can find out the authors of code changes in varying levels of detail. This information is valuable in many scenarios, as you’ll see—such as investigating when and how bugs were introduced.

In this guide, you’ll learn more about this command: how exactly it works, what the main command line options are, how it differs from similar commands, and much more. Let’s dig in.

Requirements

If you want to follow along with our examples, there are some basic requirements:

  • Familiarity with the command line

  • Git installed

  • Knowledge of at least the most basic Git commands

  • Optionally, Visual Studio Code (VS Code)

What Does Git Blame Do in Git?

During development, you’ll often want to know who made a specific change. This is useful, for instance, if you’re trying to determine when a bug was introduced. Or maybe you’re struggling to understand a piece of code and want to reach out directly to the author to ask them about it.

Git blame is the command that can tell you who was the last person to modify each line of code and when.

Git Blame: How Does It Work?

In its most basic form, this command “blames”—that is, indicates the authorship—of all lines in a file. The syntax is: git blame <FILE-PATH>.

Let’s see an example. You’ll start by cloning a repo on GitHub:

git clone https://github.com/haacked/seegit.git

After the cloning is complete, access the created folder:

cd seegit

Now display the authorship of a file:

git blame README.md

The result will look like this:

Let’s go over it in some more detail.

^2e9344d (Haacked           2012-03-04 14:23:45 -0800  1) # SeeGit - The Git Repository Visualizer
^2e9344d (Haacked           2012-03-04 14:23:45 -0800  2)
32aef720 (Haacked           2012-03-04 16:06:17 -0800  3) This is a little experiment in creating a realtime git repository visualizer.
32aef720 (Haacked           2012-03-04 16:06:17 -0800  4)

As you can see, the results from git blame contain the following parts for each line:

  • First, the commit hash identifying the commit that last modified the line

  • Then, the name of the author

  • The timestamp for the commit

  • Finally, the actual content of the file’s line, preceded by its number

Git Blame: Going Deeper

Having covered the very basics, let’s go a bit deeper.

Differences and Similarities

Let’s briefly cover how git blame relates to other Git commands.

Git Blame vs. Git Annotate

There’s another command very similar to git blame called git annotate. What is the difference between them? To make a long story short, they’re virtually the same. I quote from the documentation:

“The only difference between this command and git-blame[1] is that they use slightly different output formats, and this command exists only for backward compatibility to support existing scripts, and provide a more familiar command name for people coming from other SCM systems.”

For comparison, here you see the outputs of git blame and git annotate side by side:

Git Blame vs. Git Log

Git log is one of the most well-known commands in Git; you use it to learn about the history of a project. With the syntax git log -- <FILE-PATH> you can use it to see all the commits that touched a given file. So, how does that differ from git blame?

In short, git log gives you the overall history of the file through the entire timeline. Git blame, on the other hand, tells you who was the last one to touch each line of the code. They’re both useful, but each offers very different results.

Git Blame vs. Git Bisect

Git bisect is a powerful command that allows you to search throughout your project’s history using a binary search. You start by indicating a point in history that contains the “thing” you’re trying to identify the origin of—that’s typically a bug—and another point where you’re sure the code doesn’t contain said element. Git bisect then moves you through the history, allowing you to evaluate each stop as “good” or “bad” until the bisect command identifies the commit which introduced the defect.

When should you use bisect over blame? Simple: You’d typically use git bisect in situations where you know very little about how a bug was born. If you don’t even know which file is responsible for the problem, how are you going to use git blame?

In other words: Git blame is for when you know where to look.

Options

As with most Git commands, git blame supports many different options. Now we’ll walk you through some of the main ones:

-e: Show Author Email

As you’ve seen, the default output of git blame doesn’t include the author’s email. Use the -e option if you want the email included.

-l: Show Long Commit Hash

As you’ve also seen, the default output shows the abbreviated commit hash. If you want the full commit hash, add the -l (lowercase L) option.

-L: Specify Range of Lines

Having covered the lowercase L option, it seems fitting to follow that with uppercase L.

You use the -L option to provide git blame a range of lines instead of blaming the whole file. As an example, let’s blame the README file again, but this time, only lines 2 to 5.

git blame README.md -L 2,5

This is what the result looks like:

--first-parent: Only Follow the First Parent Commit of a Merge Commit

Commits in Git can have zero, one, or more parents. Root commits have zero parents, most commits have a single parent, and merge commits can have two or more parents.

The --first-parent option tells Git to only follow the first of the parents for merge commits when blaming a file. This is extremely useful, for instance, when you need to ignore the changes made in a different branch.

Miscellaneous Questions

We’ve covered some of the options that might come in handy when working with git blame on the command line.

However, you’ll often find yourself needing authorship information when working in a GUI context. We’ll now see how to use git blame in VS Code and on the GitHub interface.

How Do I Use Git Blame in VS Code?

VS Code is currently one of the most popular source code editors. It offers integration with Git, but you need extensions to use git blame.

One such extension is the appropriately named Git Blame. Upon installing and activating it, VS Code will display, in the status bar, who last touched each line of code:

That information changes as you navigate through the lines of the file. If you click on the label showing who last touched the given line of code, a pop-up will appear, providing more context for the change:

Finally, clicking on View will take you to GitHub, to the specified commit’s page.

GitLens is a popular extension for VS Code that, besides blaming functionality, brings many other useful Git features to the code editor. Here’s what it looks like in practice:

How Do I Git Blame on GitHub?

If you’re on GitHub and need to see authorship information, there’s a super easy way to do that. For instance, go to the repository we cloned earlier and open its README file—or just click here to go there directly.

Regardless of how you get there, you’ll notice there’s a Blame button in the right upper corner of the visualization of the file:

Just click on "Blame" to see a nice visual representation of blame information for the file:

Conclusion

Despite its negative-sounding name, git blame is an incredibly valuable Git command. With it, you can discover authorship information for every line of a single file.

That information can help you understand how a bug was introduced, trace a change back to its business reason, or discover the email of the person to contact to learn about a given piece of functionality.

As with most Git commands, you can change git blame’s behavior using its many options. The ones you’ve seen today barely scratch the surface. We recommend you continue playing and experiment with the command so you can learn more about all its capacities.

Thanks for reading!


This post was written by Carlos Schults. Carlos is a consultant and software engineer with experience in desktop, web, and mobile development. Though his primary language is C#, he has experience with a number of languages and platforms. His main interests include automated testing, version control, and code quality.

Stay up to date

We'll never share your email address and you can opt out at any time, we promise.

Loading form...
Your ad blocker may be blocking functionality on this page. Please disable for an improved experience.