Раздави мои последние X-коммиты вместе с помощью Git'а.

git rebase squash git-squash


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




Answer 1 Anomie


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

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




Answer 2 Chris Johnsen


Вы можете сделать это довольно легко без 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 на последний коммит, который вы не хотите раздавливать. Программный сброс не затрагивает ни индекс, ни рабочее дерево, оставляя индекс в желаемом состоянии для вашего нового коммита (т. Е. Он уже содержит все изменения из коммитов, которые вы собираетесь «выбросить»).




Answer 3 Mark Longair


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

ВНИМАНИЕ: Сначала убедитесь, что вы зафиксировали свою работу - убедитесь, что git status чистое (так как git reset --hard выбросит поэтапные и неустановленные изменения)

Then:

# 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 предложенное Крисом Джонсеном в его ответе, - это то, что вы получаете сообщение коммита, предварительно заполненное каждым сообщением коммита, которое вы подавляете.




Answer 4 nobar


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

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

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




Answer 5 EthanB


Основываясь на ответе Криса Джонсена ,

Добавьте глобальный псевдоним "сквош" от Бэша:(или 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"


Usage:

git squash N

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

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