gitsearch

How do I find the most recent git commit that modified a file?


I want to find the most recent commit that modified a source file.

I can use git blame to see all the dates for commits by each line, but it’s difficult to see exactly which commit was the last one to touch the file.

How can I find the last commit that touched a given file in my git repository?


Solution

  • Everyday usage

    git log supports looking at the history of specific files (and directories), so you can call it like this:

    git log path/to/file
    

    Tip: Whenever I look at the history of a specific file, I tend to also want to see the diffs, by passing -p (or --patch):

    git log -p path/to/file
    

    Advanced usage for shell scripting

    If you want only the commit hash for use in a script, git rev-list is the more appropriate low-level command (thanks Michael Erickson):

    git rev-list -1 HEAD -- path/to/file
    

    Here's what the options mean:

    What commit to search from

    Passing HEAD here makes it behave like git log (which starts at HEAD by default).

    What counts as "most recent"

    When specifying multiple branches that have diverged, or when the commit graph branches because of a merge, which commit counts as "most recent"? This is where the traversal order logic becomes relevant. The details are a bit tricky, but in most cases it basically does what you expect:

    git rev-list will always respect the topological order of the commit graph -- that is, parents are never visited before all of their children have been visited. But when it has a choice (e.g. walking the ancestors of a merge commit), it will interleave both paths by commit timestamp order (--date-order, the default) until it has reached a common ancestor. It immediately stops traversing once it has found a commit that modifies the file.

    Alternative solution

    Preserving my previous answer for the shell scripting case here: You could also use the git log -n 1 option to limit it to one commit:

    git log -n 1 --format=%H -- path/to/file
    

    --format=%H tells git log to show only the commit hash.

    I don't recommend git log for this, however, because it uses user-facing "porcelain" commands instead of lower-level "plumbing" commands.