Как grep (поиск) зафиксированный код в истории git?
13 ответов
для поиска фиксации контент (т. е. фактические строки источника, в отличие от сообщений фиксации и тому подобного), что вам нужно сделать:
git grep <regexp> $(git rev-list --all)
обновления: git rev-list --all | xargs git grep expression
будет работать, если вы столкнетесь с ошибкой "список аргументов слишком длинный"
если вы хотите ограничить поиск некоторым поддеревом (например, "lib/util"), вам нужно будет передать это в rev-list
команда и grep
а также:
git grep <regexp> $(git rev-list --all -- lib/util) -- lib/util
это будет grep через весь ваш текст фиксации для regexp.
причина прохождения пути в обеих командах заключается в том, что rev-list
вернет список ревизий, где все изменения в lib/util
случилось, но и вам нужно перейти к grep
, так что он будет искать только на lib/util
.
представьте себе следующий сценарий:grep
может найти то же самое <regexp>
на другие файлы, которые содержатся в той же редакции, возвращенной rev-list
(даже если не было никаких изменений файл на эту ревизию).
вот некоторые другие полезные способы поиска источника:
поиск рабочего дерева для текста, соответствующего регулярному выражению regexp:
git grep <regexp>
поиск в рабочем дереве строк текста, соответствующих регулярному выражению regexp1 или regexp2:
git grep -e <regexp1> [--or] -e <regexp2>
поиск рабочего дерева для строк текста, соответствующих регулярному выражению regexp1 и regexp2, только пути к файлам отчетов:
git grep -e <regexp1> --and -e <regexp2>
поиск рабочего дерева для файлы, имеющие строки текста, соответствующие регулярному выражению regexp1 и строки текста, соответствующие регулярному выражению regexp2:
git grep -l --all-match -e <regexp1> -e <regexp2>
поиск рабочего дерева для измененных строк текста по шаблону:
git diff --unified=0 | grep <pattern>
поиск всех редакций для текста, соответствующего регулярному выражению regexp:
git grep <regexp> $(git rev-list --all)
поиск всех ревизий между rev1 и rev2 для текста, соответствующего регулярному выражению regexp:
git grep <regexp> $(git rev-list <rev1>..<rev2>)
вы должны использовать Кирка (-S
) на git log
искать Foo
:
git log -SFoo -- path_containing_change
git log -SFoo --since=2009.1.1 --until=2010.1.1 -- path_containing_change
посмотреть история Git-найти потерянную строку по ключевому слову дополнительные.
As Якуб Narębski комментирует:
этой ищет различия, которые вводят или удаляют экземпляр
<string>
.
Обычно это означает " изменения, в которые вы добавили или удалена строка с 'Foo'".на
--pickaxe-regex
опция позволяет использовать расширенное регулярное выражение POSIX вместо поиска строки.
As Роб прокомментировал, что этот поиск чувствителен к регистру - он открыл вопрос о том, как искать без учета регистра.
мой любимый способ сделать это с git log
' s (добавлена в версии 1.7.4).
-G<regex>
Look for differences whose added or removed line matches the given <regex>.
существует тонкая разница между тем, как -G
и -S
параметры определяют, соответствует ли фиксация:
- на
-S
опция по существу подсчитывает количество совпадений поиска в файле до и после фиксации. Фиксация отображается в журнале, если количество до и после отличается. Это не будет, например, показывать коммиты где была перемещена строка, соответствующая вашему поиску. - С , фиксация в журнале, Если ваш поиск соответствует любой строке, которая была добавлена, удалена или изменена.
возьмите эту фиксацию в качестве примера:
diff --git a/test b/test
index dddc242..60a8ba6 100644
--- a/test
+++ b/test
@@ -1 +1 @@
-hello hello
+hello goodbye hello
поскольку количество раз, когда" hello " появляется в файле, одинаково до и после этой фиксации, оно не будет совпадать с использованием -Shello
. Однако, поскольку произошло изменение строки, соответствующей hello
, фиксация будет показана используя -Ghello
.
Если вы хотите просмотреть изменения кода (см., что на самом деле было изменено с данным словом во всей истории), перейдите к patch
mode - я нашел очень полезную комбинацию действий:
git log -p
# hit '/' for search mode
# type in the word you are searching
# if the first search is not relevant hit 'n' for next (like in vim ;) )
взял @Джит-х и по мере ее Windows (спасибо ответ):
FOR /F %x IN ('"git rev-list --all"') DO @git grep <regex> %x > out.txt
обратите внимание, что для меня по какой-то причине фактическая фиксация, которая удалила это регулярное выражение, не появилась в выходных данных команды, а скорее одна фиксация до нее.
git log
может быть более эффективным способом поиска текста во всех ветвях, особенно если есть много совпадений, и вы хотите сначала увидеть более последние (соответствующие) изменения.
git log -p --all -S 'search string'
git log -p --all -G 'match regular expression'
этот список команд журнала фиксирует, что добавляет или удаляет заданную строку поиска / регулярное выражение, (обычно) более недавнее. The -p
опция заставляет соответствующий diff отображаться, где шаблон был добавлен или удален, поэтому вы можете видеть его в контексте.
найдя соответствующие фиксация, которая добавляет текст, который вы искали (например. 8beeff00d), найдите ветви, содержащие фиксацию:
git branch -a --contains 8beeff00d
поиска любая редакция, любые файлы:
git rev-list --all | xargs git grep <regexp>
поиск только в некоторых заданных файлах, например xml-файлах:
git rev-list --all | xargs -I{} git grep <regexp> {} -- "*.xml"
строки результатов должны выглядеть следующим образом: 6988bec26b1503d45eb0b2e8a4364afb87dde7af: bla.xml: текст найденной строки...
вы можете получить больше информации, как автор, дата, разница с помощью git show:
git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af
для всех, кто пытается сделать это в SourceTree, в пользовательском интерфейсе для него нет прямой команды (начиная с версии 1.6.21.0). Однако вы можете использовать команды, указанные в принятом ответе, открыв терминал окно (кнопка доступна на главной панели инструментов) и скопируйте/вставьте их в него.
Примечание: конечно же Поиск view может частично выполнять текстовый поиск для вас. Нажмите Ctrl + 3 перейти к просмотру поиска (или нажать вкладку "Поиск" внизу). В крайнем правом углу Установите тип поиска в Изменения Файла и затем введите строку, которую вы хотите найти. Этот метод имеет следующие ограничения по сравнению с приведенной выше командой:
- SourceTree показывает только commits, которые содержат искомое слово в одном из измененных файлов. Поиск точного файла, содержащего текст поиска, снова является ручной задачей.
- регулярное выражение не поддерживаемый.
для простоты я бы предложил использовать GUI:gitk-браузер репозитория Git, его довольно гибким
и вы можете перемещаться по результатам, используя стрелку вверх/вниз
Итак, вы пытаетесь grep через более старые версии кода, чтобы увидеть, где что-то последнее существует?
Если бы я это делал, я бы, вероятно, использовал git bisect. Используя bisect, вы можете указать известную хорошую версию, известную плохую версию и простой скрипт, который проверяет, является ли версия хорошей или плохой (в этом случае grep, чтобы увидеть, присутствует ли код, который вы ищете). Запуск этого найдет, когда код был удален.
ответ@Jeet работает в PowerShell.
git grep -n <regex> $(git rev-list --all)
ниже отображаются все файлы, в любом фиксации, которые содержат password
.
# store intermediate result
$result = git grep -n "password" $(git rev-list --all)
# display unique file names
$result | select -unique { $_ -replace "(^.*?:)|(:.*)", "" }
git rev-list --all | xargs -n 5 git grep EXPRESSION
- это настройка решения @Jeet, поэтому он показывает результаты во время поиска, а не только в конце (что может занять много времени в большом РЕПО).
в моем случае мне нужно было найти короткую фиксацию, и перечисленные решения, к сожалению, не работали.
мне удалось сделать это с: (замените REGEX маркер)
for commit in $(git rev-list --all --abbrev-commit)
do
if [[ $commit =~ __REGEX__ ]]; then
git --no-pager show -s --format='%h %an - %s' $commit
fi
done