Git полностью удаляет необработанный корневой узел - PullRequest
1 голос
/ 15 марта 2019

У нас есть два репо, Repo1 и Repo2. Похоже, «кто-то» подтолкнул Repo2 к Repo1 / origin, и теперь Repo1 содержит как Repo1, так и Repo2. Есть два отдельных корневых узла, и ничего не было объединено (к счастью). Repo1 также загрязнен целой кучей тегов / веток от Repo2.

Как можно полностью обнулить любые коммиты (и их теги / ветви) с конкретным предком (корневой узел Repo2, также называемый «Первоначальный коммит»)? Или, может быть, другой / более простой способ склеить эти два репозитория?

Обратите внимание, что оба репо содержат годы работы (поэтому нецелесообразно смотреть на каждый коммит вручную), однако для каждого, кто использует Repo1, целесообразно повторное клонирование в случае необходимости.

Ответы [ 2 ]

1 голос
/ 15 марта 2019

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

     C--D
    /    \
A--B      G--H   <-- branch1
    \    /
     E--F   <-- branch2

I--J--K--L   <-- master
       \
        M--N   <-- develop

Этот конкретный граф имеет четыре "точки входа", а именно фиксирует F и H в подграфе с корнем в A икоммиты L и N в подграфе с корнем в I.

Хотя в таком репозитории нет ничего принципиально неправильного или нарушенного, его относительно легко разделить на два отдельных репозитория.Просто начните с двух клонов, оба из которых выглядят так.(Вы можете использовать git clone --mirror для создания зеркальных клонов, которые сохраняют все ссылки. Обязательно сотрите их origin s, чтобы они оба не указывали на исходный объединенный репозиторий.)

В одном такомклонировать, удалить любые внешние метки - имена ветвей, имена тегов и другие ссылки, если существуют какие-либо другие ссылки, - на любой из коммитов в один из двух подграфов:

     C--D
    /    \
A--B      G--H   <-- branch1
    \    /
     E--F   <-- branch2

I--J--K--L   [abandoned]
       \
        M--N   [abandoned]

Beобязательно включите любые теги или другие имена, которые указывают на намеренно оставленный подграф.Обычные команды просмотра графиков, такие как git log, не будут отображать неподписанный подграф: появится , который будет удален, хотя он все еще будет присутствовать физически.В конце концов, несвязанный подграф отпадет, или вы можете удалить его быстрее, используя git gc.Клоны, сделанные из , в этом хранилище не будет ссылочного подграфа.

В другом из двух клонов удалите все ссылки на другой подграф:

     C--D
    /    \
A--B      G--H   [abandoned]
    \    /
     E--F   [abandoned]

I--J--K--L   <-- master
       \
        M--N   <-- develop

Как и раньше, ссылочный подграф в конечном итоге исчезнет.

Обратите внимание, что любые клоны исходного хранилища с двумя независимыми подграфами могут использоваться для git pushдо либо этих разделенных клонов.В этом отношении любой третий, полностью независимый репозиторий может также использоваться для передачи в любой из этих двух клонов.Любой толчок, который добавляет имя для коммита, который находится в независимом подграфе, заставит весь независимый подграф войти в получателя толчка. Как вы предполагаете в комментарии , я подозреваю, что именно так возникла эта ситуация.

Вы можете добавить ловушку предварительного получения, которая отклоняет новые имена, которые добавляют новый корневой коммит,хотя нет никаких удобных приемных крючков этой формы, о которых я знаю.Это легко сделать, но медленно: запустите git rev-list --all --max-parents=0 --count для подсчета существующих корней и секунду git rev-list --all --max-parents=0 --count <hash> для подсчета корней, которые вы бы получили, если бы приняли предложенное сопоставление имени с хеш-идентификатором из git push.Если число увеличивается, новый толчок добавляет новый корень.

Обратите внимание, что можно добавить новый корень, который является не частью непересекающегося подграфа.Например, рассмотрим графики «до и после»:

before:
A--B--C  <-- master

after:

A--B--C--F--G  <-- master
        /
    D--E

Этот вид перехвата предварительного получения отклонит такой толчок.Это может быть то, что вы хотите, но это не так;будьте осторожны в том, что вы программируете.: -)

0 голосов
/ 18 марта 2019

Размещение этого сообщения для толпы TLDR, все заслуги перед отличным ответом Торека.

Я запустил это (на Windows MINGW64 git cli, цитирование / экранирование может отличаться на других терминалах), рассмотрел его, затем выполнил все команды, выводимые им.

git for-each-ref --contains <root_commit_hash> --format="%(refname:short)" refs/tags | xargs -I % echo git tag -d % \&\& git push --delete origin %

Добавьте немного git gc и / или git prune для хорошей меры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...