Resources / Guide

Reading git history: log, diff & blame

Most of git is about making history. A big part of the day-to-day value is reading it — what changed, when, and who did it. Four read-only commands turn a repo from an opaque pile of files into the most honest documentation a project has.

git log — what happened, and when

git log lists commits, newest first: the message, author, date, and a unique ID (the hash). On its own it's verbose, so the version actually worth memorizing is the compact one:

git log --oneline

That gives you one line per commit — short hash and message — which is usually all you need to get your bearings:

a1b2c3d Fix null reference when order has no line items
9f8e7d6 Add export button to orders grid
4c5b6a7 Bump dependency versions

A few additions that earn their keep:

git log --oneline --graph        # draw the branch/merge structure
git log --oneline -10            # just the last 10
git log --oneline -- Program.cs  # only commits that touched one file
git log --author="Sam"           # only one person's commits
git log --since="2 weeks ago"    # recent history

That last group is how you answer real questions: "what's changed in this file lately?", "what did I do last week?", "when did this dependency get bumped?". The -- <file> form is especially handy — it filters the whole history down to a single file's story.

git diff — what actually changed

A log tells you that something changed; git diff shows you what. With no arguments, it shows the changes in your working directory that you haven't staged yet:

git diff

Lines starting - were removed, lines starting + were added. Useful variants:

git diff --staged          # what you've staged, ready to commit
git diff main              # how your branch differs from main
git diff a1b2c3d 9f8e7d6   # the difference between two commits

git diff --staged is the one to build a habit around: run it right before you commit to read exactly what you're about to save. It catches the stray debug line, the accidentally-committed secret, the file you didn't mean to touch — the things that are annoying to fix after they're in history.

git show — one commit, in full

When git log points you at an interesting commit, git show opens it: the message plus the full diff of what it changed.

git show a1b2c3d

This is how you inspect a single change end to end — "what exactly did that bug fix touch?" — without digging through the whole history around it.

git blame — who last touched each line

git blame answers "who wrote this line, and in which commit?" by annotating a file line-by-line with the last commit that changed it:

git blame Program.cs

Each line gets a short hash, the author, the date, and the line itself. Despite the name, it's rarely about assigning fault — it's about context. You find a weird-looking line, blame tells you which commit introduced it, and git show <that hash> tells you why (the commit message and everything else that changed alongside it). That chain — blame to find the commit, show to read the reasoning — is one of the most useful moves in git, and it's how a good commit message written months ago saves someone an hour today.

Most editors and git hosts wrap blame in a nicer UI (hover a line, see the commit), but the command is always there when you want it.

Putting it together

These four commands form a little investigation loop. git log --oneline to scan what's happened, git diff to see uncommitted changes, git show to open a specific commit, and git blame to trace a particular line back to the decision that created it. None of them change anything — they're all read-only — so you can run them freely while finding your way around a codebase. The more comfortable you get reading history, the more a repo stops being a black box.

Inherited a codebase with no documentation?

Sometimes the git history is the only spec there is. I dig into unfamiliar .NET systems, map how they actually work, and get them moving again. If that's where you are, let's talk.

Work with me