Jay Taylor's notes

back to listing index

branch - How can I search Git branches for a file or directory? - Stack Overflow

[web search]
Original source (stackoverflow.com)
Tags: git howto stackoverflow.com
Clipped on: 2023-12-13

    1. Home
    2. Questions
    3. Tags
    4. Users
    5. Companies
    6. Explore Collectives
    7. Labs
    8. Discussions
  1. Teams
    Stack Overflow for Teams – Start collaborating and sharing organizational knowledge. Create a free Team Why Teams?
Asked 14 years, 11 months ago
Modified 9 months ago
Viewed 192k times
434

In Git, how could I search for a file or directory by path across a number of branches?

I've written something in a branch, but I don't remember which one. Now I need to find it.

Clarification: I'm looking for a file which I created on one of my branches. I'd like to find it by path, and not by its contents, as I don't remember what the contents are.

Belphegor
4,5361111 gold badges3535 silver badges5959 bronze badges
asked Dec 16, 2008 at 20:02
Peeja
13.8k1111 gold badges5959 silver badges7777 bronze badges

7 Answers

Sorted by:
589

git log + git branch will find it for you:

% git log --all -- somefile

commit 55d2069a092e07c56a6b4d321509ba7620664c63
Author: Dustin Sallings <dustin@spy.net>
Date:   Tue Dec 16 14:16:22 2008 -0800

    added somefile


% git branch -a --contains 55d2069
  otherbranch

Supports globbing, too:

% git log --all -- '**/my_file.png'

The single quotes are necessary (at least if using the Bash shell) so the shell passes the glob pattern to git unchanged, instead of expanding it (just like with Unix find).

StackzOfZtuff
2,57111 gold badge2929 silver badges2626 bronze badges
answered Dec 16, 2008 at 22:17
Dustin
89.5k2121 gold badges112112 silver badges133133 bronze badges
  • 4
    This works if you know the exact path to somefile: if you need regex search over the path/filename, for example, then you can use ididak's answer. Feb 27, 2012 at 9:05
  • 84
    Supports globbing, too: git log --all -- **/my_file.png
    – webmat
    Apr 25, 2012 at 18:01
  • 5
    I used this for a slightly different problem. I was trying to find all the *.sql files I had committed to a particular branch. So I used git log --grep='branch' --author='me' -- *.sql. Worked like a charm. git version 1.7.11.1
    – PREEB
    Sep 17, 2012 at 22:57
  • 1
    Note that gitk supports the globbing as well. That is an excellent answer @webmat! If you want to see where it's been deleted / created /etc, you can use git log --all --stat -- **/my_file.png, that way you won't have to guess if you're checking it out from a commit that deleted it. Oct 4, 2013 at 4:55
  • 1
    @webmat: I took the liberty of adding your information about globbing to the answer. Thanks for mentioning it!
    – sleske
    Dec 9, 2014 at 9:51
80

git ls-tree might help. To search across all existing branches:

for branch in `git for-each-ref --format="%(refname)" refs/heads`; do
  echo $branch :; git ls-tree -r --name-only $branch | grep '<foo>'
done

The advantage of this is that you can also search with regular expressions for the file name.

Petr Viktorin
65.8k99 gold badges8181 silver badges8181 bronze badges
answered Dec 16, 2008 at 20:47
ididak
5,79011 gold badge2121 silver badges2121 bronze badges
  • 3
    A few hopefully helpful comments: (a) You probably want to add "-r" to "git ls-tree" so that it'll find the file even if it's in a subdirectory. (b) A perhaps neater alternative to the first line would be to use "git for-each ref", e.g. "for branch in git for-each-ref --format="%(refname)" refs/heads; do" (c) "git ls-tree --name-only" will make the output tidier (d) it might be worth pointing out in your answer that there's an advantage of this over Dustin's solution, namely that you don't need to exactly know the filename - you can search by regular expression matching any part of the path Jun 28, 2010 at 16:02
  • 12
    I wrapped this up in a script so you can run "gitfind.sh <regex>"; the gist is gist.github.com/62d981890eccb48a99dc
    – Handyman5
    Sep 19, 2011 at 17:12
  • 6
    Note that this will only search across local branches. To search remote-tracking branches, use refs/remotes instead of refs/heads. To search everything (local branches, remote-tracking branches and tags), just use refs/.
    – sleske
    Apr 23, 2013 at 7:43
