Объединить первые два коммита 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
Есть ли способ или это просто невозможно?
9 ответов
Использование git rebase -i --root
с версии Git 1.7.12.
В интерактивном файле перебазировки измените вторую строку коммита B, чтобы он давил, и оставьте другие строки на пике:
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 - это целые деревья, а не diffs, даже если они обычно описываются и рассматриваются в терминах 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
В случае, если у вас есть сотни или тысячи коммитов, используйте ответ Костмо
git rebase -i --root
может быть непрактичным и медленным, просто из-за большого количества коммитов, которые сценарий 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
Документация
В случае интерактивного перебазирования вы должны сделать это до A, чтобы список был:
pick A
pick B
pick C
становиться:
pick A
squash B
pick C
Если A является начальным коммитом, вы должны иметь другой начальный коммит, прежде чем A. Git подумает о различиях, он будет работать на разнице между (A и B) и (B и C). Следовательно сквош не работает в вашем примере.
В связанном вопросе мне удалось придумать другой подход к необходимости раздавливания первого коммита, то есть сделать второй.
Если вам интересно: git: как вставить коммит в качестве первого, сдвинув все остальные?
Команда Git для отряда: git rebase -i HEAD~[количество коммитов]
Допустим, у вас есть история git коммитов:
pick 5152061 feat: добавлена поддержка сохранения изображения. (А)
pick 39c5a04 Fix: исправление ошибок. (В)
выбрать 839c6b3 исправить: конфликт разрешен. (С)
Теперь вы хотите раздавить A и B до AB, выполните следующие шаги:
pick 5152061 feat: добавлена поддержка сохранения изображения. (А)
s 39c5a04 Исправлено: исправление ошибок. (В)
выбрать 839c6b3 исправить: конфликт разрешен. (С)
Примечание: для фиксации сквоша мы можем использовать сквош или s. Конечный результат будет:
pick 5152061 feat: добавлена поддержка сохранения изображения. (АВ)
выбрать 839c6b3 исправить: конфликт разрешен. (С)
Вы должны выполнить немного магии командной строки.
git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a
Это должно оставить вас с веткой, в которой коммиты имеют AB и C.
Мне также интересно, что, если структура похожа
X-Y------Z
\-A-B-C/
и я хочу, чтобы окончательная структура была
X-Y-----Z
\-AB-C/
Как в этом случае объединить A и B?