$ sudo teach IT
Модуль 7 · Чистая история · Урок 7.3

Поиск по истории

Вы научитесь находить, когда и в каком коммите менялась строка, и вычислите коммит, который сломал ссылку, через git bisect.

Теория + практика~20 минутНовичокgit logblamebisect

Фильтры git log

Поиск по истории Git — это способ узнать, когда, кем и зачем изменили строку и в каком коммите появилась ошибка; для этого есть фильтры git log, команды git blame и git bisect. Вы найдёте коммит, который сломал ссылку «Все мои проекты», тремя разными способами.

История проекта теперь чистая, и пора ею воспользоваться. Помните ссылку, которую вы чинили через cherry-pick? Починить — полдела. Хочется понять, где именно она сломалась, чтобы такое не повторилось.

Простыми словами: git log без фильтров — это вся переписка в мессенджере за год. Фильтры — поиск по ней: «сообщения от Пети», «за прошлую неделю», «где упоминается слово отпуск». Всё это флаги одной команды, их можно сочетать.

ФлагЧто оставляет в списке
--author="Алекс"Коммиты, где имя или почта автора содержат эту строку
--since="2026-11-16 00:00"Коммиты не старше этой даты; можно и --since="2 weeks ago"
-- index.htmlКоммиты, которые меняли этот файл (пробел после -- обязателен)
--grep="ссылк"Коммиты, в сообщении которых есть этот текст
-S "project.html"Коммиты, после которых этот текст стал встречаться в файлах чаще или реже
--no-mergesБез merge-коммитов, только «настоящие» изменения
Терминал
$ git log --oneline --no-merges --since="2026-11-16 00:00"
ebb2e91 Сделать ссылки светлее в тёмной теме
08ddbf0 Добавить тёмную тему
1bf90b5 Исправить ссылку на проекты
60a9824 Оформить ссылки
$ git log --oneline --no-merges --grep="ссылк"
ebb2e91 Сделать ссылки светлее в тёмной теме
1bf90b5 Исправить ссылку на проекты
60a9824 Оформить ссылки
28c6c68 Добавить ссылку на GitHub в контакты
6b82c9b Добавить ссылку на сайт в README
55c1edd Покрасить ссылки в синий
68734ed Добавить ссылку на страницу проектов

Разбор по строкам

  • --since="2026-11-16 00:00" — всё, что сделано с 16 ноября; у вас даты свои. Время лучше указать: без него Git подставит текущее время суток.
  • --grep="ссылк" — ищем по части слова, чтобы найти и «ссылку», и «ссылки». Поиск различает заглавные и строчные буквы.

Самый сильный фильтр — -S (его называют «кирка», pickaxe). Он ищет не в сообщениях, а в самих изменениях: в каких коммитах строка project.html появилась или исчезла.

Терминал
$ git log --oneline -S "project.html"
1bf90b5 Исправить ссылку на проекты
60a9824 Оформить ссылки

Разбор по строкам

  • 1bf90b5 Исправить ссылку на проекты — здесь ошибочный адрес исчез — это ваше исправление.
  • 60a9824 Оформить ссылки — а здесь он появился. Подозреваемый найден.
Терминал
$ git show 60a9824 -- index.html
...
-    <p><a href="projects.html">Все проекты</a></p>
+    <p><a href="project.html">Все мои проекты</a></p>

Коллега менял текст ссылки и, перепечатывая строку, потерял букву s. Запись git show <хеш> -- index.html показывает изменения коммита только в одном файле. Подробно о фильтрах — git log.

git blame

Другой вопрос: кто и в каком коммите последним менял конкретную строку? Это как история правок ячейки в общей таблице. Команда называется git blame (дословно «обвинить», но о культуре чуть ниже):

Терминал
$ git blame -L 15,24 index.html
cb00bb89 (Алекс Иванов 2026-11-10 11:00:00 +0300 15)   <section id="projects">
cb00bb89 (Алекс Иванов 2026-11-10 11:00:00 +0300 16)     <h2>Мои проекты</h2>
cb00bb89 (Алекс Иванов 2026-11-10 11:00:00 +0300 17)     <ul>
cb00bb89 (Алекс Иванов 2026-11-10 11:00:00 +0300 18)       <li>Сайт-визитка</li>
cb00bb89 (Алекс Иванов 2026-11-10 11:00:00 +0300 19)       <li>Список дел</li>
e6267318 (Алекс Иванов 2026-11-12 14:00:00 +0300 20)       <li>Игра «Угадай число»</li>
52b34afa (Алекс Иванов 2026-11-12 13:00:00 +0300 21)       <li>Калькулятор</li>
cb00bb89 (Алекс Иванов 2026-11-10 11:00:00 +0300 22)     </ul>
1bf90b5a (Алекс Иванов 2026-11-16 15:00:00 +0300 23)     <p><a href="projects.html">Все мои проекты</a></p>
cb00bb89 (Алекс Иванов 2026-11-10 11:00:00 +0300 24)   </section>

