By admin , 29 April 2026

What you will achieve

You will use git blame and git log together to reconstruct the history of a buggy line, identify when and why a change was made, and find the right person to consult. The same techniques apply to bug-hunting, security incident response, and onboarding.

Set up a sandbox

mkdir blame-tutorial && cd blame-tutorial
git init
cat > calc.js <<'EOF'
function divide(a, b) {
  return a / b;
}
module.exports = { divide };
EOF
git add . && git commit -m "Initial divide function"

# Add validation
sed -i.bak '2i\
  if (b === 0) throw new Error("Division by zero");
' calc.js && rm calc.js.bak
git commit -am "Add zero check"

# Refactor (introduces a subtle bug)
sed -i.bak 's|if (b === 0)|if (b == 0)|' calc.js && rm calc.js.bak
git commit -am "Style: use loose equality for zero check"

Step 1: blame the suspicious line

git blame -L 2,3 calc.js

Output shows the SHA, author, date, and content of each line. The most recent change to line 2 is the loose-equality refactor.

Step 2: inspect the suspicious commit

git show <sha>

You see the full commit - message, author, diff. The "style" justification looks innocent, but loose equality has subtle behaviour around null and undefined.

Step 3: walk the file's history

git log --follow -p calc.js

--follow traces across renames. -p shows each commit's diff. You see the full evolution of the file.

Step 4: find when a string was introduced

git log -S 'Division by zero' --oneline -- calc.js
# finds commits that change the count of this string

-S is the "pickaxe" - find when text was added or removed. -G is regex-based:

git log -G 'b\\s*[!=]==?\\s*0' --oneline -- calc.js

Step 5: blame ignoring formatter commits

Mass-format commits (prettier, black) bury blame results. Maintain .git-blame-ignore-revs:

# .git-blame-ignore-revs
abc1234   # Apply prettier across codebase
def5678   # Apply black to all Python
git config blame.ignoreRevsFile .git-blame-ignore-revs
git blame -L 2,3 calc.js

Now blame skips the formatter commits and points at the real authors.

Step 6: blame across renames and moves

git blame -M calc.js          # detect within-file moves
git blame -C calc.js          # detect across-file copies
git blame -CCC calc.js        # aggressive cross-file detection

Each C increases sensitivity. Three Cs catches even small moved fragments.

Step 7: log with detailed filters

git log --since='1 month' --author='Alice'
git log --grep='checkout'
git log -p -L :divide:calc.js     # log of changes to the divide function

-L :function:file traces a specific function across history.

Step 8: log a region of a file

git log -L 1,5:calc.js

Shows every commit that touched lines 1-5 of calc.js, with diffs. Powerful for tracing the evolution of a small block.

Step 9: combine with bisect

If blame points at a refactor that touched many files, bisect narrows further:

git bisect start
git bisect bad HEAD
git bisect good v1.0.0
git bisect run npm test

Bisect identifies the exact commit; blame and log fill in the why.

Step 10: graph the divergence

git log --graph --oneline --all -20

Useful when a bug appears only on one branch - the graph shows where branches diverged.

Real-world workflow

  1. Reproduce the bug.
  2. git blame the suspicious line.
  3. git show the commit; read the message.
  4. If the commit is too coarse, git log -p -- file to walk file history.
  5. If many files changed in tandem, git log -- 'src/**' for cross-file context.
  6. If commit message lacks context, ask the author (linked via blame).
  7. If the author has left, the message and PR description are your only source of context.

Etiquette

Blame is for understanding, not finger-pointing. The author of a line might have written it years ago in a context they no longer remember. Use blame to ask, not to accuse.

Tooling

VS Code's GitLens, JetBrains' built-in annotate, and fugitive.vim in Vim provide interactive blame UIs that make this workflow much faster than the CLI.

The result

You can navigate from a buggy line to the commit, the PR, the author, and the original intent in minutes. The investigative skills compound - the more often you do this, the faster you find the answer.