git: обрезка / удаление старых веток: "ошибка: не удалось удалить sh некоторые ссылки" - PullRequest
2 голосов
/ 05 марта 2020

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

$ git branch -a  

warning: ignoring broken ref refs/remotes/remote/HEAD
* master
  origin
  restoration-effort2
  remotes/origin/master
  remotes/remote/master
  remotes/remote/carousel
  remotes/bridgent/animate
  remotes/bridgent/enlarged-hover
  remotes/bridgent/master
  remotes/bridgent/Rayom-generator-app
  remotes/bridgent/scripts
  remotes/bridgent/bridgent-carousel

Мое намерение / цель здесь состоит в том, чтобы удалить все те, которые начинаются с: 'remotes' (но не два 'master') ').

Когда я пытаюсь удалить их, я получаю:

error: unable to delete 'remote/bridgent-carousel': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

Так что у меня Google' ошибка: невозможно удалить удаленную ссылку не существует ', что вызывает вопрос SO / в ответе Git говорится, что удаленного ссылки не существует, когда я удаляю удаленную ветку

Можно найти еще одно руководство, которое я нашел (который включает в себя аналогичные советы, но объединены в один полезный пост в блоге) здесь .

Эти два руководства рекомендуют использовать такие команды:

$ git branch -D animate
$ git push origin --delete remotes/Rayom/animate
$ git fetch --prune
$ git push origin --delete <branch_name>

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

$ git push origin --delete bridgent/Rayom-generator-app                        
error: unable to delete 'bridgent/Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

$ git push origin --delete remote/bridgent-carousel 
error: unable to delete 'remote/bridgent-carousel': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

$ git push origin --delete Rayom-generator-app 
error: unable to delete 'Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

$ git push origin :Rayom-generator-app 
error: unable to delete 'Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

$ git branch --remote
<no output>

$ git remote prune origin --dry-run
<no output> 

$ git remote prune origin          
<no output>

Итак, мой основной вопрос для всех вас: как мне удалить remotes/bridgent/Rayom-generator-app и все подобные удаленные ветви?

Стоит также отметить, что когда я заменяю origin на remote, я получаю похожий вывод, но здесь все по-другому: пульты ссылаются на имя git предыдущего проекта (которого больше не существует):

$ git push remote --delete bridgent/Rayom-generator-app 
error: unable to delete 'bridgent/Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<**former**_project_name>.git'

$ git push remote --delete remote/bridgent-carousel 
error: unable to delete 'remote/bridgent-carousel': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<**former**_project_name>.git'

$ git push remote :Rayom-generator-app 
error: unable to delete 'Rayom-generator-app': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<**former**_project_name>.git'

Ответы [ 2 ]

2 голосов
/ 06 марта 2020

TL; DR

Запустите git remote и посмотрите, есть ли у вас пульты с именами remote и bridgent. (Используйте git remote -v для просмотра URL-адресов, связанных с каждым пультом.)

Если вы не хотите иметь пульт с именем remote, используйте git remote remove remote, чтобы удалить его. Это также удалит все из его имен для удаленного отслеживания. Повторите для bridgent, если / как хотите.

Если вы do хотите сохранить эти пульты, но удалите все имена удаленного отслеживания, связанные с этими пультами, запустите:

git fetch remote --prune

и / или:

git fetch bridgent --prune

Вы также можете запустить:

git fetch --all --prune

(или git fetch -a -p для краткости). --all означает контакт со всеми пультами . Или вы можете использовать git remote update --prune; git remote update по умолчанию выборка со всех пультов. По умолчанию для git fetch обычно просто вызывается и, следовательно, обновляется origin. 1


1 Технически, по умолчанию для git fetch должен вызывать пульт на основе восходящего текущей ветви, но если он не установлен, он использует origin. Большинство Git репозиториев, как правило, имеют только один пульт с именем origin, так что это работает хорошо. В вашем репозитории Git имеется три пульта дистанционного управления, поэтому его нет.

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


Long

Позвольте мне процитировать эту часть как акцент :

  remotes/origin/master
  remotes/remote/master
  remotes/remote/carousel
  remotes/bridgent/animate
[snip]