27

Although ididak's response is pretty cool, and Handyman5 provides a script to use it, I found it a little restricted to use that approach.

Sometimes you need to search for something that can appear/disappear over time, so why not search against all commits? Besides that, sometimes you need a verbose response, and other times only commit matches. Here are two versions of those options. Put these scripts on your path:

git-find-file

for branch in $(git rev-list --all)
do
  if (git ls-tree -r --name-only $branch | grep --quiet "$1")
  then
     echo $branch
  fi
done

git-find-file-verbose

for branch in $(git rev-list --all)
do
  git ls-tree -r --name-only $branch | grep "$1" | sed 's/^/'$branch': /'
done

Now you can do

$ git find-file <regex>
sha1
sha2

$ git find-file-verbose <regex>
sha1: path/to/<regex>/searched
sha1: path/to/another/<regex>/in/same/sha
sha2: path/to/other/<regex>/in/other/sha

See that using getopt you can modify that script to alternate searching all commits, refs, refs/heads, been verbose, etc.

$ git find-file <regex>
$ git find-file --verbose <regex>
$ git find-file --verbose --decorated --color <regex>

Checkout https://github.com/albfan/git-find-file for a possible implementation.

Peter Mortensen
30.8k2222 gold badges106106 silver badges131131 bronze badges
answered Jun 1, 2013 at 3:13
albfan
12.7k44 gold badges6161 silver badges8080 bronze badges
16

Command Line

You could use gitk --all and search for commits "touching paths" and the pathname you are interested in.

UI

(Credit to: @MikeW's suggestion.)

BenKoshy
33.9k1414 gold badges111111 silver badges8080 bronze badges
answered Dec 16, 2008 at 21:31
Greg Hewgill
961k185185 gold badges11551155 silver badges12881288 bronze badges
  • 3
    As stated, use gitk --all, then in View | New view, enable All Branches. Then set your search criteria: filenames (with wild cards) in the penultimate field. Finally: OK.
    – MikeW
    Jan 21, 2016 at 15:20
12

Copy & paste this to use git find-file SEARCHPATTERN

Printing all searched branches:

git config --global alias.find-file '!for branch in `git for-each-ref --format="%(refname)" refs/heads`; do echo "${branch}:"; git ls-tree -r --name-only $branch | nl -bn -w3 | grep "$1"; done; :'

Print only branches with results:

git config --global alias.find-file '!for branch in $(git for-each-ref --format="%(refname)" refs/heads); do if git ls-tree -r --name-only $branch | grep "$1" > /dev/null; then  echo "${branch}:"; git ls-tree -r --name-only $branch | nl -bn -w3 | grep "$1"; fi; done; :'

These commands will add some minimal shell scripts directly to your ~/.gitconfig as global git alias.

answered May 13, 2016 at 14:33
lumbric
8,07688 gold badges4242 silver badges5353 bronze badges
4

This command finds commits which introduced specified paths:

git log --source --all --diff-filter=A --name-only -- '**/my_file.png'
answered Jul 22, 2022 at 11:22
reddot
82399 silver badges1515 bronze badges
-3

A quite decent implementation of the find command for Git repositories can be found here:

https://github.com/mirabilos/git-find

Peter Mortensen
30.8k2222 gold badges106106 silver badges131131 bronze badges
answered Jun 13, 2016 at 22:17
Dominik George
51422 silver badges1515 bronze badges

Your Answer

Sign up or log in

Sign up using Google
Sign up using Facebook
Sign up using Email and Password

Post as a guest

Name
Email

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.

Hot Network Questions