linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it works
  • Уроки
  • База знаний
  • Собеседование
Cluster

← все кластеры

Восстановление и археология истории

Reflog как машина времени, bisect для поиска коммита-виновника, blame с его ограничениями, rev-parse как универсальный резолвер ссылок и cat-file для чтения объектов вручную. Это блок, где сразу видно «работал руками с инцидентами» vs «читал учебник».

6 вопросов · ~30 мин чтения

Questions

На этой странице

  1. 01Что такое reflog, как им пользоваться и сколько живут записи?
  2. 02Bisect: как находит коммит-виновник? Когда его использовать?
  3. 03Что показывает `git blame` и какие у него ограничения?
  4. 04Удалил ветку через `git branch -D`, ещё не push'ил коммиты. Как восстановить?
  5. 05Зачем нужен `git rev-parse` и какие виды ссылок он разрешает?
  6. 06`git cat-file -p` - зачем читать объекты руками?

#git-reflog-time-machine

juniorчасто

Что такое reflog, как им пользоваться и сколько живут записи?

Что отвечать

Reflog - локальный лог перемещений HEAD и ref'ов: каждый раз когда ветка двигается (commit, reset, rebase, checkout), Git пишет запись в `.git/logs/HEAD` и `.git/logs/refs/heads/<branch>`. `git reflog` показывает «где я был», `HEAD@{2}` это «два шага назад». Записи живут по умолчанию 90 дней для достижимых и 30 дней для недостижимых, чистятся через `git gc`. **Это только локально**, на сервере reflog обычно нет.

Что хотят услышать

Кандидат должен: - назвать reflog как спасение после `reset --hard`, неудачного rebase, accidental `branch -D` - показать workflow восстановления: `git reflog` → найти SHA → `git checkout -b restored <sha>` или `git reset --hard <sha>` - объяснить что reflog ЛОКАЛЕН - если коллега force-push'нул в main, у тебя есть твой reflog (пока не сделал gc), у него свой, но на сервере истории нет - назвать настройки `gc.reflogExpire` (90 дней) и `gc.reflogExpireUnreachable` (30 дней) и `git gc --prune=now` как способ зачистить (или наоборот сохранить) - упомянуть `git reflog <branch>` для просмотра reflog конкретной ветки, не только HEAD

Подводные камни

  • ✗ Думать что reflog есть на сервере - нет, на bare-репо обычно отключён
  • ✗ Сделать `git gc --prune=now --aggressive` сразу после факапа - можешь снести то что хотел восстановить
  • ✗ Полагаться на reflog через 3 месяца - запись скорее всего уже expired и забрана gc

Follow-up

  • ? Как настроить чтобы reflog никогда не expired?
  • ? Что покажет `git reflog refs/heads/main`?
  • ? Почему reflog не помогает другим разработчикам после твоего force-push?

Глубина в базе знаний

  • git reflog
  • Commit
tags: recovery, reflog, safety

#git-bisect-find-bad-commit

intermediateчасто

Bisect: как находит коммит-виновник? Когда его использовать?

Что отвечать

Бинарный поиск по истории. `git bisect start` → `git bisect bad` (сейчас сломано) → `git bisect good <старый-sha>` (там работало). Git ставит тебя на середину диапазона, ты проверяешь, говоришь `git bisect good` или `bad`, и так log2(N) шагов. Конец: `git bisect reset`. Когда: регрессия появилась «где-то между релизами», коммитов много, проще найти точку чем читать diff.

Что хотят услышать

Senior должен: - назвать сложность log2(N) - 1000 коммитов это 10 шагов - сказать что bisect работает только если **каждый коммит собирается и тест может его проверить** - иначе ложно-плохой коммит ломает бинпоиск - назвать `git bisect run <script>` для автоматизации: скрипт возвращает 0 - good, 1-127 (кроме 125) - bad, 125 - skip - упомянуть `git bisect skip` для коммитов которые не собираются или не относятся к делу (Git попробует ещё) - сказать что bisect не подходит для коммитов с тонкими взаимными зависимостями (например `feature_flag = false` + код за флагом)

Подводные камни

  • ✗ Запустить bisect на репо с broken-коммитами - бинпоиск даст ложный результат, нужно `git bisect skip`
  • ✗ Забыть `git bisect reset` в конце - застрянешь в bisect-режиме, любая команда будет ругаться
  • ✗ Делать bisect руками когда есть тест - быстрее `git bisect run`

