Представьте: вы работаете в команде над крупным проектом. Ветка main - стабильный релиз. Вы начали фичу, но в процессе поняли, что часть работы нужно откатить, а часть - перенести в другую ветку. Или вы случайно закоммитили в main черновой код. Или нужно объединить несколько коммитов в один, чтобы история была чистой. Стандартные add, commit, push здесь не помогут. Нужны продвинутые команды Git.
В этом туториале мы разберём 4 реальных сценария и покажем, как их решить с помощью git rebase, git cherry-pick, git stash и git reset. Каждый пример - рабочий код с пошаговым объяснением.
Зачем: Вы сделали коммит, но поняли, что код сырой. Удалять его совсем не нужно - просто уберите из истории, оставив изменения в рабочей директории.
Как: Используйте git reset --soft HEAD~1.
# Исходная ситуация: последний коммит "WIP: черновик"
git log --oneline
# abc1234 (HEAD -> main) WIP: черновик
# def5678 Фича: авторизация
# Отменяем последний коммит, но оставляем изменения в staging
git reset --soft HEAD~1
# Проверяем: коммита нет, но файлы в индексе
git status
# Changes to be committed:
# modified: app.js
# Теперь вы можете доработать код и сделать новый коммит
git commit -m "Фича: авторизация v2"
Пример: Вы случайно закоммитили console.log в продакшн-ветку. Вместо git revert (который создаёт новый коммит отмены), используйте git reset --soft - история останется чистой.
Итог: git reset --soft - ваш друг, когда нужно "переделать" последний коммит без потери данных. Для полного удаления изменений используйте --hard, но осторожно: это безвозвратно.
Зачем: В ветке develop уже есть исправление бага, но оно нужно и в hotfix. Сливать всю ветку - слишком жирно. Нужен только один коммит.
Как: git cherry-pick <хэш_коммита>.
# Находим хэш нужного коммита в ветке develop
git checkout develop
git log --oneline
# a1b2c3d Исправление: баг с таймером
# e4f5g6h Рефакторинг компонента
# Переключаемся в hotfix
git checkout hotfix
# Переносим только коммит с исправлением
git cherry-pick a1b2c3d
# Если возник конфликт - Git приостановит операцию
# Разрешаем конфликт вручную, затем:
git add .
git cherry-pick --continue
# Проверяем историю
git log --oneline -3
# a1b2c3d (HEAD -> hotfix) Исправление: баг с таймером
# (остальные коммиты hotfix)
Пример: В main нашли критический баг. Вы уже исправили его в develop, но мержить develop в main не хотите - там много незаконченных фич. cherry-pick решает проблему за секунду.
Итог: git cherry-pick - точечное копирование коммита. Идеально для hotfix-ов и переноса отдельных изменений между ветками.
Зачем: Вы работаете над фичей, но срочно нужно переключиться на другую задачу. Коммитить незаконченный код нельзя - он сломает сборку. Просто оставить изменения в рабочей директории - они "прилипнут" к другой ветке.
Как: git stash сохраняет изменения в стек и очищает рабочую директорию.
# Вы начали фичу, но нужно срочно переключиться
git status
# Changes not staged for commit:
# modified: app.js
# Прячем изменения
git stash push -m "WIP: фича логирования"
# Рабочая директория чиста - можно переключать ветки
git checkout main
# делаем срочный фикс
git commit -m "Hotfix: исправление цены"
git push
# Возвращаемся к фиче
git checkout feature/logging
git stash pop # достаёт последний stash и удаляет его из стека
# Или можно применить без удаления
git stash apply stash@{0}
Пример: Вы правите баг, а коллега просит срочно проверить его код в другой ветке. git stash сохранит ваши наработки, не требуя коммита. Можно даже сделать несколько stash - они хранятся в стеке.
Итог: git stash - временное хранилище для незавершённой работы. Не забывайте git stash list для просмотра стека и git stash drop для удаления конкретного элемента.
Зачем: У вас 10 мелких коммитов в ветке feature. Вмержить их в main - значит захламить историю. Лучше объединить их в 2-3 осмысленных коммита.
Как: git rebase -i HEAD~N, где N - количество последних коммитов для переписывания.
# Исходная история (ветка feature)
git log --oneline
# 1a2b3c4 fix: опечатка
# 5d6e7f8 fix: ещё одна опечатка
# 9g0h1i2 feat: добавлена кнопка
# 3j4k5l6 feat: базовая верстка
# Запускаем интерактивный rebase для последних 4 коммитов
git rebase -i HEAD~4
# Откроется редактор, где нужно изменить порядок и команды:
# pick 3j4k5l6 feat: базовая верстка
# pick 9g0h1i2 feat: добавлена кнопка
# fixup 5d6e7f8 fix: ещё одна опечатка # объединить с предыдущим, отбросив сообщение
# fixup 1a2b3c4 fix: опечатка # объединить с предыдущим
# Сохраняем и выходим - Git перепишет историю
# Результат:
git log --oneline
# aaa1111 feat: базовая верстка (объединил 4 коммита в 1)
Пример: Перед мержем feature-ветки в main вы делаете git rebase -i, чтобы превратить кучу "WIP" и "fix typo" в один чистый коммит. Это стандарт в командах, где ценят историю.
Важно: Никогда не делайте rebase для коммитов, которые уже отправлены в общий репозиторий (например, в main). Это сломает историю у коллег. Rebuse только для локальных веток.
Итог: git rebase -i - мощный инструмент для причёсывания истории. Используйте pick, fixup, squash для объединения коммитов и reword для переименования.
Зачем: Вы работаете в feature-ветке, а main ушёл вперёд. Нужно обновить свою ветку, чтобы избежать конфликтов при мерже. Два подхода: merge и rebase.
Как: Выберите в зависимости от команды.
# Подход 1: Merge (сохраняет историю ветвлений)
git checkout feature
git merge main
# Git создаёт merge-commit, история показывает, что feature ответвилась от старого main
# Минус: много merge-коммитов захламляют историю
# Подход 2: Rebase (линейная история)
git checkout feature
git rebase main
# Git переписывает коммиты feature так, будто они сделаны на основе нового main
# Плюс: чистая линейная история
# Минус: если конфликты - придётся разрешать их для каждого коммита по-отдельности
Пример: В команде с code review чаще используют rebase - история читается как книга. В больших open-source проектах предпочитают merge, потому что он не переписывает историю.
Итог: Для личных веток - rebase. Для общих - merge (или rebase, но только если никто кроме вас не работает в этой ветке).
Эти команды решают 90% проблем, которые возникают при работе с Git в команде. Практикуйтесь на тестовых репозиториях - и вы перестанете бояться конфликтов и "испорченной" истории.
Комментариев пока нет