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

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

Переписывание истории

amend, interactive rebase, git filter-repo, force-push. Когда переписать историю безопасно, как не сломать коллегам копии и почему filter-branch больше не используют. Senior-вопросы: что делать когда переписывание уже случилось и команда страдает.

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

Questions

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

  1. 01Когда `git commit --amend` безопасен, а когда нет?
  2. 02Как переписать серию коммитов в feature-ветке перед PR?
  3. 03Случайно закоммитили `.env` с секретом в публичный репо месяц назад. Как вычистить?
  4. 04Как договориться в команде перед переписыванием истории на shared-ветке?
  5. 05Я force-push'нул, теперь у коллеги в `git log` мои старые коммиты + мои новые. Что произошло и как починить?

#git-amend-safe-or-not

juniorчасто

Когда `git commit --amend` безопасен, а когда нет?

Что отвечать

Безопасен на **локальном коммите, который ещё не пушнут**. Amend создаёт новый коммит с новым SHA (старый становится dangling) - физически это replace, не edit. Опасен на пушнутом коммите: после amend нужен force-push, и если коллега уже базируется на старом SHA - его коммиты осиротеют. Ещё опасен с `--no-edit` без сознания что меняешь автора/timestamp: amend подменяет committer-данные, author остаётся, что может путать в blame.

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

Senior должен: - объяснить что amend это **технически новый коммит**, не правка существующего - SHA меняется - назвать конкретный safe-кейс: «забыл добавить файл / опечатка в сообщении, ещё не пушнут» → `git add forgot.txt && git commit --amend --no-edit` - сказать что после amend пушнутого коммита нужен `git push --force-with-lease`, и если кто-то уже забрал старый SHA - он получит развалившуюся историю - упомянуть `git commit --amend --reset-author` для случая когда специально хочешь обновить authorstamp - назвать `git commit --fixup=<sha>` + `git rebase -i --autosquash` как более структурированный amend для не-последнего коммита

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

  • ✗ Сделать amend на пушнутом коммите без согласования - коллеги получат развалившуюся ветку
  • ✗ Думать что `--no-edit` означает «ничего не меняется» - SHA всё равно новый
  • ✗ Сделать amend и затем `git push` без force - получишь rejected, потом панически делаешь `git pull` и вытаскиваешь обратно старый коммит как merge

Follow-up

  • ? Что вернёт `git log` после amend - старый и новый коммит или только новый?
  • ? Чем `git commit --amend --reset-author` отличается от обычного amend?
  • ? Когда выбрать `git commit --fixup=<sha>` вместо amend?

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

  • git commit --amend
  • Commit
  • Force push
tags: rewriting, amend, safety

#git-rebase-interactive-rewrite

intermediateчасто

Как переписать серию коммитов в feature-ветке перед PR?

Что отвечать

`git rebase -i origin/main` - откроется редактор с твоими коммитами от main до HEAD. Меняешь `pick` на `fixup` где надо схлопнуть, на `reword` где надо переписать сообщение, на `edit` где надо остановиться и подправить содержимое. Переставляешь строки - меняется порядок. Закрываешь редактор - Git применяет один за другим. Если конфликт - `git rebase --continue` после resolve, или `git rebase --abort` чтобы отменить всё.

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

Senior должен: - описать конкретный сценарий: 5 коммитов вида `wip`, `fix typo`, `address review` → один атомарный коммит + один атомарный + реальная feature - назвать `--autosquash` + предварительные `git commit --fixup=<sha>` как самый аккуратный workflow: коммитишь правки сразу нацеленными, потом одна команда схлопывает - сказать что после rebase нужен force-push (на feature-ветке - ок, `--force-with-lease`) - упомянуть что `exec <cmd>` в todo-листе позволяет вставить проверку: например `pick A` / `exec npm test` / `pick B` - если тесты упадут, rebase остановится - назвать `git rebase --abort` как «safety net» если запутался

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

  • ✗ Сделать rebase -i на ветке, которую ещё несколько разработчиков забрали - после force-push у них развалится
  • ✗ Закрыть редактор с пустым списком коммитов случайно - Git считает что хочешь удалить всё, ветка опустеет
  • ✗ Запустить rebase из грязного working tree - первый же конфликт смешается с локальными правками

Follow-up

  • ? Что делает `--autosquash` с коммитами с префиксом `fixup!`?
  • ? Как через rebase -i перенести коммит из середины в начало?
  • ? Что покажет `git status` посреди interactive rebase с конфликтом?

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

  • git rebase
  • Interactive rebase
  • git commit --amend
  • Force push
tags: rewriting, rebase, prep

#git-filter-repo-secrets

seniorиногда

Случайно закоммитили `.env` с секретом в публичный репо месяц назад. Как вычистить?

Что отвечать

`git filter-repo --invert-paths --path .env` (или `--path-glob '*.env'`). Это перепишет всю историю удалив файл из каждого коммита, **поменяет SHA всех коммитов которые трогали этот файл**, и потребует `git push --force` на все ветки и теги. Дальше важное: **ротировать секрет**. Удаление из истории не помогает - его уже видели/скачали/закэшировал GitHub. Filter-repo это очистка, не лечение.

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

