Простая и чистая git-история может помочь при исследовании проблемы с кодом, в моей практике случается, что рассматривая строку кода обычно полезно посмотреть, а что ещё поменялось в других местах и, возможно, сделать выводы почему сделали именно так. Если коммит один, то легко увидеть все затронутые файлы и строки кода, а если задача решалась в несколько коммитов, то это сделать не получится. Кроме этого один коммит проще ребейзить или перемещать в другие ветки. Так вот, как же это сделать?
Первое - нужно понять сколько коммитов мы хотим "схлопнуть". Для этого лучше проверить историю ветки:
git log
Вот так может выглядеть история разработке в ветки фичи, несколько коммитов могут появится в процессе code-review, ещё несколько при исправлении ошибок, в итоге можно их превратить в один коммит. Набираем команду:
git rebase -i HEAD~3
В общем случае git rebase меняет историю ветки и мы указали количество коммитов которые хотим исправить - посмотрите на HEAD~3, именно столько коммитов мы хотим изменить. Параметр -i означает интерактивность, в этом случае git откроет нам редактор и предложит определиться с изменениями.
Git подсказывает нам команды, мы будем использовать squash - команда объединения коммита с предыдущим. Команды работают так: нужно просто поменять её имя (крайнее левое слово, в данном случае pick, у каждого коммита) на подходящее для нашей цели. В нашем случае нужно заменить слово pick у всех коммитов (кроме первого, то есть верхнего) на слово squash. Или, что еще проще, заменить на одну букву s, не обязательно писать все слово squash полностью. Можно вообще ничего не трогать и просто выйти, тогда git сообщит что все сделал фразой "Successfully rebased and updated refs/heads/master." и всё останется по-старому.
Если коммитов получилось много, можно ли ускорить процесс замены команды? Если вы используете vim, то легко, попробуйте набрать:
:2,3s/pick/s/
Это обычная замена подстроки редактора vim, тут написано "от 2-й до 3-й строки нужно заменить (символ s) слово pick на слово s. Или вообще заменить все глобально:
:%s/pick/s/g
Заменит все pick на s во всем файле (ключ g - global), правда после этого придется исправить самый первый коммит назад, на pick. В итоге должна получится такая картина
2-й и 3-й коммиты объединяться с первым и станут единым целым. Таких объединений можно делать несколько, это нормально, можно даже сделать сразу несколько групп: 2-й и 3-й коммиты объединяем с первым, а какие-нибудь 9-й и 8-й с 7-м коммитом и все это за один раз. Так же коммиты можно поменять местами. Теперь сохраним файл, git снова откроет для нас редактор для того, чтобы проверить и изменить сообщение коммита, если хотите
Можно просто оставить как есть, сохранить и выйти, а можно отредактировать, я обычно удаляю лишние незакомментированные строки (это сообщения других коммитов) и оставляю лишь одно. Готово! Смотрим историю
git log
В конце стоит упомянуть, что история в вашей ветке теперь не такая как на сервере, вы ведь пушили эту ветку раньше и постоянно добавляли коммиты туда, а теперь у вас совсем другая ветка со старым именем, в ней ведь всего лишь одно изменение. Для этого вам понадобится ключ force
git push --force
Ключ force запушит ветку несмотря на разногласия в истории, фактически уничтожив старую ветку на сервере, заменив её вашей, новой. Будьте осторожны, ведь кто-то другой мог добавить в ветку "своих" коммитов, вы их удалите этой командой.