Как убрать все коммиты из ветки Git темы?
Предположим, у меня есть следующая история:
A---B---C----------D------------E master
\ /\ /
W1--X1--Y1 W2--X2--Y2
topic1 topic2
Можно ли удалить все ветки темы и их коммиты следующим образом
A-B-C-D-E master
3 ответа
У вас есть несколько вариантов для этого.
Решение 1: Сквош слияния
Одно из решений состоит в том, чтобы просто использовать hard reset с несколькими сквош-слияниями:
git checkout master
git reset --hard C
git merge --squash topic1
git commit -m "Rewrite D"
git merge --squash topic2
git commit -m "Rewrite E"
# Verify that the new branch is no different from the old one
git diff sha_of_old_E
Идея заключается в том, что слияние в виде сквоша скопирует конечное состояние ветки темы (то есть, последний коммит) в вашу текущую рабочую копию, где вы затем сможете ее зафиксировать. Это эффективно раздавливает ветку в один коммит.
Документация
Решение 2: Интерактивная перебазировка
Другой метод заключается в использовании интерактивного перебазирования для разделения веток темы в один коммит. Сначала вызовите ребаз
git rebase -i C
Это вызовет интерактивный редактор списков TODO в вашем терминале. Вы увидите следующие коммиты:
pick sha W1
pick sha X1
pick sha Y1
pick sha W2
pick sha X2
pick sha Y2
То, что вы хотите сделать, это что-то похожее на слияние сквош выше. Вы можете разбить ветки темы на отдельные коммиты, поэтому для каждого коммита ветки темы, сквош (или "исправление") коммит потомка в его родителя:
pick sha W1
squash sha X1
squash sha Y1
pick sha W2
squash sha X2
squash sha Y2
Затем нажмите :wq
в редакторе Vim, чтобы начать интерактивную перезагрузку. Я не буду вдаваться в подробности о следующих шагах, потому что они уже достаточно подробно описаны в других многочисленных источниках в Интернете, таких как Pro Git § 6.4 Инструменты Git - Переписывание истории - Squashing Commits.
Вы, вероятно, захотите дважды проверить, правильно ли вы сделали ребазинг, проверив, что вновь переписанная ветвь ничем не отличается от предыдущей, используя простой diff:
git diff sha_of_old_E
Обратите внимание, что если вы не хотите редактировать сообщения фиксации для каждого сквоша, вы можете вместо этого использовать "fixup", который будет просто повторно использовать сообщение фиксации предыдущего коммита:
pick sha W1
fixup sha X1
fixup sha Y1
pick sha W2
fixup sha X2
fixup sha Y2
Обратите внимание, что вы также можете использовать s
или же f
для сквоша и починки, соответственно.
Документация
Предупреждение о силе толкания
Обратите внимание, что оба вышеупомянутых решения переписывают вашу историю коммитов, поэтому ваши новые коммиты будут иметь разные идентификаторы ша. Если вы уже выдвинули старую версию своей ветки на свой пульт, то вам нужно будет принудительно переместить старую копию. Это может не быть тем, что вы хотите сделать, если вы делитесь своей веткой с другими людьми, по причинам, которые я не буду здесь подробно описывать, поскольку возможные опасности принудительного толчка хорошо документированы во многих других онлайн-источниках, таких как:
Один трюк - клонировать одну ветку из этого репо в новый репо.
git clone <url> --branch <branch> --single-branch [<folder>]
И использовать новый репо оттуда.
Вы можете использовать интерактивный ребаз:
git rebase -i <hash of A>
а затем удалите коммиты, которые вам не нужны, просто удалив строки, ссылающиеся на коммиты. У вас будет что-то вроде:
pick <hash of B> message of B
pick <hash of C> message of C
pick <hash of W1> message of W1
pick <hash of X1> message of X1
pick <hash of Y1> message of Y1
pick <hash of D> message of D
pick <hash of W2> message of W2
pick <hash of X2> message of X2
pick <hash of Y2> message of Y2
pick <hash of E> message of E
Затем удалите эти строки, ссылаясь на ветки темы следующим образом:
pick <hash of B> message of B
pick <hash of C> message of C
pick <hash of D> message of D
pick <hash of E> message of E