Senior должен: - назвать `git filter-repo` а **не** `git filter-branch` - последний deprecated с 2022, медленный и баговый - подчеркнуть что чистка истории = переписывание SHA = force-push всех веток и тегов + просьба всем разработчикам переклонировать репо - сказать что **ротация секрета обязательна и первоочередна**, чистка истории это уборка, не предотвращение - упомянуть что GitHub кэширует все коммиты включая force-push'нутые: `https://github.com/<repo>/commit/<old-sha>` остаётся доступным ещё долго, плюс forks хранят свою копию - назвать `git filter-repo --replace-text` для замены значения (например на `***REDACTED***`) когда полное удаление файла нежелательно - сказать что `BFG Repo-Cleaner` это популярная альтернатива, но filter-repo сейчас официальный рекомендуемый инструмент

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

  • ✗ Использовать `git filter-branch` - он deprecated, filter-repo это замена
  • ✗ Сделать filter-repo и не ротировать секрет - утечка не закрыта, файл уже скачан
  • ✗ Думать что force-push в main закроет коммит на GitHub - старый SHA остаётся доступным по прямой ссылке
  • ✗ Не уведомить команду перед force-push - все получат сломанные локальные клоны

Follow-up

  • ? Чем `git filter-repo` лучше `git filter-branch`?
  • ? Что делать с PR в которых был этот секрет до удаления?
  • ? Как использовать `--replace-text` для скрытия значений без удаления файла?

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

  • git filter-repo: переписывание истории
  • Force push
  • Поиск секретов в репозитории
tags: rewriting, filter-repo, security

#git-coordinate-team-rewrite

seniorредко

Как договориться в команде перед переписыванием истории на shared-ветке?

Что отвечать

Сначала: проверить что переписывание реально нужно (часто можно обойтись revert-коммитом или отдельной cleanup-веткой). Если нужно: назначить время (например пятница вечер), уведомить всех явно (Slack, email - не только PR-описание), все коммитят и пушат свою работу. После rewriter'а: написать «история переписана, переклонируйте или сделайте `git fetch && git reset --hard origin/<branch>`». Reset, не pull - pull нарисует дубли.

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

Senior должен: - первым делом задать вопрос «можно ли revert'ом обойтись» - revert это новый коммит, не переписывание, безопасен - назвать конкретный recovery-протокол для коллег: `git fetch --all` → `git reset --hard origin/<branch>` (не `pull` - pull попытается merge'нуть и сделает кашу) - упомянуть что незакоммиченная локальная работа должна сохраниться через `git stash` или отдельную ветку **до** reset - сказать что для длинноживущих веток (main, release) такой манёвр требует «freeze window» и часто координацию с CI/CD - назвать ADR / RFC / postmortem как обязательный артефакт после rewrite - иначе через полгода никто не помнит почему SHA скачут

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

  • ✗ Переписать историю «втихую» в надежде что никто не заметит - заметят через сломанные локальные клоны и потерянную работу
  • ✗ Сказать «делайте `git pull`» вместо `git reset --hard` - pull сделает merge между старой и новой историей
  • ✗ Не сохранить локальную работу коллег перед reset - потеряют незакоммиченные правки

Follow-up

  • ? Когда revert-коммит лучше rewrite?
  • ? Что произойдёт у коллеги который сделал `git pull` вместо reset после твоего force-push?
  • ? Как восстановить работу коллеги из его reflog после rewrite?

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

  • Force push
  • git rebase
  • git reflog
tags: rewriting, team, coordination

#git-lost-commits-after-rewrite

seniorиногда

Я force-push'нул, теперь у коллеги в `git log` мои старые коммиты + мои новые. Что произошло и как починить?

Что отвечать

Коллега сделал `git pull` (не reset) после твоего force-push. Pull = fetch + merge: его локальная ветка с твоими старыми коммитами слилась с remote-веткой с твоими новыми коммитами. Получился merge-коммит, который объединил две истории - твою выкинутую и твою новую. Лечение: коллега делает `git reset --hard origin/<branch>` (после сохранения своей незакоммиченной работы). В будущем: `git config pull.ff only` чтобы pull не делал merge.

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

Senior должен: - объяснить причину: `git pull` без `--rebase` делает merge, который примиряет «локальные коммиты» (старые) с «новыми remote» - назвать `git reset --hard origin/<branch>` как правильное восстановление, после `git stash` для незакоммиченной работы - предложить `git config --global pull.ff only` как профилактика: pull будет отказывать когда нужен merge, заставит выбрать явно reset или rebase - сказать что если у коллеги были **свои новые** локальные коммиты поверх старых - их нужно cherry-pick'нуть на новую базу, не теряя - назвать как этого избежать вообще: согласовать rewrite заранее, использовать `--force-with-lease` который иногда видит проблему до push

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

  • ✗ Не объяснить коллеге что нужен reset - он сделает ещё один pull, получит ещё один merge-коммит
  • ✗ Reset без stash - потеряют незакоммиченные правки
  • ✗ Думать что `pull.ff only` это решение проблемы - это профилактика, после факапа нужен reset

Follow-up

  • ? Что покажет `git log --graph` у коллеги после неудачного pull?
  • ? Как сохранить свои локальные коммиты коллеги при reset?
  • ? Чем `pull.ff only` отличается от `pull.rebase true`?

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

  • git pull
  • git rebase
  • git reflog
  • Force push
tags: rewriting, recovery, team
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки