Reputation: 427
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.
Upvotes: 8
Views: 1654
Reputation: 8237
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.
Upvotes: 1
Reputation: 5507
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 $?
.
Upvotes: 1
Reputation: 32454
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
Upvotes: 1
Reputation: 427
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
Upvotes: 4