Can I use Git to search for matching filenames in a repository?

Just say I have a file: "HelloWorld.pm" in multiple subdirectories within a Git repository.

I would like to issue a command to find the full paths of all the files matching "HelloWorld.pm":

For example:

/path/to/repository/HelloWorld.pm
/path/to/repository/but/much/deeper/down/HelloWorld.pm
/path/to/repository/please/dont/make/me/search/through/the/lot/HelloWorld.pm

How can I use Git to efficiently find all the full paths that match a given filename?

I realise I can do this with the Linux/Unix find command but I was hoping to avoid scanning all subdirectories looking for instances of the filename.


git ls-files will give you a listing of all files in current state of the repository (the cache or index). You can pass a pattern in to get files matching that pattern.

git ls-files HelloWorld.pm '**/HelloWorld.pm'

If you would like to find a set of files and grep through their contents, you can do that with git grep:

git grep some-string -- HelloWorld.pm '**/HelloWorld.pm'

Hmm, the original question was about the repository. A repository contains more than 1 commit (in the general case at least), but the answers given before search only through one commit.

Because I could not find an answer that really searches the whole commit history I wrote a quick brute force script git-find-by-name that takes (nearly) all commits into consideration.

#! /bin/sh
tmpdir=$(mktemp -td git-find.XXXX)
trap "rm -r $tmpdir" EXIT INT TERM

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 $1 * 

Maybe there is a more elegant way.

Please note the trivial way the parameter is passed into grep, so it will match parts of filename. If that is not desired anchor your search expression and/or add suitable grep options.

For deep histories the output might be too noisy, I thought about a script that converts a list of revisions into a range, like the opposite of what git rev-list can do. But so far it has remained a thought.


Try:

git ls-tree -r HEAD | grep HelloWorld.pm

git ls-files | grep -i HelloWorld.pm

The grep -i makes grep case insensitive.