Если вынуть часть remotes/ из каждой строки, мы получим:

origin/master
remote/master
remote/carousel
bridgent/animate
bridgent/enlarged-hover
bridgent/master
[snip]

Если мы дополнительно удалим часть из первого Оставаясь / вперед и удаляя дубликаты, мы получаем этот список:

origin
remote
bridgent

Это список пультов .

Если вы запустите git remote, Вы должны увидеть этот тот же список имен . (Если вы этого не сделаете, у нас есть несколько иная проблема, чем та, с которой, я думаю, вы столкнулись.)

Сейчас:

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

Технически, их нет в вашем GitHub хранилище. Они находятся (или внутри) в вашем локальном хранилище на вашем ноутбуке или настольном компьютере. На GitHub есть еще одно отличное хранилище; это ваш GitHub репозиторий.

Remotes и имена для удаленного слежения

Помните, что Git является распределенной системой контроля версий. Таким образом, обычно существует два, три, десять или даже миллионы репозиториев . Каждый репозиторий имеет свои собственные имена веток. То, что все клоны некоторого общего хранилища - это не ветки , а коммиты . Команды - это то, чем делятся. имена ветвей просто помогают каждому хранилищу помнить его коммитов. Каждый коммит имеет уникальный идентификатор ha sh, который одинаков в каждом хранилище. Репозиторий либо имеет этот коммит, который затем имеет идентификатор ha sh; или у него нет этого коммита, и у него нет этого sh ID.

Когда у вас есть Git, вызовите другой Git на GitHub, ваш Git просит они о их совершает. Они скажут, например, У меня есть master в качестве коммита a123456... Ваши Git чеки: У меня есть a123456...? Если вы до имейте это, ваш Git говорит ОК, у меня уже есть тот , и вам не нужно его получать. Если у вас нет , ваш Git говорит А, пожалуйста, дайте мне a123456..., и их Git теперь предлагает родительский коммит что совершать. Ваш Git проверяет, есть ли у вас этот коммит . Если нет, ваш Git запрашивает родителя a123456..., и он предлагает родителю этого коммита - прародителю a123456..., а ваш Git проверяет, имеет ли sh ID и т. Д.

В конце концов, ваши Git получают от своих Git, всех коммитов, которые они имеют на своих master, которых ваш Git вообще не имеет. Так что теперь у вас есть все ваши коммиты плюс все их коммиты. Ваш master вполне может быть этим a123456... коммитом. Или ваш master может быть другим коммитом. Как бы то ни было, ваш Git теперь создает новое имя или обновляет существующее, чтобы запомнить их master.

Ваша Git память об их * Имена ветвей 1342 * - это ваши имена удаленного отслеживания для этого конкретного "другого Git". Этот другой Git на GitHub имеет URL; remote name origin хранит этот URL. Но что, если у вас есть более одного «другого Git»?

Ваш Git может вызвать другой Git репозиторий, возможно, под именем bridgent. Это удаленное имя, bridgent, хранит URL. Вот как ваш Git позвонит , этот другой Git. Когда ваш Git вызывает этот другой Git, они скажут что-то вроде: У меня есть ветвь с именем animate и ветвь с именем enlarged-hover и ветвь с именем master. Мой animate - это коммит b789abc..., мой enlarged-hover - это коммит fedcba9..., мой master - это ...

