Шпаргалка по Git для продвинутых

Краткий справочник по 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

Итог

Минимальный продвинутый набор такой. rebase -i для чистой истории. cherry-pick для переноса коммитов. bisect run для поиска регрессий. worktree вместо вечного stash. reflog как страховка от любой ошибки. Остальное смотрите в таблице «ситуация → команда» выше. На общих ветках помните про --force-with-lease вместо --force.

Сохраните шпаргалку себе. Новые шпаргалки и разборы я анонсирую в Telegram-канале «Бруяко: код и команда».


Теги: