Как объединить (сквошить) несколько коммитов Git в один?

Ответ

Для объединения нескольких последних коммитов в один используется интерактивный ребейз (git rebase -i).

Пошаговая инструкция:

  1. Запустите интерактивный ребейз для последних N коммитов (например, 10):
    git rebase -i HEAD~10
  2. В открывшемся редакторе вы увидите список коммитов. Оставьте первый коммит с ключевым словом pick, а для всех остальных, которые нужно объединить, замените pick на squash или s.
    pick a1b2c3d Начальный коммит
    squash e4f5g6h Второй коммит
    squash i7j8k9l Третий коммит
    # ... и так далее
  3. Сохраните файл и закройте редактор.
  4. Git откроет новое окно для редактирования итогового сообщения коммита. Здесь можно оставить одно сообщение, объединив или переписав историю из всех сквошенных коммитов.
  5. Сохраните и закройте — коммиты будут объединены.

Альтернативный способ — git merge --squash: Если вы хотите объединить все коммиты из ветки feature в один коммит при мерже в main:

git checkout main
git merge --squash feature
git commit -m "Объединённый коммит из ветки feature"

Важно: Ребейз переписывает историю. Не используйте его для коммитов, которые уже были отправлены в общий репозиторий.

Ответ 18+ 🔞

А, ну вот, опять история коммитов разрослась как сорняк после дождя! Сделал десять коммитов, а по смыслу — один плевок. «Исправил опечатку», «Ещё одну опечатку», «Ой, блядь, третью опечатку». Выглядит как маньяк с грамматическим справочником. Надо это всё схлопнуть в одну красивую, годную кнопку.

Слушай сюда, рецепт простой, как три рубля. Берёшь интерактивный ребейз и ебешь им свою историю по самое не балуй.

Как это делается, по шагам, для особо одарённых:

  1. Открываешь терминал и пишешь заклинание для, скажем, последних десяти коммитов:

    git rebase -i HEAD~10

    HEAD~10 — это как «эй, гита, дай-ка мне последние десять моих художеств».

  2. Перед тобой откроется редактор, а там — список, пиздец как на доске почёта. Твоя задача — всех этих уродов склеить в одного здоровяка. Оставляешь самому первому (самому старому) в списке слово pick. А всем остальным, кого хочешь присоединить к нему, меняешь pick на squash или просто s.

    pick a1b2c3d Начальный коммит (тут всё серьёзно)
    squash e4f5g6h поправил табуляцию, бля
    squash i7j8k9l ой, забыл точку с запятой, ёпта
    # ... и так далее, пока не надоест

    Сохраняешь файл и закрываешь. Git такой: «О, понял, ща сделаем красиво».

  3. Он откроет ещё одно окошко — тут тебе предлагают написать итоговое сообщение для нового, большого и красивого коммита. Все старые сообщения будут ниже, как черновики. Можешь оставить что-то одно, а можешь скомпилировать шедевр. Главное — не написать «чё-то там пофиксил», а то сам потом охренеешь.

  4. Сохраняешь — и вуаля! В истории вместо десяти мелких пиздюков — один монолитный коммит-богатырь. Красота, да и только.

А есть же ещё способ, для ленивых или трусливых! Если ты не хочешь трогать историю в своей ветке, а просто при мерже в main всё схлопнуть, то есть команда git merge --squash.

git checkout main
git merge --squash feature
git commit -m "Вся хуйня из ветки feature одной кучей"

Сделал — и в main упадёт один коммит со всеми изменениями из feature, а сама ветка feature со своей рваной историей останется нетронутой. Удобно, если ты не уверен, что твои коллеги не придут тебя линчевать за переписанный общий коммит.

НО ВАЖНОЕ ПРЕДУПРЕЖДЕНИЕ, БЛЯДЬ! git rebase -i — это инструмент переписывания истории. Это как взять учебник и вырвать из него страницы. Если ты уже запушил эти коммиты в общий репозиторий (на GitHub, GitLab и т.д.), а потом их переписал — всем остальным будет пиздец. Их история разойдётся с твоей, и придётся делать git push --force, что равноценно крику «ВСЕМ ПЕРЕМЕРГИТЬСЯ, СУКИ, Я ГЛАВНЫЙ!». Делай такое только со своими, неопубликованными коммитами. А то мало не покажется, честно.