Jay Taylor's notes
back to listing indexbranch - How can I search Git branches for a file or directory? - Stack Overflow
[web search]-
TeamsStack Overflow for Teams – Start collaborating and sharing organizational knowledge.
Create a free Team Why Teams?
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.
-
I'm unclear about the question. Was this file in a branch that is now deleted? Was the file deleted?– AbizernDec 16, 2008 at 20:26
7 Answers
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
).
-
4This 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
-
5I 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– PREEBSep 17, 2012 at 22:57 -
1Note 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 usegit 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!– sleskeDec 9, 2014 at 9:51
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.
-
3A 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 -
12I wrapped this up in a script so you can run "gitfind.sh <regex>"; the gist is gist.github.com/62d981890eccb48a99dc Sep 19, 2011 at 17:12
-
6Note that this will only search across local branches. To search remote-tracking branches, use
refs/remotes
instead ofrefs/heads
. To search everything (local branches, remote-tracking branches and tags), just userefs/
.– sleskeApr 23, 2013 at 7:43
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.
-
Did you mean "Now you can do git-find-file <regex>"? I got it working, thank you! Apr 1, 2014 at 20:41
-
2I personally find it much more useful to use $(git branch | cut -c 3-) instead of $(git rev-list --all). I don't care about finding a bunch of commits, I care about named branches. Jul 14, 2014 at 20:15
-
I also changed the scripts to use $(git branch | cut -c 3-) since the loop over all commits was much too slow.– i4hOct 26, 2015 at 10:39
-
Seen all the fuss I thing is worth to create a repo for this. github.com/albfan/git-find-file. I have open some issues, feel free to propose more or send PR for it.– albfanOct 28, 2015 at 12:09
-
1@lumbric installing script on path works out of the box, its a git feature– albfanMay 13, 2016 at 14:09
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.)
-
3As 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.– MikeWJan 21, 2016 at 15:20
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.
-
-
-
2
-
" How do I get it to search all local and remote branches?" First pull all the remote branches with:
git branch -r | grep -v '->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done git fetch --all git pull --all
– Rob TowMar 16 at 17:19
This command finds commits which introduced specified paths:
git log --source --all --diff-filter=A --name-only -- '**/my_file.png'
A quite decent implementation of the find
command for Git repositories can be found here:
Your Answer
Post as a guest
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.
- The Overflow Blog
-
-
- Featured on Meta
-
-
-
-
-
Linked
Related
Hot Network Questions
- When is it appropriate to mix 74LSxx components with original TTL 74xx?
- Does an electric heater lose efficiency if the elements are rusty/corroded?
- Is there a way to render a 2D animation of a 3D object?
- (Complexity Theory) Given a large non-semiprime, is there a hard to compute but easy to verify problem?
- Engine comparison: How can a smaller/more efficient engine excel over its "bigger sibling"?
- Looking for an accurate Apple II(e) character set - in particular, what is CHR$(133)?
- Does DB15 actually exist?
- Defining set of all real numbers
- Can a corporation refuse to know things its agents know?
- What coordinates on Earth would provide the most arable land for a large island?
- Are items within a bag of holding that is itself within a chest of preserving kept from rotting?
- Extracting a common convergent indexing from an uncountable family of sequences
- Why is the dividend yield on the S&P 500 so low?
- Reference request: number of antichains of a partially ordered set
- Is there a difference between "There is a [noun]" vs "A [noun] is there"?
- How are these positive candy molds used? (if that's what they are)
- Is a contract written by a language model valid?
- The LaTeX Companion, Third Edition
- Book last read in 2000 involving a boy named Zeek I think who was training to be a wizard and visits a dimension called the bazaar
- A function to convert 0-2000 milliseconds to a double representing a fraction of a second
- Is it easy to shorten (cut) this ABS pipe and if yes, how?
- How can I see the version number of a GNOME Shell extension?
- Can one be a plumber yet kosher
- Combining present with past