Сквош мой последний X коммитов вместе с помощью Git - PullRequest
3036 голосов
/ 04 марта 2011

Как мне сжать мои последние X коммитов в один коммит с помощью Git?

Ответы [ 31 ]

3288 голосов
/ 05 марта 2011

Вы можете сделать это довольно легко без git rebase или git merge --squash.В этом примере мы раздавим последние 3 коммита.

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

git reset --soft HEAD~3 &&
git commit

Если вы хотите начать редактированиеновое сообщение фиксации с конкатенацией существующих сообщений фиксации (т. е. аналогично тому, с чего начнёт список инструкций pick / squash / squash /… / squash git rebase -i), затем вам нужно извлечь эти сообщения и передать их git commit:

git reset --soft HEAD~3 && 
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"

Оба эти метода объединяют последние три коммита в один новый коммит одинаково.Мягкий сброс просто перенаправляет HEAD на последний коммит, который вы не хотите раздавливать.Программный сброс не затрагивает ни индекс, ни рабочее дерево, оставляя индекс в желаемом состоянии для вашего нового коммита (т. Е. Он уже содержит все изменения из коммитов, которые вы собираетесь «выбросить»).

1716 голосов
/ 04 марта 2011

Используйте git rebase -i <after-this-commit> и замените «pick» на втором и последующих коммитах на «squash» или «fixup», как описано в руководстве .

В этом примере <after-this-commit> - это либо хэш SHA1, либо относительное местоположение из HEAD текущей ветви, из которой анализируются коммиты для команды rebase.Например, если пользователь желает просмотреть 5 коммитов из текущего HEAD в прошлом, команда будет git rebase -i HEAD~5.

669 голосов
/ 04 марта 2011

Вы можете использовать для этого git merge --squash, что несколько элегантнее, чем git rebase -i.Предположим, что вы мастер, и вы хотите раздавить последние 12 коммитов в один.

ПРЕДУПРЕЖДЕНИЕ. Сначала убедитесь, что вы зафиксировали свою работу - убедитесь, что git status чист (поскольку git reset --hard выбрасывает поэтапнои неустановленные изменения)

Затем:

# Reset the current branch to the commit just before the last 12:
git reset --hard HEAD~12

# HEAD@{1} is where the branch was just before the previous command.
# This command sets the state of the index to be as it would just
# after a merge from that commit:
git merge --squash HEAD@{1}

# Commit those squashed changes.  The commit message will be helpfully
# prepopulated with the commit messages of all the squashed commits:
git commit

Документация для git merge более подробно описывает параметр --squash.


Обновление: единственное реальное преимущество этого метода перед более простым git reset --soft HEAD~12 && git commit, предложенным Крисом Джонсеном в его ответе , заключается в том, что вы получаете сообщение о коммите, предварительно заполненное каждым сообщением о коммите, которое выСквош.

191 голосов
/ 15 марта 2014

Я рекомендую по возможности избегать git reset - особенно для Git-новичков.Если вам действительно не нужно автоматизировать процесс, основанный на числе коммитов, существует менее экзотический способ ...

  1. Поместить коммиты, которые будут раздавлены, на работающийветвь (если они еще нет) - используйте gitk для этого
  2. Проверьте целевую ветвь (например, 'master')
  3. git merge --squash (working branch name)
  4. git commit

Сообщение о фиксации будет предварительно заполнено на основе сквоша.

120 голосов
/ 19 февраля 2014

На основании ответа Криса Джонсена ,

Добавить глобальный псевдоним "squash" из bash: (или Git Bash в Windows)

git config --global alias.squash '!f(){ git reset --soft HEAD~${1} && git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"; };f'

...или с помощью командной строки Windows:

git config --global alias.squash "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"


Ваш ~/.gitconfig теперь должен содержать этот псевдоним:

[alias]
    squash = "!f(){ git reset --soft HEAD~${1} && git commit --edit -m\"$(git log --format=%B --reverse HEAD..HEAD@{1})\"; };f"


Использование:

git squash N

... который автоматически объединяет последние N коммитов включительно.

Примечание. Результирующее сообщение о фиксации представляет собой комбинацию всех сжатых коммитов по порядку.Если вы недовольны этим, вы всегда можете git commit --amend изменить его вручную.(Или измените псевдоним в соответствии со своими вкусами.)

93 голосов
/ 17 мая 2016

