Find to which git commit a file belongs?

Given a random file, is there a canonical method to determine from the command line whether the file belongs to a particular commit?

This is similar to stack overflow question find-out-which-git-commit-a-file-was-taken-from except that I wish to be able to use it in scripts and also not create a temporary branch.

  • Push Git Project to Local Directory
  • How do I backport a commit in git?
  • Why doesn't my git auto-update Expect script work?
  • Git: is there a functionality like the TFS shelveset?
  • how to update git clone
  • Efficient storage of binary files in a git repository
  • Git diff for copied files
  • In XCode 4 how do I add a remote GitHub repository to an existing local project?
  • Good ways to manage a changelog using git?
  • How can I move the root of my git repository?
  • Why is capistrano using git clone always
  • How to get the last commit ID of a remote repo using curl-like command?
  • 4 Solutions collect form web for “Find to which git commit a file belongs?”

    Below is an excerpt of a script that I have been using for the purpose. I hacked it together using my limited git knowledge and pieces of other scripts that I have found on the web. It works well enough, but I often find that there are easier ways to do things in git than what I have learned by trial and error.

    FILE=$1
    
    # git hash for file
    HASH=`git hash-object $FILE`
    
    # git revisions for file
    REVS=`git log --pretty=%H -- $FILE`
    
    # check each revision for checksum match
    for rev in $REVS; do
        POSSIBLE=`git ls-tree $rev $FILE | awk '{print $3}'`
        if [[ $HASH == $POSSIBLE ]]; then
            echo $rev
        fi
    done
    

    Your approach may fail to work in case of insignificant differences (e.g. line-ending style, or differences due to clean/smudge filters) between the local and repository versions of the file.

    The following script works via git diff rather than relying on hashes. It accepts diff options after the file name.

    Usage examples:

    # list all commits that introduce the file README.md in its local state
    list_introducing_commits README.md
    
    # list all commits that introduce the file README.md in its local state
    # ignoring any difference in whitespace
    list_introducing_commits README.md -w
    

    list_introducing_commits (couldn’t find a better name):

    #!/bin/bash
    
    if [ $# -eq 0 ]
    then
        echo "Usage: $(basename $0) path/to/file [<diff-options>]"
        exit 1
    fi
    
    file="$1"
    shift 1
    
    for rev in $(git log --pretty=%H -- "$file")
    do
        if git diff --exit-code $@ $rev -- $file &> /dev/null
        then
            echo $rev
        fi
    done
    

    Building on DavidN’s answer, if the file is in the current worktree, and the worktree is in sync with HEAD, this will get you the commit corresponding to the file’s current contents:

    git log --pretty="%H" -1  -- path/to/file
    

    But you might want to test those assumptions ahead of time via “git diff --exit-code /path/to/file” and taking a peek at $?.

    Do you mean, was the file modified in a commit? If so, something like git log --oneline -- filePathName should list the commits from HEAD where that is the case.

    On second reading, I think you are just asking for commits which contain that file, whether or not its changed. If so, then doesn’t your ls-tree need a -r flag, to recurse into its sub-trees (subdirs)? that will find any copies of a file under any name, if you just match on the sha.

    Git Baby is a git and github fan, let's start git clone.