Show Who Last Changed Each Line with git blame -L
Show who last changed each line of a range with git blame -L 2,3 file. The range can be line numbers, an offset like /regex/,+1, or a function name.
You care about a few lines of a long file and want to know which commit changed them and who wrote it.
export GIT_AUTHOR_DATE='2024-03-01T10:00:00Z' GIT_COMMITTER_DATE='2024-03-01T10:00:00Z'
git init -q repo && cd repo
git config user.name Ann && git config user.email [email protected]
printf 'one\ntwo\nthree\nfour\n' > f.txt
git add f.txt && git commit -qm 'add file'
export GIT_AUTHOR_DATE='2024-03-05T10:00:00Z' GIT_COMMITTER_DATE='2024-03-05T10:00:00Z'
sed -i 's/two/TWO/' f.txt
git -c user.name=Bob -c [email protected] commit -qam 'upper two'
git blame -L 2,3 --date=short f.txt
git blame -L '/three/,+1' --date=short f.txt
git blame -L 2,2 --porcelain f.txt | head -n 36b3a64ff (Bob 2024-03-05 2) TWO
^fb683f5 (Ann 2024-03-01 3) three
^fb683f5 (Ann 2024-03-01 3) three
6b3a64ff084441848108656f0750b9c7b076899d 2 2 1
author Bob
author-mail <[email protected]>-L 2,3 limits the blame to lines two and three, so the output has two lines and not the whole file. A regular expression works as a start, and /three/,+1 begins at the first match and takes one more line. The line for two shows Bob and a later date because that line was edited, while three shows Ann and a leading caret, which marks a boundary commit with nothing earlier. --porcelain prints a machine format. See git blame.
Blame names the last commit that touched a line, which may be a reformat and not the change you care about. Add -w to ignore whitespace and -C to follow code moved between files, or use git log -L for the history of a range. Dates in this run were fixed with environment variables so the hashes would repeat.