Объединение нескольких коммитов перед нажатием в Git

У меня есть несколько коммитов в моем локальном хранилище, которые тематически похожи. Я хотел бы объединить их в один коммит, прежде чем отправлять на удаленный. Как мне это сделать? Я думаю rebase делает это, но я не могу понять документы.

8 ответов

Решение

То, что вы хотите сделать, называется в Git "раздавливание". Есть много вариантов, когда вы делаете это (слишком много?), Но если вы просто хотите объединить все свои невыдвинутые коммиты в один коммит, сделайте это:

git rebase -i origin/master

Это вызовет ваш текстовый редактор (-i для "интерактивного") с файлом, который выглядит следующим образом:

pick 16b5fcc Code in, tests not passing
pick c964dea Getting closer
pick 06cf8ee Something changed
pick 396b4a3 Tests pass
pick 9be7fdb Better comments
pick 7dba9cb All done

Изменить все pick в squash (или же s) кроме первого:

pick 16b5fcc Code in, tests not passing
squash c964dea Getting closer
squash 06cf8ee Something changed
squash 396b4a3 Tests pass
squash 9be7fdb Better comments
squash 7dba9cb All done

Сохраните файл и выйдите из редактора. Затем откроется другой текстовый редактор, который позволит вам объединить сообщения коммита от всех коммитов в одно большое сообщение коммита.

Вуаля! Гугл "git squashing" даст вам объяснения всех других доступных опций.

Если у вас много коммитов, и вы хотите раздавить только последние X коммитов, найдите идентификатор фиксации коммита, с которого вы хотите начать сквош, и выполните

git rebase -i <that_commit_id>

Затем выполните действия, описанные в ответе Леопда, изменив все pickс squashДа, кроме первого.

Здесь довольно много рабочих ответов, но я нашел это самым простым. Эта команда откроет редактор, где вы можете просто заменить pick с squash чтобы удалить / объединить их в один

git rebase -i HEAD~4

где, 4 это количество коммитов, которые вы хотите раздавить в один. Это объясняется и здесь.

Вы можете сделать это с git rebase -i, передавая ревизию, которую вы хотите использовать в качестве 'root':

git rebase -i origin/master

откроет окно редактора, отображающее все коммиты, сделанные вами после последнего коммита в origin/master, Вы можете отклонить коммиты, зафиксировать сквош в один коммит или отредактировать предыдущие коммиты.

Есть несколько ресурсов, которые могут объяснить это лучше и показать некоторые другие примеры:

http://book.git-scm.com/4_interactive_rebasing.html

а также

http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html

первые две хорошие страницы, которые я мог найти.

Я придумал

#!/bin/sh

message=`git log --format=%B origin..HEAD | sort | uniq | grep -v '^$'`
git reset --soft origin
git commit -m "$message"

Объединяет, сортирует, объединяет и удаляет пустые строки из сообщения коммита. Я использую это для локальных изменений в github wiki (используя gollum)

Вы можете раздавить (присоединиться) коммиты с помощью интерактивной перебазировки. На YouTube есть довольно симпатичное видео, показывающее, как это сделать из командной строки или с помощью SmartGit:

Если вы уже являетесь пользователем SmartGit, вы можете выбрать все свои исходящие коммиты (удерживая клавишу Ctrl) и открыть контекстное меню (щелчок правой кнопкой мыши), чтобы раздавить ваши коммиты.

Это очень удобно

введите описание изображения здесь

Существует также очень хороший учебник от Atlassian, который показывает, как это работает:

И мой образ squashing множественный push есть (возможно, вы отправили в свою ветку много коммитов, и теперь вы хотите сделать запрос на извлечение и не хотите загромождать их многими коммитами, которые вы уже выдвинули). То, как я это делаю (насколько я могу судить, нет более простого варианта).

  1. Создать новую ветку ради squash (ветка от оригинальной ветки, в которую вы хотите перетащить запрос).
  2. Нажмите на вновь созданную ветку.
  3. Объединить ветку с коммитами (уже переданными) в новую ветку.
  4. Перебазируй новую ветку и сквош.
  5. Нажмите новую ветку.
  6. Создайте новый запрос на извлечение для новой ветви, которая теперь имеет один коммит.

Пример:

git checkout from_branch_you_wish_to_pull_request_to
git checkout -b new_branch_will_have_single_squashed_commit
git push -u new_branch_will_have_single_squashed_commit
git merge older_branch_with_all_those_multiple_commits
git rebase -i (here you squash)
git push origin new_branch_will_have_single_squashed_commit

Теперь вы можете перетащить запрос в from_branch_you_wish_to_pull_request_to

Возможно, вы захотите использовать Interactive Rebasing, который подробно описан в этой ссылке.

Вы можете найти другие полезные ресурсы, если будете искать "git rebase interactive".

Другие вопросы по тегам