Разбор по строкам

  • -L 15,24 — показать только строки с 15-й по 24-ю (у вас номера могут быть другими: смотрите строку со ссылкой).
  • cb00bb89 — хеш коммита, который последним менял строку (blame показывает 8 символов).
  • (Алекс Иванов 2026-11-10 11:00:00 +0300 15) — автор, дата этого коммита и номер строки.
  • 1bf90b5a ... 23) — строку со ссылкой последним менял коммит исправления, а не коммит, который её сломал.

Последний пункт важен: blame показывает последнее изменение строки. Чтобы заглянуть глубже, спросите, какой строка была до исправления — добавьте коммит перед ним (~1, как в HEAD~1):

Терминал
$ git blame -L 23,23 1bf90b5~1 -- index.html
60a98242 (Коллега 2026-11-16 12:00:00 +0300 23)     <p><a href="project.html">Все мои проекты</a></p>

На GitHub то же самое без терминала: откройте файл в репозитории и над его содержимым нажмите Blame. Строки сгруппируются по коммитам с автором и датой, а значок рядом с коммитом с подсказкой «View blame prior to this change» (показать blame до этого изменения) делает то же, что наш ~1. Вернуться к обычному виду — кнопка Code.

blame ищет причину, а не виноватого

Несмотря на название, в хороших командах blame открывают, чтобы найти коммит и прочитать, зачем строку поменяли, а не чтобы кого-то отругать. Ошибаются все; важно, что история помогает быстро понять и исправить.

git bisect

-S и blame работают, когда вы знаете, какой текст искать. А если известен только симптом: «раньше работало, теперь нет», и непонятно, какая строка виновата? Тогда помогает git bisect — бинарный поиск по истории.

Простыми словами: это игра «угадай число от 1 до 100». Вы не перебираете числа по одному, а спрашиваете «больше 50?» и каждый ответ отсекает половину. Git так же берёт коммит посередине между «точно работало» (good) и «уже сломано» (bad), вы проверяете его и отвечаете. Из 100 коммитов виновный находится примерно за 7 проверок.

Терминал
$ git bisect start
status: waiting for both good and bad commits
$ git bisect bad 1bf90b5~1
status: waiting for good commit(s), bad commit known
$ git bisect good 68734ed
Bisecting: 3 revisions left to test after this (roughly 2 steps)
[5c6bd94017a4099fc883a2a6224d2d8c3219548e] Merge pull request #2 from alex-ivanov/feature/about-skills

Разбор по строкам

  • git bisect start — начать поиск; Git ждёт отметок good и bad.
  • git bisect bad 1bf90b5~1 — коммит перед исправлением точно сломан.
  • git bisect good 68734ed — коммит, где ссылку добавили, точно работал.
  • Bisecting: 3 revisions left to test after this (roughly 2 steps) — «после этой проверки останется 3 коммита, примерно 2 шага». В примере история короче вашей: у вас коммитов между good и bad больше, и шагов будет 4–5.
  • [5c6bd94...] Merge pull request #2 ... — Git переключил рабочую папку на коммит посередине. Проверяйте его.

Проверка у нас простая — посмотреть адрес в ссылке. Сайт можно и открыть в браузере: файлы в папке сейчас ровно такие, какими были в этом коммите.

Терминал
$ grep "проекты</a>" index.html
    <p><a href="projects.html">Все проекты</a></p>
$ git bisect good
Bisecting: 1 revision left to test after this (roughly 1 step)
[31583dccc17ea90622d16c9d5d15beb004d5001b] Merge pull request #6 from alex-ivanov/feature/colleague-footer
$ grep "проекты</a>" index.html
    <p><a href="projects.html">Все проекты</a></p>
$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[60a982425a79147f20a29918b62c588a9b180785] Оформить ссылки
$ grep "проекты</a>" index.html
    <p><a href="project.html">Все мои проекты</a></p>
$ git bisect bad
60a982425a79147f20a29918b62c588a9b180785 is the first bad commit
commit 60a982425a79147f20a29918b62c588a9b180785
Author: Коллега <colleague@example.com>
Date:   Mon Nov 16 12:00:00 2026 +0300

    Оформить ссылки

 index.html | 2 +-
 style.css  | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

Разбор по строкам

  • grep "проекты</a>" index.html — grep печатает строки файла, где есть этот текст: так видно адрес ссылки.
  • git bisect good / git bisect bad — ваш ответ про текущий коммит; Git сразу переходит к следующему.
  • ... is the first bad commit — «это первый плохой коммит» — тот же 60a9824, что нашёл -S.

Во время поиска вы не на ветке: git status пишет HEAD detached at … и You are currently bisecting, started from branch 'main'. Когда виновный найден, обязательно вернитесь:

Терминал
$ git bisect reset
Previous HEAD position was 60a9824 Оформить ссылки
Switched to branch 'main'
Your branch is up to date with 'origin/main'.

Проверку можно отдать Git

