Краткий справочник по Git за пределами add, commit, push. Всё на одной странице: переписать историю, перенести коммит, найти сломавший сборку коммит, восстановить потерянное. Здесь только «как». Команды, которые экономят часы, но плохо держатся в голове. Рядом по теме лежат Linux-утилиты для ежедневной работы.
rebase: переписываем историю
# Перенести текущую ветку поверх свежего main
git rebase main
# Интерактивно: почистить последние 4 коммита
git rebase -i HEAD~4
# в редакторе: pick → squash (склеить), reword (переписать сообщение),
# drop (выбросить), edit (остановиться и поправить)
# Если во время ребейза конфликт
git rebase --continue # после правки конфликта и git add
git rebase --abort # откатить всё обратно
Перенести часть веток на новую базу умеет --onto. Берём коммиты ветки feature поверх main, отбросив старую базу old-base:
git rebase --onto main old-base feature
Золотое правило: не ребейзить то, что уже опубликовано. Ребейз меняет SHA коммитов. Если ветку кто-то уже забрал, его история разойдётся с вашей.
cherry-pick: переносим отдельные коммиты
# Перенести один коммит в текущую ветку
git cherry-pick a1b2c3d
# Диапазон коммитов (не включая first, включая last)
git cherry-pick first..last
# С пометкой, откуда взят коммит (добавит строку "cherry picked from...")
git cherry-pick -x a1b2c3d
# Конфликт во время переноса
git cherry-pick --continue
git cherry-pick --abort
Типичный кейс: горячая правка ушла в релизную ветку, и тот же коммит нужно поднять в main.
bisect: ищем коммит, который сломал сборку
Бинарный поиск по истории. Указываем заведомо плохой и заведомо хороший коммит. Git делит диапазон пополам и спрашивает на каждом шаге.
git bisect start
git bisect bad # текущий коммит сломан
git bisect good v1.4.0 # на этом теге всё работало
# Git переключается на середину. Проверяем, отвечаем:
git bisect good # этот ок
git bisect bad # этот сломан
# ...пока не найдётся первый плохой коммит
git bisect reset # вернуться к исходному состоянию
Автоматический режим: скрипт сам помечает коммиты. Код возврата 0 значит хороший коммит, 1–127 (кроме 125) значит плохой. Код 125 значит пропустить коммит — его нельзя проверить.
git bisect start HEAD v1.4.0
git bisect run go test ./...
worktree: несколько веток одновременно
Один репозиторий, несколько рабочих директорий. Не нужно делать stash, чтобы переключиться на срочный фикс.
# Создать отдельную папку с веткой hotfix
git worktree add ../proj-hotfix hotfix
# Посмотреть список рабочих деревьев
git worktree list
# Удалить, когда закончили
git worktree remove ../proj-hotfix
Незавершённая работа остаётся нетронутой в основной папке, а в ../proj-hotfix параллельно правится hotfix.
reflog: восстановить потерянное
reflog помнит, куда указывал HEAD, даже после reset --hard, неудачного ребейза или удаления ветки.
# История перемещений HEAD
git reflog
# Вернуться к состоянию до неудачного ребейза
git reset --hard HEAD@{2}
# Восстановить удалённую ветку (нашли её SHA в reflog)
git branch recovered a1b2c3d
Пока коммит виден в reflog, он не потерян. По умолчанию записи живут 90 дней.
restore и switch: замена checkout
git checkout перегружен. В новых версиях Git его роль разделили на два понятных инструмента.
# Отменить изменения в файле (вернуть как в HEAD)
git restore file.go
# Убрать файл из индекса, не трогая изменения
git restore --staged file.go
# Восстановить файл из конкретного коммита
git restore --source=HEAD~2 file.go
# Переключить ветку
git switch main
# Создать ветку и перейти на неё
git switch -c feature
stash: приёмы помимо базового
# Спрятать только выбранные куски (по частям)
git stash -p
# Именованный stash — легче найти потом
git stash push -m "недоделанный рефакторинг парсера"
# Список и просмотр
git stash list
git stash show -p stash@{0}
# Применить и удалить из стека
git stash pop
# Превратить stash в новую ветку
git stash branch feature-x stash@{0}
Ситуация → команда
| Ситуация | Команда |
|---|---|
| Отменить последний коммит, оставив изменения в рабочей копии | git reset --soft HEAD~1 |
| Отменить последний коммит и изменения | git reset --hard HEAD~1 |
| Изменить сообщение последнего коммита | git commit --amend |
| Добавить забытый файл в последний коммит | git add file && git commit --amend --no-edit |
| Безопасно запушить переписанную историю | git push --force-with-lease |
| Откатить уже опубликованный коммит | git revert <sha> |
| Посмотреть, кто и когда менял строку | git blame -L 10,20 file.go |
| Найти коммит по тексту в изменениях | git log -S "функция_которую_ищем" |
| Временно убрать изменения, чтобы переключиться | git stash / git worktree add |
Антипаттерны
# ПЛОХО: затирает чужие коммиты без предупреждения
git push --force
# ХОРОШО: откажется пушить, если на сервере появилось новое
git push --force-with-lease
reset --hardбез оглядки наreflog. Команда выглядит необратимой. Ноreflogпочти всегда спасает. Проверьте его, прежде чем паниковать.- Ребейз чужих веток. Меняет SHA опубликованных коммитов и ломает историю всем, кто их забрал. На общих ветках используйте
mergeилиrevert. commit --amendпосле push. То же самое: переписывает уже опубликованный коммит. Делайте это только до пуша. Или с--force-with-leaseна личной ветке.
Итог
Минимальный продвинутый набор такой. rebase -i для чистой истории. cherry-pick для переноса коммитов. bisect run для поиска регрессий. worktree вместо вечного stash. reflog как страховка от любой ошибки. Остальное смотрите в таблице «ситуация → команда» выше. На общих ветках помните про --force-with-lease вместо --force.
Сохраните шпаргалку себе. Новые шпаргалки и разборы я анонсирую в Telegram-канале «Бруяко: код и команда».
Теги: