switch - git tag vs branch




Как выполнить grep(search) код в истории git? (9)

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

Очень плохое решение заключается в grep log:

git log -p | grep <pattern>

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


В моем случае мне нужно было искать Short Commit, и перечисленные решения, к сожалению, не работали.

Мне удалось это сделать: (замените токен 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

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

Как заметил Якуб Нарбский :

  • это ищет различия, которые вводят или удаляют экземпляр <string> .
    Обычно это означает «ревизии, в которых вы добавили или удалили строку с помощью« Foo ».

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

Как заметил Rob , этот поиск чувствителен к регистру - он открыл следующий вопрос о том, как искать регистр без учета регистра.


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

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

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


Если вы хотите просмотреть изменения кода (см., Что на самом деле было изменено с данным словом за всю историю), перейдите в режим 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 ;) )

Итак, вы пытаетесь выполнить grep через более старые версии кода, чтобы посмотреть, где что-то существует?

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


Мой любимый способ сделать это - с помощью опции -G git log (добавлено в версии 1.7.4).

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

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

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

Возьмите это совершение в качестве примера:

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

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


Чтобы найти контент для фиксации (то есть фактические строки источника, в отличие от сообщений фиксации и т. П.), Вам нужно сделать следующее:

git grep <regexp> $(git rev-list --all)

Обновления : git rev-list --all | xargs git grep <expression> 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>)

Я взял ответ @ Jeet и применил его к Windows (благодаря этому ответу ):

FOR /F %x IN ('"git rev-list --all"') DO @git grep <regex> %x > out.txt

Обратите внимание, что для меня по какой-то причине фактическая фиксация, которая удалила это регулярное выражение, не появилась в выводе команды, а скорее одна фиксация до нее.


git rev-list --all | xargs -n 5 git grep EXPRESSION

является настройкой решения @ Jeet, поэтому он показывает результаты во время поиска, а не только в конце (что может занять много времени в большом репо).







diff