Как выполнить Git коммитов diff или содержимого для определенного слова?
В репозитории Git-кода я хочу перечислить все коммиты, которые содержат определенное слово. Я пробовал это
git log -p | grep --context=4 "word"
но это не обязательно возвращает мне имя файла (если оно не менее 5 строк от слова, которое я искал. Я также пытался
git grep "word"
но это дает мне только настоящие файлы, а не историю.
Как мне искать всю историю, чтобы отслеживать изменения в определенном слове? Я имею в виду искать в моей кодовой базе вхождения слова, чтобы отследить изменения (поиск в истории файлов).
9 ответов
Если вы хотите найти все коммиты, где сообщение о коммите содержит данное слово, используйте
$ 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, ®match, 0); ... - hit = !regexec(regexp, mf2.ptr, 1, ®match, 0);
В то время как
git log -G"regexec\(regexp"
покажет этот коммит,git log -S"regexec\(regexp" --pickaxe-regex
не будет (потому что количество вхождений этой строки не изменилось).
git log
кирка найдет коммиты с изменениями, включая "слово" с git log -Sword
После долгих экспериментов я могу порекомендовать следующее, которое показывает коммиты, которые вводят или удаляют строки, содержащие заданное регулярное выражение, и отображает изменения текста в каждом, а цвета показывают слова, добавляемые и удаляемые.
git log --pickaxe-regex -p --color-words -S "<regexp to search for>"
Требуется время, чтобы бежать, хотя...;-)
Вы можете попробовать следующую команду:
git log --patch --color=always | less +/searching_string
или используя grep
следующим образом:
git rev-list --all | GIT_PAGER=cat xargs git grep 'search_string'
Запустите эту команду в родительском каталоге, где вы хотите искать.
Еще один способ / синтаксис сделать это: git log -S "word"
Как это вы можете искать, например, git log -S "with whitespaces and stuff @/#ü !"
Чтобы использовать логический соединитель для регулярного выражения:
git log --grep '[0-9]*\|[a-z]*'
Это регулярное выражение для поиска регулярного выражения [0-9]* или [az]* в сообщениях фиксации.
Это полезно в сочетании с BGF / git-filter-repo, оно просто получает пути к файлам, чтобы вы могли передать их в один из двух инструментов, которые я только что упомянул.
A. Полные, уникальные, отсортированные пути:
# Get all unique filepaths of files matching 'password'
# Source: https://stackoverflow.com/a/69714869/10830091
git rev-list --all | (
while read revision; do
git grep -F --files-with-matches 'password' $revision | cat | sed "s/[^:]*://"
done
) | sort | uniq
Б. Уникальные отсортированные имена файлов (не пути):
# Get all unique filenames matching 'password'
# Source: https://stackoverflow.com/a/69714869/10830091
git rev-list --all | (
while read revision; do
git grep -F --files-with-matches 'password' $revision | cat | sed "s/[^:]*://"
done
) | xargs basename | sort | uniq
Эта вторая команда полезна для BFG, потому что она принимает только имена файлов, а не репо-относительные / системные пути.
Итак, наслаждайтесь использованием этих фрагментов bash, причиняя столько же мучений, сколько они причинили мне. Ненавижу bash, почему я продолжаю его использовать ???
Расслоение
Получить только имена / пути к файлам
Любой из следующих вариантов означает то же самое ( git-rep docs):
-
-l
-
--files-with-matches
-
--name-only
Вместо того, чтобы показывать каждую совпадающую строку, показывайте только имена файлов, содержащих цитату из блока.
Ваш шаблон: A. Regex vs B. Fixed String?
Что касается
-F
, это просто означает использование фиксированной строки вместо регулярного выражения для интерпретации шаблона. Источник здесь .
Еще одно полезное примечание, которое принадлежит сюда, вы можете добавить
-i
или
--ignore-case
быть к нечувствительнымрегистру .
Избавьтесь от этого глупого ведущего хеша коммита
sed "s/[^:]*://"
Источник .
Получите им уникальные пути!
| sort | uniq
Кому нужны дублированные пути? не ты, не я! Ой, смотрите, они тоже отсортированы! Наслаждаться. Источник: я. Я использовал это столько, сколько себя помню.(
man sort
а также
man uniq
)
А как насчет имен файлов без путей?
xargs basename
Вы могли бы подумать
| basename
будет работать, но нет. Он не принимает входной STDIN, но в качестве аргументов командной строки, вот объяснение этого.
basename
в основном возвращает основное имя файла без начального пути.
man basename
Вдохновения
- Посмотрите этот отличный альтернативный ответ .
- /questions/21916121/poisk-vsej-istorii-git-dlya-stroki/21916125#21916125
- /questions/17707197/tolko-imya-fajla-git-grep/17707200#17707200
vim-fugitive универсален для такого рода исследований в Vim.
использование :Ggrep
сделать это. Для получения дополнительной информации вы можете установить vim-fugitive и посмотреть турориал по :help Grep
, И этот эпизод: исследование-хранилище-истории-git-репозитория поможет вам сделать все это.
Если вы хотите найти конфиденциальные данные для того, чтобы удалить их из своей истории мерзавцев (именно поэтому я попал сюда), для этого есть инструменты. Github в качестве специальной страницы справки по этому вопросу.
Вот суть статьи:
BFG Repo-Cleaner - более быстрая и простая альтернатива git filter-branch для удаления нежелательных данных. Например, чтобы удалить файл с конфиденциальными данными и оставить ваш последний коммит без изменений), выполните:
bfg --delete-files YOUR-FILE-WITH-SENSITIVE-DATA
Чтобы заменить весь текст, указанный в файле passwords.txt, где бы он ни находился в истории вашего репозитория, запустите:
bfg --replace-text passwords.txt
См. Документацию BFG Repo-Cleaner для полного использования и инструкций по загрузке.