Follow-up

  • ? Чем `git bisect skip` отличается от `bad`/`good`?
  • ? Как написать bisect-run скрипт для проверки регрессии?
  • ? Что произойдёт если тест сам по себе flaky?

Глубина в базе знаний

  • git bisect
  • Commit
  • Атомарный коммит
tags: recovery, bisect, debugging

#git-blame-limitations

intermediateиногда

Что показывает `git blame` и какие у него ограничения?

Что отвечать

Для каждой строки файла - коммит, который её последним менял, автор и дата. Ограничения: не отличает переименование файла (теряет связь), не отличает перенос блока кода в другой файл, шумит на reformatting-коммитах (forall lines: тот коммит). Лечится флагами: `-w` игнорирует whitespace, `-M` детектит move внутри файла, `-C` детектит copy между файлами, `--ignore-rev <sha>` пропускает шумные коммиты (например, после migration на prettier).

Что хотят услышать

Senior должен: - назвать `-w -M -C` как стандартный набор для blame в больших проектах с историей рефакторингов - сказать про `.git-blame-ignore-revs` файл: список SHA «шумных» коммитов которые надо игнорировать, GitHub его подхватывает автоматически в UI - упомянуть `git log -L :func_name:file.c` как альтернативу blame для отслеживания истории конкретной функции - назвать что blame полезен для understanding-зачем, не для обвинения-кого: «зачем эта строка тут» а не «кто виноват» - сказать что blame через UI GitHub есть, но без `-w -M -C` - качество хуже, чем локально

Подводные камни

  • ✗ Делать blame без `-w` и думать что reformatting-коммит «кто-то всё переписал»
  • ✗ Использовать blame для blame-обвинения - команда быстро устаёт
  • ✗ Не настраивать `.git-blame-ignore-revs` после массового refactor - blame в UI будет неюзабельным

Follow-up

  • ? Как настроить `.git-blame-ignore-revs` чтобы прятать коммит prettier-миграции?
  • ? Чем `git log -L` лучше blame для отслеживания функции?
  • ? Что покажет `git blame -C -C -C file.c`?

Глубина в базе знаний

  • git blame
  • git log
tags: recovery, blame, archaeology

#git-restore-deleted-branch

intermediateчасто

Удалил ветку через `git branch -D`, ещё не push'ил коммиты. Как восстановить?

Что отвечать

Через reflog. `git reflog` (или конкретно `git reflog --date=iso --all`) покажет последнее место где была ветка - перед удалением там была запись «checkout: moving to ...». Бери SHA tip-коммита удалённой ветки и делай `git checkout -b restored-feature <sha>`. Если reflog уже не содержит этот SHA - помогает `git fsck --lost-found`, который ищет «dangling commits» в `.git/objects/`.

Что хотят услышать

Senior должен: - первой командой назвать `git reflog`, не fsck - reflog работает пока gc не пробежал - сказать что коммиты не удаляются физически при `branch -D` - просто пропадает ref на них, объекты остаются «dangling» до gc - назвать `git fsck --lost-found` как fallback когда reflog уже потерян (или для веток, которые ты лично не трогал) - упомянуть что после force-push в main можно восстановить старую историю из локального reflog любого разработчика, который раньше её fetch'нул - его reflog содержит старые SHA - сказать что `git reflog` принимает время: `HEAD@{yesterday}`, `HEAD@{2.hours.ago}` - удобно когда не помнишь сколько шагов

Подводные камни

  • ✗ Сделать `git gc --prune=now` сразу после `branch -D` - можешь снести dangling-коммиты которые fsck бы нашёл
  • ✗ Думать что `branch -D` физически стирает объекты - не стирает, до gc они достижимы через reflog
  • ✗ Полагаться на fsck без reflog через месяц - дефолтный gc уже пробежал, объектов нет

Follow-up

  • ? Что покажет `git fsck --lost-found` после `branch -D`?
  • ? Как восстановить ветку которая была force-push'нута неделю назад?
  • ? Чем `HEAD@{yesterday}` удобнее `HEAD@{42}` для восстановления?

Глубина в базе знаний

  • git reflog
  • Ветка (branch)
tags: recovery, reflog, fsck

#git-rev-parse-universal

