git push: refs / heads / my / підгалузь існує, створити не вдається


84

Хіба це неможливо створити вкладену папку 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?
Ікке

Відповіді:


152

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

  • Якщо гілка 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
"Це внутрішнє обмеження git." - Добре, але чому? Чи легше було логіку реалізувати таким чином? Або якась обхід дерева? Або те, що?
Д. Ковач

2
@ D.Kovács: заборонивши такий випадок, Git може просто писати хеші посилань у файли, ім'я яких створюється шляхом обробки посилання як імені шляху. Якби Git дозволив і те, refs/tags/fooі інше refs/tags/foo/2, наприклад, він не зміг би цього зробити: йому потрібно було б реалізувати власне сховище ключ-значення. Я думаю, що Git у будь-якому випадку буде змушений впровадити власний сховище ключ-значення, але я не знаю, чи знімуть вони тоді обмеження.
torek

1
@ ĐinhAnhHuy: Я не знаю жодної офіційної документації, що описує це обмеження. Однак підмодулі знаходяться в абсолютно окремому просторі імен: імена підмодулів та імена гілок не повинні зіштовхуватися так само, як імена гілок та імена файлів не стикаються (тобто вони трапляються, але ви додаєте неоднозначність: git checkout -- masterозначає перевірити файл з ім'ям master, а не назву філії).
Торек

60

Я був у стані, коли навіть не міг отримати, бо в моєму репо було інформація про неіснуючі віддалені гілки, які я навіть не перевіряв. Я вирішив це, запустивши комбінацію (спасибі @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'коли я намагався push / pull / fetch
конні

30

Для мене ->

Помилка =

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

3

Спробуйте виконати цю команду:

git gc

запустити ряд господарських завдань у поточному сховищі та видалити недосяжні об’єкти (викликаючи git pruneта git fsck --unreachable).

Детальніше: git help gcіgit help prune


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 refs / tags
  2. git fetch
  3. git pull
  4. git push


1

Як користувач Windows жодне з вирішень досі не вирішило проблему для мене. Причиною того, що я побачив цю помилку, було те, що (використовуючи імена гілок OP) я намагався створити гілку, dev/subале хтось інший створив гілку з назвою, Devі як ми всі знаємо, у Windows є файлова система, що не враховує регістр.

Отже, коли Windows намагався вийти вниз, dev/subвін спочатку намагався створити папку dev, але це не вдалося, оскільки Devвже існувало.

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

Ще одне заняття в майбутньому, назви гілок завжди повинні бути малими, щоб уникнути подібних помилок.


1

Я розумію, на це вже відповіли, але мені це не вдалося. Я не піклувався про місцеві зміни, оскільки вони вже були висунуті, але у мене виникли проблеми з відтягуванням. У моєму випадку ми змінили половину шляху від того, щоб мати "виправлення" як гілку, до системи папок, мати батьківську папку як "виправлення".

- виправлення ---- виправлення / 1234_bug ---- виправлення / 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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.