Search code examples
cherry-pickpre-commitgit-checkout

How to find out what commit a checked out file came from


When I check out a file with git checkout $commit $filename and I forget $commit but still remember $filename, how do I find out what $commit was?


Solution

  • First a non-git answer. Check your shell command history. Well, if you didn't use a shell with command history then you don't...

    The git answer. You generally cannot find THE $commit. Generally the same contents might have been part of many commits and I don't think git keeps a log of what single file you have checked out (it keeps a log of previous values of HEAD)

    Here is a brute force script git-find-by-contents. Call it with your $filename as parameter, and it will show you all commits where this file was included. As the name says it searches by contents. So it will find files with any name, as long as the contents matches.

    #! /bin/sh
    tmpdir=/tmp/$(basename $0)
    mkdir $tmpdir 2>/dev/null
    rm  $tmpdir/* 2>/dev/null
    
    hash=$(git hash-object $1)
    echo "finding $hash"
    
    allrevs=$(git rev-list --all)
    # well, nearly all revs, we could still check the log if we have
    # dangling commits and we could include the index to be perfect...
    
    for rev in $allrevs
    do
      git ls-tree --full-tree -r $rev >$tmpdir/$rev 
    done
    
    cd $tmpdir
    grep $hash * 
    
    
    rm -r $tmpdir
    

    I would not be surprised if there is a more elegant way, but this has worked for me a couple of times in similar situations.

    EDIT: a more techy version of the same problem appears here: Which commit has this blob?