git push: refs / heads / my / subbranch существует, не может создать

88

Невозможно ли создать подпапку somme в репо на сервере?

если я сделаю:

git push origin dev/master 

все работает найти

но если я сделаю

git push origin dev/sub/master

я получил это:

error: 'refs/heads/dev/sub' exists; cannot create 'refs/heads/dev/sub/master'

Я проверил с помощью «git branch -r» и напрямую с помощью ssh, еще не создана папка dev / sub.

что случилось?

Снайф
источник
1
Что возвращает git ls-remote origin?
Ikke

Ответы:

156

Это не папка , а ветка . (Ну, может быть где-то задействована папка / каталог, а может и нет, поскольку ссылки «упаковываются» и перестают существовать как файлы в каталогах.)

  • Если ветка bсуществует, указанная ветка не b/anythingможет быть создана.
  • Точно так же, если ветка dev/bсуществует, dev/b/cне может быть создана.

Это внутреннее ограничение git. В этом конкретном случае у удаленного originесть ветка с именем dev/sub(независимо от того, есть она у вас или нет, важно, есть ли она у удаленного). Для того , чтобы создать на originфилиал имени dev/sub/master, необходимо сначала удалить ветку с именем dev/subна origin:

git push origin :dev/sub

(Конечно, удаление этой ветки может удалить там что-то важное, поэтому убедитесь, что вы знаете, что делаете. Как правило, вы можете git fetch originсначала записать их dev/subкак свои origin/dev/sub. Затем вы можете создать локальную ветку с именем, dev/renamed-subуказывающую на ту же фиксацию , создать dev/renamed-subна удаленном, удалить удаленный dev/sub, а затем создать dev/sub/masterна удаленном.)


Если вы можете войти в систему на удаленном компьютере (в системе, в originкоторой размещена), вы можете войти в репозиторий и просто переименовать локальную dev/subветку. (Основываясь на комментариях ниже, я подозреваю, что там также есть сломанный сценарий автоматического развертывания, который, вероятно, следует исправить, чтобы развертывать только «развертываемые» ветки, а не все, что отправляется. Но я просто предполагаю здесь.)

торек
источник
1
Полагаю, мы здесь просто суетимся из-за терминологии. Под «внутренним ограничением» я подразумеваю то, что git может преодолеть, не меняя того, как кто-либо использует git. Безусловное ограничение будет чем-то гораздо более фундаментальным, например, если кто-то сломает SHA1: хотя даже это можно преодолеть (например, перейти на SHA256), детали 40-символьного SHA-1 раскрываются, например, в большинстве хуков, так что это ограничение просачивается наружу.
torek
2
Это странно раздражающее ограничение, учитывая, что вы, возможно, захотите иметь release/1.1и release/1.2с release/1.1/hofix/prevent-upload-bork& release/1.1/hotfix/assure-user-of-competence, и т. Д. И сообщение об ошибке ведет сюда (спасибо), вместо того, чтобы указывать ограничение! Но спасибо за простое и понятное объяснение.
Benjohn
2
«Это внутреннее ограничение мерзавца». -- Хорошо, но почему? Было ли проще реализовать какую-то логику? Или обход дерева? Или что?
Д. Ковач
2
@ D.Kovács: запретив этот случай, Git может просто записывать хэши ссылок в файлы, имя которых создается путем обработки ссылки как имени пути. Если бы Git позволял и то, refs/tags/fooи другое, и refs/tags/foo/2, например, он не смог бы этого сделать: ему нужно было бы реализовать собственное хранилище значений ключей. Я думаю, что Git в любом случае будет вынужден реализовать собственное хранилище ключей и значений, но я не знаю, снимут ли они это ограничение.
Торек
1
@ ĐinhAnhHuy: Я не знаю какой-либо официальной документации, описывающей это ограничение. Подмодули, однако, находятся в совершенно отдельном пространстве имен: имена подмодулей и имена веток не должны конфликтовать так же, как имена веток и имена файлов не конфликтуют (т. Е. Они сталкиваются, но вы добавляете средство устранения неоднозначности: git checkout -- masterозначает проверку файл с именем master, а не название филиала).
torek
62

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

  • git branch -r список локальных копий удаленных филиалов
  • git ls-remote список удаленных веток
  • git fetch --prune originобновлять локальные копии удаленных веток ( мне это не помогло )
  • git remote prune originудалить информацию об удаленных удаленных ветках ( это сделал )
меридиус
источник
8
git remote prune originбыла единственной командой, которую я выполнил, чтобы исправить это состояние ошибки. Действительно вводящее в заблуждение сообщение - в моем случае я пытался нажать "release / 2.6.0", и я удалил весь каталог 'refs / remotes / origin / release *', но git продолжал жаловаться, error: update_ref failed for ref 'refs/remotes/origin/release/2.6.0': cannot lock ref 'refs/remotes/origin/release/2.6.0': 'refs/remotes/origin/release' exists; cannot create 'refs/remotes/origin/release/2.6.0'когда я пытался нажать / тянуть / получить
conny
32

Для меня ->

Ошибка =

fatal: cannot lock ref 'refs/heads/release/wl/2.3': 'refs/heads/release/wl' 
exists; cannot create 'refs/heads/release/wl/2.3'

Решение =

$~ git update-ref -d refs/heads/release/wl
$~ git checkout release/wl/2.3
МЕЗИДИ Хамза
источник
1
git update-ref -d refs / remotes ... решил мою проблему: существует 'refs / remotes / origin / hotfix'; Невозможно создать «refs / remotes / origin / hotfix / ISSUE ...»
Эдуардо
Это также устранило мою проблему.
Михаил Морфиков
16

