Git log -S и -G: как найти коммит, изменивший нужный код

Git log -S и -G: как найти коммит, изменивший нужный код
Содержание статьи

Если вы помните строку кода, но не сообщение коммита, начните с git log -S или git log -G. Первый вариант ищет изменение количества вхождений строки, второй ищет строки патча, подходящие под регулярное выражение. Флаг --grep ищет в сообщениях коммитов, поэтому решает другую задачу.

В разборе Mentoring.digital используем только команды чтения истории. Они не переключают ветку и не меняют файлы рабочего каталога.

Найдите появление или исчезновение строки

git log --oneline -S"timeoutMs" -- src/client.js
git log -p -S"timeoutMs" -- src/client.js

Замените timeoutMs и src/client.js своими значениями. Первая команда покажет короткий список коммитов, вторая патчи. Разделитель -- отделяет путь от параметров и обозначений ревизий.

Ключевой нюанс: -S не означает «все коммиты, где эта строка встречалась». Если строку timeoutMs = 1000 заменили на timeoutMs = 2000, количество вхождений timeoutMs осталось прежним. Такой патч может не попасть в результат -S"timeoutMs".

Для изменения строки используйте -G

git log --oneline -G"timeoutMs[[:space:]]*=" -- src/client.js
git log -p -G"timeoutMs[[:space:]]*=" -- src/client.js

-G проверяет добавленные и удалённые строки патча по регулярному выражению. Поэтому замена числового значения в присваивании подходит под этот запрос. Сначала сделайте шаблон простым, затем уточняйте. Слишком узкое выражение может пропустить другое форматирование кода.

Если известна именно старая строка целиком, можно использовать -S"timeoutMs = 1000". Тогда изменение количества этого точного фрагмента станет сигналом. Поиск учитывает содержимое истории, а не смысл программы: одинаковый текст в комментарии тоже может совпасть.

Проверьте область поиска

git log --all --oneline -G"timeoutMs"
git log --all --oneline --grep="timeout"
git show COMMIT_HASH -- src/client.js

Без --all поиск обычно начинается от текущего HEAD. С --all рассматриваются локально известные ссылки. Это не скачивание истории с сервера. В неглубоком клоне или при отсутствии нужной удалённой ветки результат может быть неполным.

В последней команде замените COMMIT_HASH реальным хешем из результата. Просмотрите автора, дату, сообщение и изменения вокруг совпавшей строки. Найденный коммит ещё не доказывает причину ошибки: проверьте связанный код и условия воспроизведения.

Небольшое упражнение на различие флагов

В отдельном учебном репозитории создайте три последовательных коммита: сначала добавьте timeoutMs = 1000, затем замените 1000 на 2000, затем удалите строку. Назовите сообщения произвольно, без слова timeout.

  • -S"timeoutMs" должен обнаружить добавление и удаление, но не простую замену числа.
  • -G"timeoutMs" должен обнаружить все три изменения.
  • --grep="timeout" не должен найти эти коммиты по сообщениям.

Если файл переименовали, попробуйте --follow с единственным путём и внимательно смотрите патчи. История слияний также требует отдельного внимания: обычный вывод не равен доказательству отсутствия изменений во всех родителях merge-коммита.

Для системного освоения истории и веток подойдёт курс Git с практикой. Если ищете источник регрессии, покажите наставнику по Git известный исправный сценарий, ошибку и найденные патчи.

Похожие статьи по данной теме