Как я могу искать в ветвях Git файл или каталог?

Как в Git искать файл или каталог по пути в нескольких ветках?

Я что-то написал в ветке, но не помню какой. Теперь мне нужно его найти.

Уточнение: я ищу файл, созданный мной в одной из своих веток. Я бы хотел найти его по пути, а не по содержимому, так как я не помню, что это за содержимое.


person Peeja    schedule 16.12.2008    source источник
comment
Я не понимаю вопрос. Был ли этот файл в ветке, которая сейчас удалена? Файл был удален?   -  person Abizern    schedule 16.12.2008


Ответы (6)


git log + git branch найдет это для вас:

% git log --all -- somefile

commit 55d2069a092e07c56a6b4d321509ba7620664c63
Author: Dustin Sallings <[email protected]>
Date:   Tue Dec 16 14:16:22 2008 -0800

    added somefile


% git branch -a --contains 55d2069
  otherbranch

Также поддерживает подстановку:

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

Одиночные кавычки необходимы (по крайней мере, при использовании оболочки Bash), поэтому оболочка передает шаблон glob в git без изменений, а не расширяет его (как в Unix find).

person Dustin    schedule 16.12.2008
comment
Это работает, если вы знаете точный путь к somefile: если вам нужен поиск регулярных выражений по пути / имени файла, например, вы можете использовать ответ ididak. - person ShreevatsaR; 27.02.2012
comment
Также поддерживает подстановку: git log --all -- **/my_file.png - person webmat; 25.04.2012
comment
Я использовал это для немного другой проблемы. Я пытался найти все файлы * .sql, которые я передал в конкретную ветку. Так что я использовал git log --grep='branch' --author='me' -- *.sql. Работал как шарм. git версия 1.7.11.1 - person thepriebe; 18.09.2012
comment
Обратите внимание, что gitk также поддерживает подстановку. Это отличный ответ @webmat! Если вы хотите увидеть, где он был удален / создан / и т. Д., Вы можете использовать git log --all --stat -- **/my_file.png, чтобы вам не пришлось гадать, извлекаете ли вы его из коммита, который его удалил. - person eacousineau; 04.10.2013
comment
@webmat: Я взял на себя смелость добавить к ответу вашу информацию о глобализации. Спасибо, что упомянули об этом! - person sleske; 09.12.2014
comment
для чего нужно использовать две звездочки? только одного не хватит? - person Alexandre N.; 26.02.2016
comment
@AlexN. Две звездочки используются для обозначения нескольких уровней подкаталогов. - person Juha Palomäki; 30.09.2016
comment
Для тех, кому интересно (и сделайте это дальше в комментариях!): --all = ›Сделайте вид, будто все ссылки в refs / перечислены в командной строке как ‹commit›. - person Snowcrash; 02.10.2017
comment
Обратите внимание, что вы должны написать имя файла, как указано выше (со звездочками): ** / file.txt. Иначе ничего не покажет. - person CoolMind; 12.01.2018
comment
В этом ответе следует упомянуть, что (полный) относительный путь необходим для первой команды Git (git log --all -- somefile). - person Peter Mortensen; 07.01.2019
comment
если вы знаете только имя, лучше запустите эту команду из корня репозитория. Как сказал @PeterMortensen, вам нужно указать the (full) relative path, поэтому **/filename не будет работать, если вам нужно спускаться по папкам, чтобы найти файл. наверное для этого есть синтаксис? - person arod; 25.02.2020
comment
Боже, ты только что спас мне рассудок. В тот момент, когда вы реализовали что-то несколько недель назад, ветка все еще открыта, и вы просто не можете найти соответствующие файлы в беспорядке других 100 веток. - person Froxx; 03.03.2020
comment
Для Windows CMD используйте двойные кавычки для подстановки git log --all - ** / file.name - person esmirnov; 03.03.2021

git ls-tree может помочь. Для поиска по всем существующим веткам:

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

Преимущество этого заключается в том, что вы также можете выполнять поиск по имени файла с помощью регулярных выражений.

