Вопрос: Сквош мой последний Х коммитирует вместе, используя Git


Как я могу скворовать, мой последний Х фиксируется вместе в одном коммите, используя Git?


2235


источник


Ответы:


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

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


1221



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

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

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

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

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

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


2502



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


560



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

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

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


132



Based on Chris Johnsen's answer,

Add a global "squash" alias from bash: (or Git Bash on 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'

... or using Windows' Command Prompt:

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


Your ~/.gitconfig should now contain this alias:

[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

... Which automatically squashes together the last N commits, inclusive.

Note: The resultant commit message is a combination of all the squashed commits, in order. If you are unhappy with that, you can always git commit --amend to modify it manually. (Or, edit the alias to match your tastes.)


97



If you use TortoiseGit, you can the function Combine to one commit:

  1. Open TortoiseGit context menu
  2. Select Show Log
  3. Mark the relevant commits in the log view
  4. Select Combine to one commit from the context menu

Combine commits

This function automatically executes all necessary single git steps. Unfortunatly only available for Windows.


46



Thanks to this handy blog post I found that you can use this command to squash the last 3 commits:

git rebase -i HEAD~3

This is handy as it works even when you are on a local branch with no tracking information/remote repo.

The command will open the interactive rebase editor which then allows you to reorder, squash, reword, etc as per normal.


45



Based on this article I found this method easier for my usecase.

My 'dev' branch was ahead of 'origin/dev' by 96 commits (so these commits were not pushed to the remote yet).

I wanted to squash these commits into one before pushing the change. I prefere to reset the branch to the state of 'origin/dev' (this will leave all changes from the 96 commits unstaged) and then commit the changes at once:

git reset origin/dev
git add --all
git commit -m 'my commit message'

28