Ответ
Для объединения (squash) коммитов я использую интерактивный rebase (git rebase -i). Это стандартный способ привести историю в порядок перед мержем в основную ветку, например, в main или master, особенно в рамках Pull/Merge Request.
Типичный сценарий: У меня есть ветка feature/auth, в которой за время разработки накопилось несколько коммитов типа "WIP", "Fix typo", "Add tests". Перед созданием PR я хочу объединить их в один логичный коммит "Implement user authentication".
Процесс:
- Убедиться, что я на нужной ветке и рабочая директория чиста.
git status git checkout feature/auth - Запустить интерактивный rebase относительно точки, от которой ответвилась моя ветка (или указав количество коммитов).
# Способ 1: Указать хэш коммита, ПРЕДШЕСТВУЮЩИЙ первому коммиту, который нужно сквошить git rebase -i main # Способ 2: Объединить последние N коммитов от HEAD git rebase -i HEAD~3 - В открывшемся редакторе я вижу список коммитов. Для коммитов, которые нужно объединить с предыдущим, я заменяю
pickнаsquash(или простоs). Самый старый коммит в списке оставляю какpick— он станет основой.pick a1b2c3d Implement user authentication logic squash e4f5g6h Add unit tests for auth service squash i7j8k9l Fix typo in login error message -
После сохранения и закрытия редактора Git откроет еще один редактор для редактирования итогового сообщения коммита. Я удаляю автоматически сгенерированные сообщения от сквошенных коммитов и оставляю одно четкое, например:
Implement user authentication - Add JWT-based login and registration endpoints - Integrate with PostgreSQL user table - Add comprehensive unit and integration tests - Update API documentation - После сохранения коммит будет создан. Так как история переписана, для отправки на удаленный репозиторий потребуется force-push.
git push origin feature/auth --force-with-leaseВажное предупреждение:
--force-with-leaseбезопаснее--force, так как проверит, что никто другой не пушил в эту ветку после вашего последнего fetch. Никогда не делайте force-push в общие ветки (main, develop).
Альтернатива для простых случаев: Если нужно просто объединить последние N коммитов без переупорядочивания, можно использовать git reset --soft:
git reset --soft HEAD~3 # Перемещает HEAD на 3 коммита назад, оставляя все изменения в staged состоянии
git commit -m "New combined commit message" Ответ 18+ 🔞
Слушай, история про гитовый сквош — это вообще отдельный вид искусства, как правильно накосячить, чтобы потом не выглядеть полным идиотом. Ёпта, я тебе сейчас расскажу, как это делают не распиздяи, а те, кто хоть немного уважает себя и коллег.
Вот представь: ты наваял ветку feature/auth, а там коммитов, как говна за баней — овердохуища. "WIP", "Фикс опечатки", "Ещё один фикс той же опечатки", "Ой, забыл тесты". Выглядит, будто мартышлюшка на клавиатуре скакала. Такую хуйню в main пулить — это чих-пых тебя в сраку, тебя просто затрахают ревьюверы. Надо это всё в один красивый коммит сгруппировать.
Как нормальные люди делают:
- Первым делом, бля, проверь, где ты стоишь и не насрал ли ты мимо рабочей директории. Базовая гигиена, ебать.
git status git checkout feature/auth - Дальше — магия, она же интерактивный ребейз. Запускаешь и чувствуешь себя богом истории. Главное — правильно указать, откуда начинать.
# Вариант норм: ребейз относительно ветки, от которой ты когда-то ответвился. git rebase -i main # Или проще: сквошни последние три коммита с головы. git rebase -i HEAD~3 - Откроется редактор, и тут начинается самое интересное. Видишь список своих "творений". Рядом с теми, которые надо вмазать в предыдущий, меняешь
pickнаsquash(или простоs). Самый первый, старый коммит в этом списке оставляешьpick— он будет основным.pick a1b2c3d Реализовал логику аутентификации squash e4f5g6h Добавил тесты для сервиса squash i7j8k9l Пофиксил опечатку в сообщении об ошибке -
Сохранил, закрыл — и тут Git, хитрая жопа, спрашивает: "А какое сообщение к итоговому коммиту написать?". Тут надо не лениться. Выкинь нахуй все автогенерённые сообщения от мелких коммитов и напиши одно, но годное.
Реализована аутентификация пользователя - Добавлены JWT эндпоинты для логина и регистрации - Интеграция с таблицей пользователей в PostgreSQL - Покрытие юнит- и интеграционными тестами - Обновлена документация API - Всё, коммит готов. Но, ёпта, история-то переписана! Значит, пушить в удалённый репозиторий надо с силой. Только, блядь, не
--force, а--force-with-lease! Это как предохранитель.git push origin feature/auth --force-with-leaseВнимание, мудя! Силовой пуш — это оружие массового поражения. Ты им НИКОГДА не работаешь с общими ветками (
main,develop). Только со своейfeature/auth. Иначе будет вам хиросима и нигерсраки, когда кто-то ещё в эту ветку что-то закоммитил.
Лайфхак для ленивых: Если коммиты идут подряд и их просто надо слепить в кучу, без перетасовки, можно проще:
git reset --soft HEAD~3 # Откатывает HEAD на три коммита, но все изменения остаются как staged
git commit -m "Один большой и красивый коммит вместо трёх кривых"
Но это так, для бытовухи. Ребейз — мощнее и правильнее.