How can I view prior commits with git blame?

GitCommitBlame

Git Problem Overview


Is it possible to see who edited a specific line before the commit reported by git blame, like a history of commits for a given line?

For example, I run the following (on the superb uncrustify project):

$ git blame -L10,+1 src/options.cpp
^fe25b6d (Ben Gardner 2009-10-17 13:13:55 -0500 10) #include "prototypes.h"

How can I find out who edited that line before commit fe25b6d? And who edited it before that commit?

Git Solutions


Solution 1 - Git

git blame -L 10,+1 fe25b6d^ -- src/options.cpp

You can specify a revision for git blame to look back starting from (instead of the default of HEAD); fe25b6d^ is the parent of fe25b6d.


Edit: New to Git 2.23, we have the --ignore-rev option added to git blame:

git blame --ignore-rev fe25b6d

While this doesn't answer OP's question of giving the stack of commits (you'll use git log for that, as per the other answer), it is a better way of this solution, as you won't potentially misblame the other lines.

Solution 2 - Git

You can use git log -L to view the evolution of a range of lines.

For example :

git log -L 15,23:filename.txt

means "trace the evolution of lines 15 to 23 in the file named filename.txt".

Solution 3 - Git

Amber's answer is correct but I found it unclear; The syntax is:

git blame {commit_id} -- {path/to/file}

Note: the -- is used to separate the tree-ish sha1 from the relative file paths. 1

For example:

git blame master -- index.html

Full credit to Amber for knowing all the things! :)

Solution 4 - Git

You might want to check out:

git gui blame <filename>

Gives you a nice graphical display of changes like "git blame" but with clickable links per line, to move into earlier commits. Hover over the links to get a popup with commit details. Not my credits... found it here:

http://zsoltfabok.com/blog/2012/02/git-blame-line-history/

git gui is a graphical Tcl/Tc interface to git. Without any other params it starts a pretty simple but useful graphical app for committing files, hunks or even single lines and other similar commands like amend, revert, push... It's part of the git stock suite. On windows it is included in the installer. On debian - I don't know about other *nix systems - it has to be installed separately:

apt-get install git-gui

From the docs:

https://git-scm.com/docs/git-gui

> DESCRIPTION > > A Tcl/Tk based graphical user interface to Git. git gui focuses on > allowing users to make changes to their repository by making new > commits, amending existing ones, creating branches, performing local > merges, and fetching/pushing to remote repositories. > > Unlike gitk, git gui focuses on commit generation and single file > annotation and does not show project history. It does however supply > menu actions to start a gitk session from within git gui. > > git gui is known to work on all popular UNIX systems, Mac OS X, and > Windows (under both Cygwin and MSYS). To the extent possible OS > specific user interface guidelines are followed, making git gui a > fairly native interface for users. > > COMMANDS > > blame > > Start a blame viewer on the specified file on the given version (or working directory if not specified). > > browser > > Start a tree browser showing all files in the specified commit. Files selected through the browser are opened in the blame viewer. > > citool > > Start git gui and arrange to make exactly one commit before exiting and returning to the shell. The interface is limited to only > commit actions, slightly reducing the application’s startup time and > simplifying the menubar. > > version > > Display the currently running version of git gui.

Solution 5 - Git

Building on the previous answer, this bash one-liner should give you what you're looking for. It displays the git blame history for a particular line of a particular file, through the last 5 revisions:

LINE=10 FILE=src/options.cpp REVS=5; for commit in $(git rev-list -n $REVS HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done

In the output of this command, you might see the content of the line change, or the line number displayed might even change, for a particular commit.

This often indicates that the line was added for the first time, after that particular commit. It could also indicate the line was moved from another part of the file.

Solution 6 - Git

A very unique solution for this problem is using git log, as explained by Andre here:

> git log -p -M --follow --stat -- path/to/your/file

Solution 7 - Git

There's also recursive-blame. It can be installed with

npm install -g recursive-blame

Solution 8 - Git

If you are using JetBrains Idea IDE (and derivatives) you can select several lines, right click for the context menu, then Git -> Show history for selection. You will see list of commits which were affecting the selected lines:

enter image description here

Solution 9 - Git

As of Git 2.23 you can use git blame --ignore-rev

For the example given in the question this would be:

git blame -L10,+1 src/options.cpp --ignore-rev fe25b6d

(however it's a trick question because fe25b6d is the file's first revision!)

Solution 10 - Git

Build on stangls's answer, I put this script in my PATH (even on Windows) as git-bh:

That allows me to look for all commits where a word was involved:

git bh path/to/myfile myWord

Script:

#!/bin/bash
f=$1
shift
csha=""
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    res=$(git blame -L"/$1/",+1 $hash -- "$f" 2>/dev/null | sed 's/^/  /')
    sha=${res%% (*}
    if [[ "${res}" != "" && "${csha}" != "${sha}" ]]; then
      echo "--- ${hash}"
      echo "${res}"
      csha="${sha}"
    fi
  done
}

Solution 11 - Git

Building on Will Shepard's answer, his output will include duplicate lines for commits where there was no change, so you can filter those as as follows (using this answer)

LINE=1 FILE=a; for commit in $(git rev-list HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

Note that I removed the REVS argument and this goes back to the root commit. This is due to Max Nanasy's observation above.

Solution 12 - Git

Building on DavidN's answer and I want to follow renamed file:

LINE=8 FILE=Info.plist; for commit in $(git log --format='%h%%' --name-only --follow -- $FILE | xargs echo | perl -pe 's/\%\s/,/g'); do hash=$(echo $commit | cut -f1 -d ','); fileMayRenamed=$(echo $commit | cut -f2 -d ','); git blame -n -L$LINE,+1 $hash -- $fileMayRenamed; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

ref: https://stackoverflow.com/questions/13447884/nicely-display-file-rename-history-in-git-log/37514394#37514394

Solution 13 - Git

I use this little bash script to look at a blame history.

First parameter: file to look at

Subsequent parameters: Passed to git blame

#!/bin/bash
f=$1
shift
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    echo "--- $hash"
    git blame $@ $hash -- "$f" | sed 's/^/  /'
  done
}

You may supply blame-parameters like -L 70,+10 but it is better to use the regex-search of git blame because line-numbers typically "change" over time.

Solution 14 - Git

I wrote ublame python tool that returns a naive history of a file commits that impacted a given search term, you'll find more information on the þroject page.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSedate AlienView Question on Stackoverflow
Solution 1 - GitAmberView Answer on Stackoverflow
Solution 2 - GitNavneetView Answer on Stackoverflow
Solution 3 - GitThorSummonerView Answer on Stackoverflow
Solution 4 - GitHolger BöhnkeView Answer on Stackoverflow
Solution 5 - GitWill SheppardView Answer on Stackoverflow
Solution 6 - GitmannuscriptView Answer on Stackoverflow
Solution 7 - GitThomas WView Answer on Stackoverflow
Solution 8 - GitwarvariucView Answer on Stackoverflow
Solution 9 - GitMichael PlatingsView Answer on Stackoverflow
Solution 10 - GitVonCView Answer on Stackoverflow
Solution 11 - GitDavidNView Answer on Stackoverflow
Solution 12 - GitBill ChanView Answer on Stackoverflow
Solution 13 - GitstanglsView Answer on Stackoverflow
Solution 14 - GitkraymerView Answer on Stackoverflow