ВСЕ коммиты дублируются после BFG (редактирование истории) - PullRequest
2 голосов
/ 11 октября 2019

Я не знал о чистом способе удаления больших / чувствительных файлов с помощью BFG, и пропустил важный шаг: git clone --mirror git://example.com/some-big-repo.git

, который, когда я пытался перейти на удаленный доступ, приводил к конфликтам истории, который я наивно разрешил с помощью git pull origin master --allow-unrelated-histories, слил несколько конфликтов, затем нажал.

это дублировало коммиты, иногда 5-10 раз.

Так как я один работаю над этим репоУ меня нет возможности убрать это на землю и перезапустить с более разумной копии, и я не должен беспокоиться, что разные коммиты разные, я уверен, что они идентичны.

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

1 Ответ

5 голосов
/ 11 октября 2019

Существует ли команда грубой силы для удаления всех коммитов, которые идентичны во всех аспектах, кроме хэшей?

Нет. Вы можете, однако, отказаться от своего коммитного слияния, которое связывает старую историю и новую историю вместе. Это не сотрет старую историю, но вы можете просто прекратить использовать ее . В конце концов, если ваш Git не может его найти, он упадет.

Вам нужно будет запустить git reset --hard в своем собственном репозитории (чтобы отменить один коммит слияния), а затем использовать git push -f чтобы отправить все на origin и иметь их move их master.


Два разных хеш-идентификатора коммита - это два разных коммита, иневозможно изменить что-либо о коммите. Вот почему BFG (и собственные Git git filter-branch) copy все коммиты: они буквально не могут изменить старые. Вот как вы получили две копии всего.

Сначала вы сделали новые копии и бросили старые в пользу новых. Это то, что делает BFG. (Это не совсем то, что делает git filter-branch: он не выбрасывает старые, он просто отбрасывает их в сторону и затем заставляет вас выбрасывать их.)

Пока все хорошо,Но затем вы запустили git fetch, чтобы забрать все старые коммиты, а затем git merge с опцией: теперь разбивают вместе старые и новые, даже если они не имеют отношения друг к другу .

Если ваши старые и новые истории коммитов были очень просты, мы могли бы нарисовать их так:

A--B--...--H   <-- origin/master

A'-B'-...--H'  <-- master

(Заглавные буквы обозначают хэши коммитов, а простые знаки, например, A' вместо A, укажите, что это копии с измененным чем-то, поэтому у них разные хэши.) Вероятно, ваши истории - ваши коммиты - более сложны, но этого представления все еще достаточно: есть одинзадействовано исходное принятие конечной точки, такое как H, и одно новое принятие конечной точки H'.

Слияние, которое вы вставили в конец, делает это:

A--B--...--H    <-- origin/master
            \
             M   <-- master
            /
A'-B'-...--H'

(где первый родительский элемент M равен H', а второй родительский элемент M равен H). Имя origin/master в вашем собственном Git - это память вашего Git о том, что Git origin постоянно говорит: my master is: они все еще помнят коммит H как их master.

Если вы удалите коммит M из кончика вашей собственной ветви master, вы 'осталось в вашем собственном хранилище:

A--B--...--H    <-- origin/master
            \
             M   [abandoned]
            /
A'-B'-...--H'   <-- master

Фиксация M все еще существует но вы не можете увидеть это больше: нет ничего легкогоспособ найти это. Непростые способы найти его будут держать его как минимум еще 30 дней, если вы решите, что хотите его вернуть, но в конечном итоге они позволят ему упасть и по-настоящему исчезнут.

Теперь на этомВы можете набрать:

git push --force origin master

, чтобы ваш Git вызывал Git origin, убедитесь, что у него есть все переписанные коммиты (A'-...-H'), а затем отправьте им принудительную команду:форма: Да, это лишает вас доступа к фиксации H, но вместо этого установите master на указание фиксации H'. Обычно они подчиняются этой команде, если не будут,вы должны выяснить , почему они не будут (например, функция "защищенной ветви" GitHub) и исправить , что сначала - а затем они будут иметь:

A--B--...--H   [abandoned]

A'-B'-...--H'  <-- master

(при условии, что вы их никогда не отправляли M - если вы это сделали, они тоже их получат, но также забросят). Ваш Git увидит, что они подчиняются этой команде, и обновит ваш origin/master, чтобы отразить ее:

A--B--...--H   [abandoned]
            \
             M   [abandoned]
            /
A'-B'-...--H'   <-- master, origin/master

Когда истекло достаточно времени - как правило, намного короче для пустых серверных репозиториев (например,те, что на GitHub), но более 30 дней в вашем собственном репозитории - заброшенные коммиты будут сметены с мусора, когда сборщик мусора Git запустится и очистится. В этот момент никто не запомнит исходные хэш-идентификаторы, а оригинальные команды нигде не будут найдены.

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

...