Благодаря этому удобному сообщению в блоге Я обнаружил, что вы можете использовать эту команду для сжатия 3 последних коммитов:

git rebase -i HEAD~3

Это удобно, так как работает, даже когда вы находитесьлокальная ветвь без информации об отслеживании / удаленного репо.

Команда откроет интерактивный редактор ребаз, который затем позволит вам изменить порядок, сквош, переформулировать и т. д. как обычно.


Использование интерактивного редактора rebase:

Интерактивный редактор rebase показывает последние три коммита.Это ограничение было определено HEAD~3 при запуске команды git rebase -i HEAD~3.

Самый последний коммит, HEAD, отображается первым в строке 1. Строки, начинающиеся с #, являются комментариями / документацией..

Документация отображается довольно ясно.В любой заданной строке вы можете изменить команду с pick на команду по вашему выбору.

Я предпочитаю использовать команду fixup, так как это "раздавливает" изменения коммита в коммите в строке вышеи отбрасывает сообщение коммита.

Поскольку коммит в строке 1 равен HEAD, в большинстве случаев вы бы оставили это как pick.Вы не можете использовать squash или fixup, так как нет другого коммита, чтобы раздавить коммит в.

interactive rebase editor

54 голосов
/ 06 ноября 2015

Если вы используете TortoiseGit, вы можете использовать функцию Combine to one commit:

  1. Открыть контекстное меню TortoiseGit
  2. Выбрать Show Log
  3. Отметить соответствующие коммиты в представлении журнала
  4. Выберите Combine to one commit из контекстного меню

Combine commits

Эта функция автоматически выполняет все необходимые одиночные шаги git. К сожалению, доступно только для Windows.

41 голосов
/ 22 мая 2014

На основании этой статьи Я нашел этот метод проще для моего сценария использования.

Моя ветка 'dev' опередила 'origin / dev' на 96 коммитов (поэтому эти коммиты не былипока что нажал на пульт).

Я хотел сжать эти коммиты в один, прежде чем нажать на изменения.Я предпочитаю сбросить ветку в состояние origin / dev (это оставит все изменения из 96 коммитов без изменений), а затем зафиксировать изменения сразу:

git reset origin/dev
git add --all
git commit -m 'my commit message'
38 голосов
/ 06 апреля 2017

Для этого вы можете использовать следующую команду git.

 git rebase -i HEAD~n

n (= 4 здесь) - номер последнего коммита.Затем вы получаете следующие опции:

pick 01d1124 Message....
pick 6340aaa Message....
pick ebfd367 Message....
pick 30e0ccb Message....

Обновление, как показано ниже,

p 01d1124 Message....
s 6340aaa Message....
s ebfd367 Message....
s 30e0ccb Message....

Для получения подробной информации нажмите на ссылку

Удачи !!

29 голосов
/ 10 января 2018

1) Определение короткого хэша коммита

# git log --pretty=oneline --abbrev-commit
abcd1234 Update to Fix for issue B
cdababcd Fix issue B
deab3412 Fix issue A
....

Здесь даже git log --oneline также можно использовать для получения короткого хэша.

2) Если вы хотите использовать последний (последний) сквош (слияние)two commit

# git rebase -i deab3412 

3) Откроется редактор nano для слияния.И это выглядит так:

....
pick cdababcd Fix issue B
pick abcd1234 Update to Fix for issue B
....

4) Переименуйте слово pick в squash, которое присутствует до abcd1234.После переименования оно должно выглядеть следующим образом.

....
pick cdababcd Fix issue B
squash abcd1234 Update to Fix for issue B
....

5) Теперь сохраните и закройте редактор nano.Нажмите ctrl + o и нажмите Enter для сохранения.А затем нажмите ctrl + x для выхода из редактора.

6) Затем снова откроется редактор nano для обновления комментариев, при необходимости обновите его.

7) Теперь его успешно завершили, вы можетепроверьте это, проверив логи.

# git log --pretty=oneline --abbrev-commit
1122abcd Fix issue B
deab3412 Fix issue A
....

8) Теперь нажмите на репо.Обратите внимание, чтобы добавить + знак перед названием ветви.Это означает принудительное нажатие.

# git push origin +master

Примечание: это основано на использовании git на ubuntu shell.Если вы используете разные ОС (Windows или Mac), то приведенные выше команды одинаковы, за исключением редактора.Вы можете получить другой редактор.

...