Объединить первые два коммита в Git-репозиторий?

Предположим, у вас есть история, содержащая три коммита 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

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

7 ответов


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

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

pick f4202da A
squash bea708e B
pick a8c6abc C

это объединит два коммита A и B на одно обязательство AB.

нашли в ответ.


вы пытались:

git rebase -i A

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

edit e97a17b B
pick asd314f C

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

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

сделано.


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

этот рецепт работает, даже если есть несколько коммитов между 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

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

pick A
pick B
pick C

стать:

pick A
squash B
pick C

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


в случае, если у вас есть сотни или тысячи коммитов, используя kostmo это of

git rebase -i --root

может быть непрактичным и медленным, просто из-за большого количества коммитов, которые должен обработать скрипт 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

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


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

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


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

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

это должно оставить вас с веткой, которая имеет AB и C в качестве коммитов.