Объединить первые два коммита Git-репозитория? - PullRequest
189 голосов
/ 12 января 2009

Предположим, у вас есть история, содержащая три коммита A, B и C :

A-B-C

Я хочу объединить два коммита A и B в один коммит AB :

AB-C

Я пытался

git rebase -i A

, который открывает мой редактор со следующим содержанием:

pick e97a17b B
pick asd314f C

Я изменяю это на

squash e97a17b B
pick asd314f C

Тогда Git 1.6.0.4 говорит:

Cannot 'squash' without a previous commit

Есть ли способ или это просто невозможно?

Ответы [ 8 ]

155 голосов
/ 09 февраля 2014

Использование git rebase -i --root от Git версия 1.7.12 .

В интерактивном файле rebase измените вторую строку коммита B на сквош и оставьте другие строки в pick :

pick f4202da A
squash bea708e B
pick a8c6abc C

Это объединит два коммита A и B в один коммит AB .

Нашел в этот ответ .

126 голосов
/ 12 февраля 2009

Вы пробовали:

git rebase -i A

Можно начать так, если вы продолжите с edit вместо squash:

edit e97a17b B
pick asd314f C

затем запустите

git reset --soft HEAD^
git commit --amend
git rebase --continue

Готово.

64 голосов
/ 12 января 2009

A был начальный коммит, но теперь вы хотите, чтобы B был начальный коммит. Коммиты git - это целые деревья, а не diff-ы, даже если они обычно описываются и рассматриваются в терминах diff, которые они вводят.

Этот рецепт работает, даже если между A и B есть несколько коммитов, а также B и C.

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp
10 голосов
/ 12 января 2009

В случае интерактивного перебазирования вы должны сделать это до A, чтобы список был:

pick A
pick B
pick C

стать:

pick A
squash B
pick C

Если A является начальным коммитом, вам нужно сделать другой начальный коммит, прежде чем A. Git подумает о различиях, он будет работать на разнице между (A и B) и (B и C). Следовательно, сквош не работает в вашем примере.

9 голосов
/ 23 июля 2014

В случае, если у вас есть сотни или тысячи коммитов, используйте ответ Костмо из

git rebase -i --root

может быть непрактичным и медленным, просто из-за большого количества коммитов, которые сценарий rebase должен обработать дважды , один раз для генерации списка интерактивного редактора rebase (где вы выбираете, какое действие предпринять для каждого commit) и один раз для фактического выполнения повторного применения коммитов.

Вот альтернативное решение , которое позволит избежать затрат времени на создание списка интерактивного редактора rebase , не используя в первую очередь интерактивную rebase . Таким образом, это похоже на решение Чарльза Бейли . Вы просто создаете потерянную ветвь из второго коммита, а затем перебазируете все коммиты-потомки поверх него:

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

Документация

1 голос
/ 14 марта 2009

В связанном вопросе мне удалось придумать другой подход к необходимости раздавливания против первого коммита, то есть сделать его вторым.

Если вам интересно: git: как вставить коммит в качестве первого, сдвинув все остальные?

0 голосов
/ 22 ноября 2018

Команда Git для отряда: git rebase -i HEAD ~ [количество коммитов]

Допустим, у вас ниже история коммитов git:


pick 5152061 feat: Добавлена ​​поддержка сохранения изображения. (А)
pick 39c5a04 Исправлено: исправление ошибок. (В)
выбрать 839c6b3 исправить: конфликт разрешен. (С)

Теперь вы хотите раздавить A и B в AB, выполните следующие шаги:


pick 5152061 feat: Добавлена ​​поддержка сохранения изображения. (А)
s 39c5a04 Исправление: исправление ошибок. (В)
выбрать 839c6b3 исправить: конфликт разрешен. (С)

Примечание: для фиксации в сквошах мы можем использовать squash или s. Конечный результат будет:
pick 5152061 feat: добавлена ​​поддержка сохранения изображения. (АВ)
выбрать 839c6b3 исправить: конфликт разрешен. (С)

0 голосов
/ 12 января 2009

Вы должны выполнить немного магии командной строки.

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

Это должно оставить вас с веткой, в которой коммиты имеют AB и C.

...