Как grep (поиск) зафиксировал код в истории git?



Я удалил файл или какой-то код в файл когда-то в прошлом. Могу ли я grep в содержании (не в сообщениях фиксации)?



очень плохое решение состоит в том, чтобы grep журнал:



git log -p | grep <pattern>


однако это не возвращает хэш фиксации сразу. Я играл с git grep безрезультатно.

762   13  

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 через весь ваш текст фиксации для регулярного выражения.

причина прохождения пути в обеих командах заключается в том, что rev-list вернет список ревизий, где все изменения в lib/util случилось, но и вам нужно перейти к grep, так что он будет искать только на lib/util.

только представьте себе следующий сценарий:grep может найти то же самое <regexp> на другие файлы, которые содержатся в той же редакции возвращается rev-list (даже если не было никаких изменений файл на эту ревизию).

вот некоторые другие полезные способы поиска источника:

поиск рабочего дерева для сопоставления текста регулярное выражение регулярное выражение:

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>

поиск всех редакций для сопоставления текста регулярное выражение регулярное выражение:

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-найти потерянную строку по ключевому слову дополнительные.


как Якуб Narębski комментирует:

  • этой ищет различия, которые вводят или удаляют экземпляр <string>.
    Обычно это означает " изменения, где вы добавили или удалена строка с 'Foo'".

  • the --pickaxe-regex опция позволяет использовать расширенное регулярное выражение POSIX вместо поиска строки.


как Роб прокомментировал, что этот поиск чувствителен к регистру - он открыл вопрос о том, как искать без учета регистра.

мой любимый способ сделать это с git log ' s (добавлена в версии 1.7.4).

-G<regex>
       Look for differences whose added or removed line matches the given <regex>.

есть тонкая разница между тем, как -G и -S параметры определяют, соответствует ли фиксация:

  • The -S опция по существу подсчитывает количество совпадений поиска в файле до и после фиксации. Фиксация отображается в журнале, если подсчеты до и после различны. Это не будет, например, показывать коммиты куда была перемещена строка, соответствующая вашему поиску.
  • С , фиксация в журнале, Если ваш поиск соответствует любой строке, которая была добавлена, удалена или изменена.

возьмите эту фиксацию в качестве примера:

diff --git a/test b/test
index dddc242..60a8ba6 100644
--- a/test
+++ b/test
@@ -1 +1 @@
-hello hello
+hello goodbye hello

потому что количество раз" привет " появляется в файле одинаково до и после этого фиксации, он не будет соответствовать с помощью -Shello. Однако, поскольку произошло изменение в строке соответствия hello, фиксация будет показана используя -Ghello.

Если вы хотите просмотреть изменения кода (смотрите, что на самом деле было изменено с данным словом во всей истории) перейдите к patch режим - я нашел очень полезное сочетание делает:

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'

эти команды журнала список коммитов, которые добавляют или удаляют заданную строку поиска/регулярное выражение, (как правило) более поздние сначала. Элемент причины соответствующих различий быть показано, где шаблон был добавлен или удален, так что вы можете увидеть его в контексте.

найдя соответствующие фиксация, которая добавляет текст, который вы искали (например. 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: текст найденной строки...

вы можете получить дополнительную информацию, как автор, дата, diff с помощью git show:

git show 6988bec26b1503d45eb0b2e8a4364afb87dde7af

для тех, кто еще пытается сделать это в SourceTree, в пользовательском интерфейсе для него нет прямой команды (начиная с версии 1.6.21.0). Однако вы можете использовать команды, указанные в принятом ответе, открыв терминал окно (кнопка доступна на главной панели инструментов) и копировать/вставлять их в него.

Примечание: конечно же Поиск посмотреть можно частично сделать текстовый поиск для вас. Нажмите Ctrl + 3, чтобы перейти к просмотру Поиск (или нажать вкладку "Поиск" внизу). В крайнем правом углу Установите тип поиска в Изменения Файла и затем введите строку, которую вы хотите найти. Этот метод имеет следующие ограничения по сравнению с приведенной выше командой:

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

для простоты я бы предложил использовать GUI:gitk-браузер репозитория Git, его довольно гибким

  1. в поиск код: enter image description here
  2. поиск файлов: enter image description here
  3. потому что он также поддерживает регулярные выражения: enter image description here

и вы можете перемещаться по результатам с помощью стрелки вверх/вниз

Итак, вы пытаетесь 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, поэтому он показывает результаты во время поиска, а не только в конце (что может занять много времени в большом РЕПО).

в моем случае мне нужно было найти короткую фиксацию, и перечисленные решения, к сожалению, не работали.

мне удалось это сделать с помощью: (замените регулярное выражение маркер)

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

Comments

    Ничего не найдено.