Прежде всего, вы пытаетесь удалить первые 20 коммитов или 20 коммитов после первого ?Как вы могли заметить в опубликованном вами списке TODO, commit 4b6d12e не указан, поэтому даже если операция работает, это не повлияет.Это потому, что вы указали 4b6d12e как upstream .Если вы хотите включить его (и если у него нет родителя, поскольку вы сказали, что пытаетесь удалить first 20 фиксаций), вы бы использовали опцию --root
, чтобы у вас не былоуказать коммит как upstream
.
Во-вторых, как вы определяете «удалить коммит»?Если commit A
добавляет file1, а commit B
добавляет file2, и я «удаляю» commit A
, так что у меня остается только коммит B'
- должен B'
содержать и file1 и file2, илитолько file2?
Если коммит B'
должен содержать только file2 - это означает, что вы удаляете коммит A
и внесенные в него изменения - тогда способ сделать это - интерактивная перебазировка с опцией d
.Но конечно это вызовет конфликты, которые вам придется разрешать вручную;из каждого коммита, который вы сохраняете, любой, который изменяет файл, который больше не создается (потому что он изначально был создан коммитом, который вы удалили) является конфликтом.У git нет возможности сделать вывод, что вы хотите, поэтому вы должны разрешить конфликт вручную.То, как ваш вопрос прерывается, предполагает, что вы ожидаете, что процесс будет автоматическим, но если вы удаляете исходные коммиты репо вместе с их изменениями, это не может быть автоматическим.
Обратите внимание, что этопереписать историю.Если репо используется совместно с другими, и ветвь даже была нажата (в то время, когда она содержала один из этих первых 20 коммитов), тогда
(a) вам придется использовать push -f
для обновленияудаленный и
(b) обновив пульт, вы переведете всех остальных пользователей в неисправное состояние, из-за которого неправильная процедура ремонта с их стороны отменит ваши изменения;поэтому вы должны согласовать со всеми остальными, кто будет затронут, если вы хотите, чтобы это работало.
С другой стороны, если B'
должен содержать оба файла - в этом случае он должен называться как AB
вместо B'
- тогда вы хотите сделать одну из двух вещей:
Один из вариантов - squash
коммиты вместо delete
их[1].Это просто вопрос использования разных команд для каждого коммита в списке rebase -i
TODO.Если все, что вы делаете, это коммиты в сквош, то не должно быть конфликтовно это по-прежнему переписывание истории, так что приведенные выше замечания по-прежнему применимы.
Другой вариант - создать мелкий клон репо.Это не переписывание истории;его главное преимущество заключается в том, что он сохраняет идентификаторы коммитов, поэтому никто не нарушает репо (и, как побочный эффект, вы можете повторно связать удаленную историю в будущем, если возникнет такая необходимость).См. Параметры depth
и shallow-*
git commit
.https://git -scm.com / docs / git-clone
Быть мелким - это не то, чем вы действительно можете поделиться с помощью толкания и вытягивания.Если удаленному пользователю необходимо удалить коммиты, вам придется заменить его на неглубокий (и предположительно зеркальный) клон.Каждый пользователь, имеющий клон, может обновить указанный клон [2].
[1] На самом деле я не люблю эту терминологию rebase
команда, потому что это продвигает неправильное представление о том, что коммит определяется его патчем, что на физическом уровне совершенно неверно.Но вот как rebase
использует слова.
[2] Последний пункт также указывает на возможную побочную проблему: независимо от того, какой подход вы выберете, вы не можете заставить других отказаться от этих коммитов от своих клонов.Так что если вы удаляете их, потому что, скажем, они содержат конфиденциальные данные, то, вероятно, кошка из сумки.Вы должны рассматривать любые учетные данные, которые когда-либо были отправлены в общий репозиторий, как скомпрометированные, например.