seniorредко

Зачем нужен `git rev-parse` и какие виды ссылок он разрешает?

Что отвечать

Универсальный «резолвер» любой ссылки в SHA. `git rev-parse HEAD`, `git rev-parse main`, `git rev-parse origin/main~3`, `git rev-parse v1.2.3^{commit}`, `git rev-parse :/fix login` (поиск по сообщению коммита) - всё это даёт 40-символьный SHA. Используется в скриптах чтобы получить полный SHA для дальнейших команд. Плюс много утилитарного: `--show-toplevel` (корень репо), `--git-dir` (путь к `.git/`), `--abbrev-ref HEAD` (имя текущей ветки).

Что хотят услышать

Senior должен: - назвать `rev-parse` как «лучшая команда для скриптов» - работает с любой формой ссылки - перечислить нотации: `~N` (N коммитов назад по первому родителю), `^N` (N-ый родитель merge-коммита), `^{tree}`/`^{commit}`/ `^{tag}` (peel до нужного типа), `@{N}` (N-ая запись reflog), `@{u}` (upstream) - назвать утилитарные флаги: `--show-toplevel`, `--git-dir`, `--show-cdup`, `--abbrev-ref` - всё что нужно для скрипта который не должен зависеть от cwd - упомянуть `git rev-parse --verify <ref>` как способ проверить что ссылка валидна, не вернув мусор (exit 0/1) - сказать что `git rev-parse` дешевле чем `git log -1 --format=%H`, потому что не строит лог

Подводные камни

  • ✗ Парсить вывод `git log` regex'ом вместо `git rev-parse` - хрупко
  • ✗ Перепутать `^` (родитель) и `^{commit}` (peel до типа) - синтаксис похожий, смысл разный
  • ✗ Не использовать `--verify` в скрипте - получаешь мусорный SHA при опечатке в ref'е

Follow-up

  • ? Что вернёт `git rev-parse HEAD^2` на не-merge коммите?
  • ? Чем `git rev-parse --show-toplevel` лучше `pwd` в скрипте?
  • ? Как с помощью rev-parse найти коммит по подстроке в сообщении?

Глубина в базе знаний

  • git rev-parse
  • git reflog
tags: recovery, plumbing, scripting

#git-cat-file-read-objects

seniorредко

`git cat-file -p` - зачем читать объекты руками?

Что отвечать

Чтобы понять что внутри коммита/tree/blob без посредников. `git cat-file -t <sha>` показывает тип, `-p <sha>` распаковывает и печатает: blob - содержимое файла, tree - список записей с правами и SHA, commit - tree+parent+author+committer+message, tag - обёрнутый коммит с подписью. Полезно при дебаге странного поведения («почему этот коммит видит файл которого не должно быть»), при объяснении объектной модели стажёру, и при ручном разборе packfile-проблем.

Что хотят услышать

Senior должен: - назвать четыре типа объектов и что для каждого покажет `-p` - продемонстрировать `git cat-file -p HEAD^{tree}` для просмотра что лежит в корневом дереве коммита - упомянуть `git cat-file --batch-check` для массовой проверки существования и типа объектов (используется в скриптах для GC и audit'а) - сказать что `cat-file` обходит alternate-objects (`info/alternates`) и shared-pack'и - видит всё что Git считает доступным - назвать что вместе с `git ls-tree -r HEAD` (рекурсивный обход tree) `cat-file` даёт полный контроль над объектами без выхода в plumbing-команды low-level библиотек

Подводные камни

  • ✗ Думать что `-p` работает только на blob - работает на любом типе, формат вывода разный
  • ✗ Перепутать SHA коммита и SHA tree - `git cat-file -p HEAD` это commit, `git cat-file -p HEAD^{tree}` это tree
  • ✗ Использовать `cat-file` на abbreviated SHA в скрипте без `--verify` - при коллизии короткого префикса будет ошибка

Follow-up

  • ? Что покажет `git ls-tree -r HEAD` и чем это отличается от `cat-file -p`?
  • ? Как через `cat-file` посмотреть размер объекта без распаковки?
  • ? Зачем нужен `--batch` режим cat-file?

Глубина в базе знаний

  • git cat-file
  • Blob
  • Tree
  • Commit
tags: recovery, plumbing, debuggingbook: edu/Git_book/03-object-model.md
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.