Удалите старые коммиты git

88

Я новичок в git, и мне было интересно, возможно ли что-то подобное?

>git log --pretty=oneline --abbrev-commit
2f05aba Added new feature
3371cec Fixed screw up    <-- I want to remove this
daed25c Screw up          <-- and remove this.
e2b2a84 First.                So it's like they never happend.

Это возможно?

Джош
источник

Ответы:

63

Это возможно с помощью git rebase. Попробуйте следующее

git rebase -i HEAD~4

а затем следуйте интерактивным инструкциям в редакторе. На первом этапе вы «раздавливаете» коммиты. Это должно выглядеть примерно так:

pick 2f05aba ... will be preserved
squash 3371cec ... will be squashed with daed25c
squash daed25c ... will be squashed with e2b2a84
pick e2b2a84 .. will contain this and 3371cec and daed25c

На втором этапе вы можете редактировать сообщения фиксации.

Деве
источник
25
Разве вопрос не в том, чтобы удалить коммиты, а не раздавить их?
Ричард
3
@Stony: Ну, вы, наверное, тоже могли бы их удалить. Но из комментариев к фиксации в OP («Ошибка» и «Исправлена ​​ошибка») я предположил, что один отменяет другой, и что вы также можете просто раздавить их.
Деве
85

Если вы действительно хотите удалить их (стереть их из истории, чтобы их больше не видели), вы можете

запустить rebase:

git rebase -i HEAD~4

а затем просто удалите (или закомментируйте) строки, соответствующие коммитам, которые вы хотите удалить, например:

pick 2f05aba ... #will be preserved
#pick 3371cec ... #will be deleted
#pick daed25c ... #will be deleted
pick e2b2a84 ... #will be preserved
Шатур
источник
2
Я новичок в github, как вы нажимаете изменения после этого (когда я нажимаю «Синхронизировать», он просто отменяет то, что я сделал). Думаю, я понял: git push origin HEAD --force
Николас Тери
@NicolasThery, ты не знаешь. Вот почему git push отказывается работать без --force, потому что вы переписываете историю и сломаете репозитории других людей. Если вы уже нажали, то единственный вариант - сделать файл git revert. Что, если подумать, это разумно, потому что, если бы вы вытащили чужой код, вы бы не хотели, чтобы они могли стирать ваши старые коммиты без какой-либо истории, не так ли?
Angry Dan
Я предполагаю, что это просто работает в текущем репозитории Git и ничего не меняет в восходящем / любом другом узле Git?
Александр Миллс
2
@AlexanderMills Он ничего не меняет в апстриме, пока вы его не нажимаете (и если вы это сделаете, вы должны добавить флаг --force, как сказал Злой Дэн).
Shathur
dили dropэто команда для удаления коммитов из истории.
Брошенная тележка
5

Чтобы полностью удалить фиксацию (и), теперь есть новая опция dropдля интерактивных перебазов git. Первый забег:

git rebase -i HEAD~4

Затем замените pickс dropдля фиксации (s) быть отброшено:

pick 2f05aba ... #will be preserved
drop 3371cec ... #will be dropped
drop daed25c ... #will be dropped
pick e2b2a84 ... #will be preserved

У меня это сработало в Fedora со следующей версией:

$ git version
git version 2.21.0
Руссоу
источник
2

Сквош полезен, когда вы хотите сгенерировать список объединенных коммитов под одним хешем, но если вы хотите взять три отдельных коммита и получить окончательный результат, который выглядит так, как будто это был один коммит, я рекомендую fixup

git rebase -i HEAD~4

pick 2f05aba ... will be preserved
fixup 3371cec ... will be merged with daed25c
fixup daed25c ... will be merged with e2b2a84
pick e2b2a84 .. will include 3371cec and daed25c, but only the commit message of e2b2a84

Дополнительную информацию можно найти в списке команд пользовательского интерфейса интерактивной перебазировки.

Брошенная тележка
источник