Принят в настоящее время ответ не помог мне , потому что у меня не было реф на удаленный репозиторий для удаления - это чисто на мой местный! Итак, если вы оказались в такой ситуации, вот что делать:

Это проблема, с которой я столкнулся:

$ git fetch origin
error: cannot lock ref 'refs/remotes/origin/fix/sub-branch': 
'refs/remotes/origin/fix' exists; cannot create 
'refs/remotes/origin/fix/sub-branch'
From <repo URL>
 ! [new branch]      fix/sub-branch          -> origin/fix/sub-branch
 (unable to update local ref)

Я попробовал принять предложение ответа, но получил следующее:

$ git push origin :fix
error: unable to delete 'fix': remote ref does not exist
error: failed to push some refs to <repo URL>

Так что рефери даже не существовал origin- он явно просто болтался где-то в моем локальном репо. Итак, я побежал $ git remote show meи произвел:

Remote branches:
...
refs/remotes/origin/fix             stale (use 'git remote prune' to remove)
...

Что затем прояснило решение:

$ git remote prune origin
Pruning origin
URL: <redacted>
 * [pruned] origin/fix

С этим проблема исчезла:

$ git fetch origin
remote: Counting objects: 5, done.
remote: Total 5 (delta 2), reused 2 (delta 2), pack-reused 3
Unpacking objects: 100% (5/5), done.
From <repo URL>
 * [new branch]      fix/sub-branch          -> origin/fix/sub-branch
авреккан
источник
3
Да, та же проблема, с которой вы столкнулись, и git remote prune originисправила ее. Благодаря!
ToddH 02
3

Попробуйте эту команду, чтобы исправить это:

git gc

для выполнения ряда служебных задач в текущем репозитории и удаления недоступных объектов (путем вызова git pruneи git fsck --unreachable).

Подробнее: git help gcиgit help prune

Kenorb
источник
2

Если ничего не помогает, убедитесь, что ваша система репо не имеет ограничений для имен веток. В моем случае вы могли создавать только ветки, которые начинаются с SD-<number>. Любое другое именование даст вам только общее:

remote: error: cannot lock ref 'refs/heads/mybranch': 'refs/heads/mybranch/environment-variables' exists; cannot create 'refs/heads/mybranch'
To git.example.com:project/repository.git
 ! [remote rejected] mybranch -> mybranch (failed to update ref)
error: failed to push some refs to 'git@git.example.com:project/repository.git'
Юха Унтинен
источник
1
#!/usr/bin/env bash
echo "update-ref delete refs/tags"
log="git-update-ref-errors.log"
script="./git-update-ref-exist-tags-delete.sh"
git_command="git update-ref -d refs/tags"

echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors to ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}

echo fetch
log="git-fetch-errors.log"
script="./git-fetch-exist-tags-delete.sh"
git_command="git fetch"
echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors from ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}
git fetch

echo pull
log="git-pull-errors.log"
script="./git-pull-exist-tags-delete.sh"
git_command="git pull"
echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors from ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}
git pull

echo push
log="git-push-errors.log"
script="./git-push-exist-tags-delete.sh"
git_command="git push"
echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors from ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}
git push

Приведенный выше сценарий будет записывать ошибки в XXX-errors.log и исправлять их, автоматически создавая и запуская XXX-exist-tags-delete.sh из XXX-errors.log с помощью следующих команд:

  1. git update-ref -d ссылки / теги
  2. git fetch
  3. git pull
  4. git push
Томер Бар-Шломо
источник
1

git remote prune origin исправил проблему для меня

Андреа Герарди
источник
1

Как пользователь Windows, ни одно из решений до сих пор не решило проблему для меня. Причина, по которой я видел эту ошибку, заключалась в том, что (используя имена веток OP) я пытался создать ветку, dev/subно кто-то другой создал ветку с именем, Devи, как мы все знаем, в Windows есть файловая система без учета регистра.

Поэтому, когда окна пытались раскрыть, dev/subон сначала пытался создать папку dev, но не смог, потому что Devуже существовал.

Решением было удалить Devветку локально и удаленно с помощью git branch -d Dev && git push origin :Dev. А git pullпосле этого все нормально работало.

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

Alexkb
источник
1

Я понимаю, что на это уже дан ответ, но у меня это не сработало. Я не заботился о локальных изменениях, поскольку он уже был выдвинут, но у меня возникли проблемы с откатом. В моем случае мы изменились на полпути между наличием «исправления» в качестве ветки к системе папок с родительской папкой в ​​качестве «исправления».

- hotfix ---- hotfix / 1234_bug ---- hotfix / 3456_bug

Итак, я получал следующую ошибку:

Fetching from origin Error: cannot lock ref 'refs/remotes/origin/hotfix/1234_bug': 'refs/remotes/origin/hotfix' exists; cannot create 'refs/remotes/origin/hotfix'

После поиска похожих ошибок я наконец нашел решение в ветке обсуждения здесь .

git remote prune origin
Санджай Залке
источник
0
git checkout -b hotfix/my-new-branch

ga
gm "my commit"

gp --set-upstream origin hotfix/subscribers-function
Ослеплять
источник
0

Переименуйте dev/subв dev/sub/something, затем вы можете создать ветку dev/sub/master.

Катанор
источник