Если проверку умеет делать команда, git bisect run <команда> пройдёт все шаги сама: успешное завершение команды Git считает good, ошибку — bad. Новичку достаточно ручного режима. Подробно — git bisect.

Хорошие сообщения окупаются

Посмотрите на найденный коммит глазами следователя. Сообщение «Оформить ссылки» обещает стиль ссылок, а внутри ещё и правка адреса в index.html. Будь это два коммита — «Сделать ссылки темнее» и «Переименовать ссылку на проекты», — ошибка бросилась бы в глаза ещё на ревью. Правило «одна мысль — один коммит» нужно как раз для таких дней.

Второе: сообщение должно говорить не только что, но и зачем. «Что» видно в diff, а «зачем» знаете только вы и только сейчас. Подробное пояснение пишут вторым абзацем; в терминале его добавляет второй флаг -m:

Терминал
$ git commit -m "Переименовать ссылку на проекты" -m "Текст «Все мои проекты» понятнее на телефоне."

Первый -m — заголовок, его показывает git log --oneline; второй — пояснение, оно видно в полном git log и в git show.

Практика у себя

В ~/projects/portfolio, ветка main, git status чист. Подставляйте свои хеши.

Шаг 1. Найдите коммиты, которые меняли index.html: git log --oneline --no-merges -- index.html. В списке есть коммит коллеги Оформить ссылки и ваш Исправить ссылку на проекты.

Шаг 2. Найдите, где ошибочный адрес появился и исчез: git log --oneline -S "project.html". Две строки: исправление и Оформить ссылки. Посмотрите изменение: git show <хеш «Оформить ссылки»> -- index.html.

Шаг 3. Посмотрите blame строки со ссылкой: git blame index.html, найдите строку «Все мои проекты» — там хеш исправления. Затем git blame <хеш исправления>~1 -- index.html — та же строка с project.html и хешем коллеги.

Шаг 4. На GitHub откройте index.html и нажмите Blame. Найдите ту же строку и коммит рядом с ней.

Шаг 5. Теперь притворимся, что ответа не знаем, и пройдём bisect. Хеш для good — нижняя строка вывода git log --oneline -S "projects.html" -- index.html (коммит, где ссылка появилась; подпись у вас может быть своя):

Терминал
$ git log --oneline -S "projects.html" -- index.html
1bf90b5 Исправить ссылку на проекты
60a9824 Оформить ссылки
68734ed Добавить ссылку на страницу проектов
$ git bisect start
$ git bisect bad 1bf90b5~1
$ git bisect good 68734ed

Шаг 6. На каждом шаге выполняйте grep "проекты</a>" index.html. В адресе projects.html — отвечайте git bisect good; project.html — git bisect bad. Если ссылки в файле нет совсем (коммит из ветки, где её ещё не было), поломки тоже нет: good. Число шагов зависит от вашей истории.

Шаг 7. Когда появится is the first bad commit, сверьте хеш с шагом 2 и выполните git bisect reset.

Проверьте себя

  • git bisect назвал тот же коммит, что и git log -S "project.html", — Оформить ссылки.
  • После git bisect reset команда git status пишет On branch main и не упоминает bisecting.
  • Вы можете объяснить, почему git blame на текущей версии показывает коммит исправления, а не коммит с ошибкой.
  • Вы знаете, где на GitHub кнопка Blame.

Частые ошибки

Забыли git bisect reset. Вы остались в detached HEAD на старом коммите: правки и коммиты «повиснут» вне ветки, а git status напоминает You are currently bisecting. Выполните git bisect reset — вернётесь на ветку, с которой начали.

Ошиблись с ответом good/bad. Bisect доверяет вам и найдёт не тот коммит. Начните заново: git bisect reset, затем снова start, bad, good.

blame «врёт». Он показывает последнее изменение строки, а не то, где появилась ошибка. Смотрите на строку до этого коммита (<хеш>~1 или «View blame prior to this change» на GitHub) либо ищите через -S.

-S или --grep ничего не нашли. Оба различают регистр и ищут точный текст. Сократите запрос до надёжной части слова и проверьте кавычки.

blame как поиск виноватого. Отправить коллеге «это ты сломал» — плохая идея. Лучше: «нашёл коммит, где поменялась ссылка, давай посмотрим вместе».

Что важно запомнить

  • Фильтры git log: --author, --since, -- файл, --grep (по сообщениям), -S (по изменениям), --no-merges.
  • git blame файл — кто и в каком коммите последним менял каждую строку; на GitHub — кнопка Blame.
  • git bisect: start, bad, good, проверка и ответ на каждом шаге, в конце обязательно reset.
  • Маленькие коммиты с понятным «зачем» превращают поиск ошибки из детектива в пару команд.

Вы умеете вести чистую историю и искать по ней. Осталось отметить в этой истории важную точку: «вот версия, которую не стыдно показать». В практикуме вы выпустите первую версию сайта: напишете CHANGELOG, поставите тег v1.0.0 и опубликуете релиз на GitHub.

На следующий урок