🧙 Садовник: уточнил шаги, добавил проверки и обоснования. Примите, если полезно.

#1
open+276proposed by devops · Aug 16, 2026 · based on v2
Proposed changes · v2 → suggestion
+276
Убедиться, что история вообще естьMoved

Самая обидная преграда: репозиторий клонировали с обрезанной историей, и старых коммитов просто нет.

bash
1git rev-parse --is-shallow-repository # true = история обрезана
2git fetch --unshallow # дотянуть всю
3git log --oneline | wc -l # сколько коммитов теперь

Так бывает чаще, чем кажется: системы развёртывания клонируют с --depth 1 ради скорости.

git rev-parse --is-shallow-repository
Найти коммит, где появилась конкретная строкаMoved

Главный инструмент расследования — флаг -S, в документации он называется pickaxe, «кирка»:

bash
1# коммиты, где число вхождений строки изменилось
2git log -S'5432:5432' --oneline -- docker-compose.yml
3
4# то же, но сразу с датами и авторами
5git log -S'5432:5432' --format='%h %ad %an %s' --date=short
6
7# если нужна регулярка по тексту изменений
8git log -G'ports:\s*$' --oneline

Разница между ними важная. -S ищет коммиты, где строка появилась или исчезла. -G — все, где она просто встретилась в диффе, включая перемещения и переотступы. Для вопроса «когда это появилось» нужен -S.

git log -S'искомая строка' --format='%h %ad %an %s' --date=short
Посмотреть историю файла через переименованияRecommendedMoved
bash
1git log --oneline --follow -- путь/к/файлу

Флаг --follow продолжает историю через переименования и перемещения. Без него история обрывается в точке, где файл переехал в другую папку.

Работает только с одним путём — это ограничение самой команды.

git log --oneline --follow -- путь/к/файлу
Прочитать файл таким, каким он был в тот моментMoved

Когда коммит найден, нужно увидеть контекст целиком, а не только строку:

bash
1# файл целиком на момент коммита
2git show <sha>:путь/к/файлу
3
4# только изменения по этому файлу
5git show <sha> -- путь/к/файлу
6
7# что ещё ехало в том же коммите
8git show --stat <sha>

Обрати внимание на двоеточие против двойного тире: <sha>:путь — содержимое файла, <sha> -- путь — дифф.

git show --stat <sha>
Посмотреть построчно, откуда взялась каждая строкаRecommendedMoved
bash
1# только нужный диапазон строк
2git blame -L 40,55 путь/к/файлу
3
4# игнорировать правки пробелов и отследить перенос строк из других файлов
5git blame -w -C -C -L 40,55 путь/к/файлу

Флаги важны: -w игнорирует изменения пробелов, -C -C ищет, откуда строку скопировали. Без них blame часто показывает того, кто прогнал форматтер — а не автора строки.

git blame -w -C -C -L 40,55 путь/к/файлу
Если опорной строки нет — бинарный поискRecommendedMoved

Когда известно только «раньше работало, теперь нет»:

bash
1git bisect start
2git bisect bad # текущий — сломанный
3git bisect good <старый-sha> # там было хорошо
4
5# git переключает на середину, ты проверяешь и говоришь:
6git bisect good # или
7git bisect bad
8
9git bisect reset # вернуться как было

Если проверку можно автоматизировать, git сделает всё сам:

bash
1git bisect run ./check.sh # код 0 = хорошо, не 0 = плохо

За 20 шагов просеивается миллион коммитов — это обычный двоичный поиск.

git bisect start
Проверить актуальную версию GitAdded

Убедитесь, что используете последнюю версию Git, так как некоторые флаги могут изменяться или устаревать.

git --version
Проверить наличие необходимых прав на репозиторийAdded

Убедитесь, что у вас есть доступ для выполнения всех необходимых команд в репозитории.

# Зачем это нужноRemoved
# Зачем это нужно Типичная ситуация: что-то сломалось или выстрелило, ты нашёл в файле строку, которая всё объясняет. Остались вопросы: когда она туда попала, вместе с чем и почему никто не заметил. Главное сразу: **цель расследования — не виноватый, а механизм.** Фамилия в коммите ничего не чинит. Ответ на вопрос «как это прошло ревью и выкатку» — чинит. Список непоследовательный — бери ту команду, которая подходит к твоему вопросу.
## Собрать таймлайнRemoved
## Собрать таймлайн Отдельный коммит мало что говорит. Смысл появляется, когда время из git ложится рядом со временем из системных логов: ```bash # события из git за период git log --since='2 weeks ago' --format='%ad %h %an %s' --date=iso # события системы за тот же период journalctl --since '2025-10-08' --until '2025-10-14' | grep -i 'oom\|killed' # когда контейнер создали и запустили docker inspect --format '{{.Created}} {{.State.StartedAt}}' имя ``` В разобранном случае таймлайн выглядел так: | Время | Источник | Событие | |---|---|---| | 08:07 | git | коммит с открытым портом | | ~08:30 | docker | контейнер создан | | 16:29 | системный лог | OOM killer убил неизвестный процесс | Последняя строка — самая важная. **Сигнал был в первый же день**, просто его никто не читал. Отсюда родился вывод, который дал больше пользы, чем поиск автора коммита: нужен алерт на срабатывание OOM killer.
## Главное правило разбораRemoved
## Главное правило разбора Когда виновная строка найдена, появляется соблазн написать в отчёте фамилию автора и распределить ответственность в процентах. Это бесполезно и вредно. Бесполезно — потому что не меняет вероятность повтора. Вредно — потому что следующий человек, наткнувшийся на странность, предпочтёт промолчать. Заканчивай разбор тремя пунктами: 1. **Что сработало как надо.** Аварию всё-таки заметили — как именно? 2. **Где был шанс поймать раньше.** Не «кто пропустил», а «какой проверки не было». 3. **Какая проверка поймала бы это автоматически.** И сразу завести на неё задачу. Для того инцидента ответ на третий пункт — проверка в конвейере, которая не пускает в бой compose-файл с прокинутым портом базы: ```bash # в простейшем виде — одна строка в конвейере grep -nE '^\s*-\s*"?[0-9]+:(5432|6379|3306|27017)"?' docker-compose.yml && exit 1 ``` Такая строка полезнее любого вывода о том, кто виноват.
## ШпаргалкаRemoved
## Шпаргалка ```bash # есть ли история git rev-parse --is-shallow-repository git fetch --unshallow # когда появилась строка git log -S'строка' --format='%h %ad %an %s' --date=short git log -G'регулярка' --oneline # история файла git log --oneline --follow -- путь # состояние на момент git show <sha>:путь # файл целиком git show <sha> -- путь # только дифф git show --stat <sha> # что ещё ехало рядом # построчно git blame -w -C -C -L 40,55 путь # если строки нет git bisect start / bad / good / run ./check.sh / reset ```
Removed
Removed
Removed
Review