Как выполнить Git коммитов diff или содержимого для определенного слова?

623

В репозитории Git-кода я хочу перечислить все коммиты, которые содержат определенное слово. Я пробовал это

git log -p | grep --context=4 "word"

но это не обязательно возвращает мне имя файла (если оно не менее 5 строк от слова, которое я искал. Я также пытался

git grep "word"

но это дает мне только настоящие файлы, а не историю.

Как найти всю историю, чтобы отслеживать изменения в определенном слове? Я намерен искать в моей кодовой базе вхождения слова, чтобы отследить изменения (поиск в истории файлов).

Джеспер Рённ-Йенсен
источник

Ответы:

907

Если вы хотите найти все коммиты, в которых сообщение коммита содержит данное слово, используйте

$ git log --grep=word

Если вы хотите найти все коммиты, в которых «слово» было добавлено или удалено в содержимом файла (а точнее: где изменилось число вхождений «слова»), то есть поиск по содержимому коммита , используйте так называемый поиск «кирки» с

$ git log -Sword

В современном git есть также

$ git log -Gword

искать различия, чья добавленная или удаленная строка соответствует «слову» (также фиксирует содержимое ).

Обратите внимание, что -Gпо умолчанию принимает регулярное выражение, в то время как -Sпринимает строку, но может быть изменено, чтобы принимать регулярные выражения, используя --pickaxe-regex.

Чтобы проиллюстрировать разницу между -S<regex> --pickaxe-regexи -G<regex>, рассмотрим коммит со следующим diff в том же файле:

+    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
...
-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);

Пока git log -G"regexec\(regexp"покажет этот коммит, git log -S"regexec\(regexp" --pickaxe-regexне будет (так как количество вхождений этой строки не изменилось).


С Git 2.25.1 (февраль 2020) документация проясняется вокруг этих регулярных выражений.

См. Коммит 9299f84 (06 февраля 2020 г.) Мартина Агрена (``) .
(Объединено с Junio ​​C Hamano - gitster- в фиксации 0d11410 , 12 Feb 2020)

diff-options.txt: избежать перегрузки "regex" в примере

Автор: Адам Динвуди.
Подписано: Мартин Агрен.
Автор: Тейлор Блау.

Когда мы иллюстрируем разницу между -Gи -S(используя--pickaxe-regex ), мы делаем это с помощью примера diff и git diffвызова, включающего «regexec», «regexp», «regmatch», ...

Пример верный, но мы можем упростить распутывание, избегая написания «регулярных выражений. *», Если только это действительно не нужно для нашей цели.

Вместо этого используйте некоторые выдуманные слова без регулярных выражений.

git diffДокументация теперь включает в себя:

Чтобы проиллюстрировать разницу между -S<regex> --pickaxe-regexи -G<regex>, рассмотрим коммит со следующим diff в том же файле:

+    return frotz(nitfol, two->ptr, 1, 0);
...
-    hit = frotz(nitfol, mf2.ptr, 1, 0);

Пока git log -G"frotz\(nitfol"покажет этот коммит, git log -S"frotz\(nitfol" --pickaxe-regexне будет (так как количество вхождений этой строки не изменилось).

Якуб Наребски
источник
3
@TankorSmash -S<string>Ищите различия, которые вводят или удаляют экземпляр <string>. -G<string>Ищите различия, чья добавленная или удаленная строка соответствует данному <регулярному выражению>.
м-рик
1
@ m-ric О, я вижу один экземпляр строки, а не целую строку! Спасибо
TankorSmash
3
@ m-ric, @TankorSmash: Разница в том, что -S<string>быстрее, потому что он только проверяет, <string>изменилось ли количество вхождений , в то время как -G<string>поиск добавляет и удаляет строки в каждом коммите diff.
Якуб Наребски
3
Если вам нужно искать слова с пробелом между ними git log --grep="my words",.
MEM
4
@MEM, --grepотличается от -Sи -G. Вы можете указать строку для каждого из этих аргументов.
Acumenus
255

git logкирка найдет коммиты с изменениями, включая "слово" с git log -Sword

u0b34a0f6ae
источник
60
Это не совсем точно. -S <string> Ищите различия, которые вводят или удаляют экземпляр <string>. Обратите внимание, что это отличается от строки, просто появляющейся в выводе diff;
тымтам
4
Хотя это, как правило, правильный ответ, я проголосовал только за то, чтобы побудить других прочитать этот ответ ( stackoverflow.com/a/1340245/586983 ), который имеет 3 различных способа и объясняет их тонкости.
Jakeonrails
18
Гоша! Я не думаю, что это хорошая причина, чтобы понизить правильный ответ ... Вы не были уверены, что включение ссылки в комментарии будет достаточной поддержкой?
Дебора
@jakeonrails, этот ответ должен был быть правкой этого (более старого) ответа, поэтому у нас нет этих надоедливых дубликатов. Но людям нужна только репутация, а не чистая страница ответов.
Юлиан Онофрей
22

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

git log --pickaxe-regex -p --color-words -S "<regexp to search for>"

Требуется время, чтобы бежать, хотя ... ;-)

CharlesW
источник
2
Это одно из лучших на сегодняшний день спасибо. Подсказка: чтобы просто перечислить все результаты без разбивки на страницы, либо добавьте команду к команде, GIT_PAGER=catлибо добавьте ее| cat
Зак Моррис
Указать путь или файл будет намного быстрееgit log --pickaxe-regex -p --color-words -S "<regexp to search for>" <file or fiepath>
fangxing
10

Вы можете попробовать следующую команду:

git log --patch --color=always | less +/searching_string

или используя grepследующим образом:

git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'

Запустите эту команду в родительском каталоге, где вы хотите искать.

kenorb
источник
2
Мне нравится этот метод, потому что коммиты, на которые я смотрю, содержат сотни строк несвязанных изменений, и меня интересуют только патчи, содержащие слово, которое я ищу. Для получения цвета используйте git log --patch --color=always | less +/searching_string.
Радон Росборо
9

Еще один способ / синтаксис сделать это: git log -S "word"
например, вы можете искать, например,git log -S "with whitespaces and stuff @/#ü !"

1u-
источник
1

vim-fugitive универсален для такого рода исследований в Vim.

Используйте :Ggrepдля этого. Для получения дополнительной информации вы можете установить vim-fugitive и посмотреть турориал :help Grep. И этот эпизод: исследование хранилища-истории-git-репозитория поможет вам сделать все это.

Лернер Чжан
источник
1

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

git log --grep '[0-9]*\|[a-z]*'

Это регулярное выражение для поиска регулярного выражения [0-9] * или [az] * в сообщениях фиксации.

Reudismam
источник
-1

Если вы хотите найти конфиденциальные данные, чтобы удалить их из своей истории мерзавцев (именно поэтому я и попал сюда), для этого есть инструменты. Github в качестве специальной страницы справки по этому вопросу .

Вот суть статьи:

BFG Repo-очиститель является более быстрым, простой альтернативой мерзавца фильтра-ветвь для удаления ненужных данных. Например, чтобы удалить файл с конфиденциальными данными и оставить ваш последний коммит без изменений), выполните:

bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA

Чтобы заменить весь текст, указанный в файле passwords.txt, где бы он ни находился в истории вашего репозитория, выполните:

bfg --replace-text passwords.txt

См. Документацию BFG Repo-Cleaner для полного использования и инструкций по загрузке.

edelans
источник
Возможно, вы захотите добавить этот ответ в stackoverflow.com/questions/872565/… вместо этого
lacostenycoder