person ididak    schedule 16.12.2008
comment
Несколько, надеюсь, полезных комментариев: (a) Вы, вероятно, захотите добавить -r в git ls-tree, чтобы он нашел файл, даже если он находится в подкаталоге. (b) Возможно, более изящной альтернативой первой строке было бы использование git для каждой ссылки, например для филиала в git for-each-ref --format="%(refname)" refs/heads; do (c) git ls-tree --name-only сделает вывод более аккуратным (d), возможно, стоит указать в своем ответе, что это преимущество перед решением Дастина, а именно то, что вам не нужно точно знать имя файла - вы можете искать по регулярному выражению, соответствующему любой части пути - person Mark Longair; 28.06.2010
comment
Я обернул это в скрипт, чтобы вы могли запустить gitfind.sh ‹regex›; суть: gist.github.com/62d981890eccb48a99dc - person Handyman5; 19.09.2011
comment
Обратите внимание, что поиск будет выполняться только в локальных ветках. Для поиска веток удаленного отслеживания используйте refs/remotes вместо refs/heads. Для поиска всего (локальных веток, веток удаленного отслеживания и тегов) просто используйте refs/. - person sleske; 23.04.2013

Хотя ответ ididak довольно крутой, а Handyman5 предоставляет скрипт для его использования, я нашел его немного ограничен в использовании этого подхода.

Иногда вам нужно искать что-то, что может появляться / исчезать со временем, так почему бы не искать по всем коммитам? Кроме того, иногда вам нужен подробный ответ, а иногда - только фиксация совпадений. Вот две версии этих вариантов. Поместите эти сценарии на свой путь:

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

Теперь ты можешь сделать

$ 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

Обратите внимание, что с помощью getopt вы можете изменить этот скрипт, чтобы поочередно искать все коммиты, ссылки, ссылки / главы, были многословны и т. д.

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

Оформить заказ https://github.com/albfan/git-find-file для Возможная реализация.

person albfan    schedule 01.06.2013
comment
Вы имели в виду, что теперь вы можете использовать git-find-file ‹regex›? У меня все заработало, спасибо! - person Elijah Lynn; 02.04.2014
comment
Лично я считаю, что гораздо полезнее использовать $ (git branch | cut -c 3-) вместо $ (git rev-list --all). Меня не волнует поиск кучки коммитов, меня интересуют именованные ветки. - person Campadrenalin; 15.07.2014
comment
Я также изменил сценарии, чтобы использовать $ (git branch | cut -c 3-), поскольку цикл по всем коммитам был слишком медленным. - person i4h; 26.10.2015
comment
Видел всю суету, что стоит создать репо для этого. github.com/albfan/git-find-file. У меня есть открытые вопросы, не стесняйтесь предлагать больше или отправлять PR. - person albfan; 28.10.2015
comment
@ElijahLynn, если вы хотите использовать git find-file, вы можете сделать это, добавив его как псевдоним git, просто запустите `git config --global alias.find-file '! Git-find-file'. - person lumbric; 13.05.2016
comment
Сценарий установки @lumbric по пути работает из коробки, это функция git - person albfan; 13.05.2016
comment
Чтобы использовать только ветки, $ (git branch | cut -c 3-) перечисляет только локальные ветки, и их нужно вырезать. Вместо этого можно использовать $(git for-each-ref --format='%(refname:short)' refs/remotes refs/heads) для прямого перечисления локальных и удаленных ветвей. Кроме того, строка sed здесь содержит '/', который не будет работать с '/' в имени ветки, их можно изменить на '~', который является недопустимым символом в имени ветки, чтобы избежать этой проблемы. - person Zitrax; 20.05.2016
comment
@Zitrax Спасибо за комментарии. Теперь вы можете установить скрипт, получить справочную страницу, цвет, ссылки - все с помощью одной команды. - person albfan; 21.05.2016
comment
На какой платформе? Linux? - person Peter Mortensen; 07.01.2019

Вы можете использовать gitk --all и искать коммиты "касание путей" и имя пути, которое вас интересует.

person Greg Hewgill    schedule 16.12.2008
comment
Как уже говорилось, используйте gitk --all, затем в View | Новый вид, включите все ветви. Затем установите критерии поиска: имена файлов (с подстановочными знаками) в предпоследнем поле. Наконец: ОК. - person MikeW; 21.01.2016

Скопируйте и вставьте это, чтобы использовать git find-file SEARCHPATTERN

Печать всех найденных веток:

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; :'

Печатать только ветки с результатами:

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; :'

Эти команды добавят некоторые минимальные сценарии оболочки прямо в ваш ~/.gitconfig как global git псевдоним.

person lumbric    schedule 13.05.2016
comment
это только поиск в основной ветке - person Nasif Imtiaz Ohi; 20.03.2019
comment
Ищет во всех местных филиалах - person Leonardo Herrera; 12.06.2020
comment
Как мне заставить его искать во всех локальных и удаленных филиалах? - person rgvcorley; 29.06.2020

Здесь можно найти вполне приличную реализацию команды find для репозиториев Git:

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

person Dominik George    schedule 13.06.2016