git blame: who changed each line, and when

Updated July 31, 2026

git blame <file> prints the file line by line and attaches to every line the commit, the author and the date on which that line took its current shape.

You reach for it when a file contains a line nobody can explain: an odd value in a config, or a commented-out block nobody can account for. Blame tells you which commit the line came from, and the commit carries the message and everything else that changed alongside it.

$ git blame report.txt
^3d8599d (Anna Petrova 2025-02-14 10:12:00 +0300 1) Report for Q3
^3d8599d (Anna Petrova 2025-02-14 10:12:00 +0300 2) 
9bc5bb09 (Ivan Sokolov 2025-03-03 14:22:10 +0300 3) Sales grew by 12%.
9bc5bb09 (Ivan Sokolov 2025-03-03 14:22:10 +0300 4) We hired two people.

Four columns. First the abbreviated commit hash. Then, in brackets, the author of that commit, the date with time and time zone, and the line number in the file. After the closing bracket comes the line itself as it stands now. The first two lines have sat untouched since February; the third and fourth were written in March by someone else.

The ^ in front of the hash on the first two lines means they come from the earliest commit in the range being examined, usually the very first commit of the repository. The hash is printed one character shorter there so the column still lines up.

Flags worth knowing:

$ git blame -L 3,4 report.txt   # lines three through four only
$ git blame -w report.txt       # do not count whitespace-only edits
$ git blame -C report.txt       # look for lines moved in from other files

-L is what saves you in long files: blame over a thousand-line file is unreadable.

From a line to its commit

The hash in the first column is an ordinary commit hash, and the next step is almost always the same one: look at the whole commit.

$ git show 9bc5bb09
commit 9bc5bb094f1a5665665fe922f7f9bddf8e1e3cc5
Author: Ivan Sokolov <ivan@example.com>
Date:   Mon Mar 3 14:22:10 2025 +0300

    sales numbers and hiring

diff --git a/report.txt b/report.txt

Here you get the message, the other files of the same commit and its full diff. The line stops being an orphan: you can see which piece of work it belonged to.

Common mistakes

Blame shows the last edit of a line, not where it came from. A mass reformat or a file rename makes whoever committed it the author of every line, and the real history moves one layer deeper. That is what -w and -C are for: the first skips whitespace-only edits, the second follows lines that moved in from other files. When neither helps, take the hash of the useless commit and run blame on its parent: git blame 9bc5bb09^ -- report.txt.

Second, the name misleads. Blame answers "who wrote this", not "whose fault is this". A line can be correct for three years and break because of a change somewhere else entirely, and the author of the commit may have merely moved someone else's text around.

Where this is in the book

Chapter 4. Inspect, undo, ignore