Ваш Git будет получен от bridgent Git любой коммит, который он имеет, а вы нет. Тогда ваш Git создаст или обновит ваши bridgent/* имена. Они содержат идентификаторы ha sh, которые ваш Git получил от Git, URL которого ваш Git сохранил под именем bridgent.

Итак, поскольку у вас есть origin и remote и bridgent, это означает, что ваш Git записал три отдельных пульта . Каждый пульт хранит URL; по этому URL-адресу Git отвечает, когда вы звоните по его номеру. У Git есть список названий ветвей. Каждое имя ветви идентифицирует какой-то конкретный коммит по номеру sh. Ваш Git также проверяет наличие этих коммитов, а затем создает или обновляет имена для удаленного отслеживания для каждого из этих других Git репозиториев.

имена для удаленного отслеживания Git ваших Git вызовов origin перечислены в origin/*. Имена удаленного отслеживания для Git ваших Git вызовов remote перечислены в remote/*. Имена удаленного отслеживания для Git ваших Git вызовов bridgent перечислены в bridgent/*. Вот как ваш Git сохраняет все это прямо.

Но git branch -a печатает remotes/origin/master et c

Если вы используете:

git branch

ваш Git перечисляет названия ваших филиалов. Они выдаются как master, develop и т. Д.

Если вы используете:

git branch -r

, ваш Git перечисляет ваши имена для удаленного отслеживания. Они выглядят как origin/master, bridgent/animate и т. Д.

Оба набора имен сокращены . Фактическое полное имя вашего master: refs/heads/master. Фактическое полное имя origin/master - refs/remotes/origin/master. У ветви имена refs/heads/ удалены, а имена удаленного слежения имеют refs/remotes/ удалены.

Установка этих префиксов обратно на гарантирует что имена не могут конфликтовать. Если по какой-то странной причине вы создадите свою собственную локальную ветку с именем origin/master, ее фактическое полное имя будет refs/heads/origin/master. Ваше дистанционное отслеживание origin/master действительно refs/remotes/origin/master. Очевидно, что эти два имени различаются из-за разного префикса . Поскольку Git использует полные имена для внутреннего использования, Git не запутается ... но поскольку Git, и вы, см. сокращены имена, вы можете запутаться. Не создавайте локальную ветвь с именем origin/master! 2

По любой причине, однако, git branch -a удаляет только часть refs/ при перечислении имен для удаленного отслеживания. Итак, git branch -a показал вам remotes/origin/master для origin/master, remotes/remote/carousel для remote/carousel и т. Д.

Вы можете , если хотите, удалить имена для удаленного слежения используя команду git branch: введите -d -r, т. е. удаленные опции и .

Вы не можете - по крайней мере, не успешно - попросите Git попросить Git в origin удалить remote/bridgent-carousel:

$ git push origin --delete remote/bridgent-carousel 
error: unable to delete 'remote/bridgent-carousel': remote ref does not exist
error: failed to push some refs to 'git@github.com:Nostrad/<project_name>.git'

, поскольку Git в origin не имеет это имя. Это Git в bridgent, которое имеет - или, по крайней мере, когда-то - название carousel. Вы можете попросить их удалить его, если у вас есть разрешение. Или вы можете удалить remote в вашем Git репозитории. Удаленное имя, bridgent-carousel, сохраняет URL-адрес и позволяет вашему Git иметь имена для удаленного отслеживания в форме bridgent/*, или, более полно, refs/remotes/bridgent/*.


2 Если вы это сделаете, вы можете написать refs/heads/origin/master и refs/remotes/origin/master или просто heads/origin/master и remotes/origin/master, чтобы они оставались прямыми. Делайте это достаточно долго, чтобы переименовать или удалить локальную ветку с именем origin/master.

0 голосов
/ 06 марта 2020

Вот:

$ git remote -v
origin  git@github.com:Nostrad/<project_name>.git (fetch)
origin  git@github.com:Nostrad/<project_name>.git (push)
remote  git@github.com:Nostrad/<former_project_name>.git (fetch)
remote  git@github.com:Nostrad/<former_project_name>.git (push)
bridgent git@github.com:bridgent/<project_name>.git (fetch)

Я подумал, что, поскольку есть пульт с именем «remote», он указывает на URL, который больше не существует.

Итак, я запустил:

$ git remote remove remote

Затем:

$ git remote remove bridgent
$ git fetch --prune
$ git push origin --delete

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

Вот мое дерево со всеми удаленными устаревшими ветвями:

git branch -a
warning: ignoring broken ref refs/remotes/remote/HEAD
* master
  origin
  restoration-effort2
  remotes/origin/master

Я достиг своего конечного результата. Я выполнил свою первоначальную цель до просмотра чрезвычайно подробного и полезного объяснения @ torek . Поэтому у меня не было возможности попробовать его TL; DR предложения:

$ git fetch remote --prune
$ git fetch bridgent --prune
$ git fetch --all --prune
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...