git push: refs / heads / my / subbranch existe, no se puede crear

84

¿No es posible crear alguna subcarpeta en un repositorio en un servidor?

si lo hago:

git push origin dev/master 

todo el trabajo encuentra

pero si lo hago

git push origin dev/sub/master

tengo esto:

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

Verifiqué con "git branch -r" y directamente con ssh, no hay una carpeta dev / sub ya creada.

que esta mal

Snyf
fuente
1
¿Qué devuelve git ls-remote origin?
Ikke

Respuestas:

152

No es una carpeta que existe, es una rama . (Bueno, puede haber una carpeta / directorio involucrado en alguna parte, o tal vez no, ya que las referencias se "empaquetan" y dejan de existir como archivos dentro de los directorios).

  • Si bexiste una rama, no b/anythingse puede crear ninguna rama con nombre .
  • Del mismo modo, si dev/bexiste una rama , dev/b/cno se puede crear.

Esta es una limitación interna de git. En este caso particular, el control remoto origintiene una rama nombrada dev/sub(independientemente de si la tienes o no, lo importante es si el control remoto la tiene). Para crear, en origin, una rama nombrada dev/sub/master, primero debe eliminar la rama nombrada dev/suben origin:

git push origin :dev/sub

(Por supuesto, eliminar esta rama puede eliminar algo importante allí, así que asegúrese de saber lo que está haciendo. En general, es posible que desee git fetch originprimero, capturar su dev/subcomo su origin/dev/sub. Luego puede hacer una rama local llamada que dev/renamed-subapunte a la misma confirmación , cree dev/renamed-suben el control remoto, elimine el control remoto dev/suby luego cree dev/sub/masteren el control remoto).


Si puede iniciar sesión en el control remoto (el sistema que originestá alojado), puede ir al repositorio de allí y simplemente cambiar el nombre de la dev/subsucursal local . (Según los comentarios a continuación, sospecho que allí también hay un script de implementación automática roto, que probablemente debería arreglarse para implementar solo ramas "implementables", en lugar de todo lo que se empuja. Pero solo estoy adivinando).

torek
fuente
1
Supongo que aquí estamos preocupados por la terminología. Por "limitación interna" me refiero a que es algo que git podría superar sin cambiar cómo alguien usa git. Una limitación incondicional sería algo mucho más fundamental, como, por ejemplo, si alguien rompe SHA1: aunque incluso esto podría superarse (por ejemplo, pasar a SHA256), los detalles de los SHA-1 de 40 caracteres se exponen en, por ejemplo, la mayoría de los ganchos, por lo que esta limitación se filtra a lo externo.
torek
2
Esa es una limitación extrañamente irritante, dado que es posible que desee tener release/1.1y release/1.2con release/1.1/hofix/prevent-upload-bork& release/1.1/hotfix/assure-user-of-competence, etc. Y el mensaje de error lo lleva a uno aquí (gracias), en lugar de indicar la limitación. Pero gracias por una explicación simple y clara.
Benjohn
2
"Esta es una limitación interna de Git". -- ¿Está bien, pero por qué? ¿Fue alguna lógica más fácil de implementar de esta manera? ¿O algún cruce de árboles? ¿O que?
D. Kovács
2
@ D.Kovács: al prohibir ese caso, Git puede simplemente escribir hash de referencia en archivos cuyo nombre se produce al tratar la referencia como un nombre de ruta. Si Git permitiera ambos refs/tags/fooy refs/tags/foo/2, por ejemplo, no podría hacer esto: necesitaría implementar su propio almacén de clave-valor. Creo que Git se verá obligado a implementar su propio almacén de valores clave de todos modos, pero no sé si eliminarán la limitación en ese momento.
torek
1
@ ĐinhAnhHuy: No conozco ninguna documentación formal que describa esta limitación. Los submódulos, sin embargo, están en un espacio de nombres completamente separado: los nombres de los submódulos y los nombres de las ramas no deben colisionar de la misma manera que los nombres de las ramas y los nombres de los archivos no chocan (es decir, lo hacen, pero agrega un desambigador: git checkout -- mastersignifica verificar el archivo nombrado master, en lugar del nombre de la rama).
torek
60

Estaba en un estado en el que ni siquiera podía buscar porque mi repositorio tenía información sobre ramas remotas no existentes que ni siquiera había revisado. Lo resolví ejecutando la combinación (gracias @torek) de:

  • git branch -r enumerar copias locales de sucursales remotas
  • git ls-remote enumerar ramas remotas
  • git fetch --prune origin actualizar copias locales de sucursales remotas ( esto en realidad no me ayudó )
  • git remote prune origineliminar información sobre ramas remotas eliminadas ( esto lo hizo )
meridio
fuente
8
git remote prune originfue el único comando que ejecuté para resolver este estado de error. De hecho, mensaje engañoso: en mi caso, estaba tratando de presionar un "release / 2.6.0" y había eliminado todo el directorio 'refs / remotes / origin / release *', pero git seguía quejándose 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'cada vez que intentaba push / pull / fetch
conny
30

Para mi ->

Error =

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

Solución =

$~ git update-ref -d refs/heads/release/wl
$~ git checkout release/wl/2.3
MEZIDI Hamza
fuente
1
git update-ref -d refs / remotes ... resolvió mi problema a 'refs / remotes / origin / hotfix' existe; no se puede crear 'refs / remotes / origin / hotfix / ISSUE ...
Eduardo
También solucionó mi problema.
Mikhail Morfikov
16

La respuesta actualmente aceptada no me ayudó porque no tenía una referencia en el repositorio remoto para eliminar, ¡estaba puramente en mi local! Entonces, si se encuentra en esa situación, esto es lo que debe hacer:

Este es el problema al que me enfrentaba:

$ 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)

Probé la sugerencia de la respuesta aceptada pero obtuve esto:

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

Así que el árbitro ni siquiera existía en origin- claramente estaba merodeando en algún lugar de mi repositorio local. Entonces corrí $ git remote show me, lo que produjo:

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

Lo que luego dejó clara la solución:

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

Con esto, el problema desapareció:

$ 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
awreccan
fuente
3
Sí, el mismo problema con el que se encontró y lo git remote prune originsolucionó. ¡Gracias!
ToddH
3

Prueba este comando para solucionarlo:

git gc

para ejecutar una serie de tareas de limpieza dentro del repositorio actual y eliminar objetos inalcanzables (invocando git pruneygit fsck --unreachable ).

Leer más: git help gcygit help prune

Kenorb
fuente
2

Si todo lo demás falla, verifique que su sistema de repositorios no tenga limitaciones para los nombres de las sucursales. En mi caso, solo podrías crear ramas que comiencen con SD-<number>. Cualquier otro nombre le daría solo un genérico:

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 '[email protected]:project/repository.git'
Juha Untinen
fuente
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

El script anterior registrará los errores en XXX-errors.log y los solucionará generando y ejecutando un XXX-exist-tags-delete.sh automáticamente desde el XXX-errors.log utilizando los siguientes comandos:

  1. git update-ref -d refs / tags
  2. git fetch
  3. git pull
  4. git push
Tomer Bar-Shlomo
fuente
1

git remote prune origin solucionó el problema para mí

Andrea Gherardi
fuente
1

Como usuario de Windows, ninguna de las soluciones hasta ahora me resolvió el problema. La razón por la que estaba viendo este error era porque (usando los nombres de las ramas del OP) estaba tratando de crear una rama dev/subpero alguien más había creado una rama llamadaDev y, como todos sabemos, Windows tiene un sistema de archivos que no distingue entre mayúsculas y minúsculas.

Entonces, cuando Windows intentó desplegarse dev/sub, primero estaba tratando de crear la carpeta dev, pero no pudo porque Devya existía.

La solución fue eliminar la Devsucursal de forma local y remota con git branch -d Dev && git push origin :Dev. A git pulldespués de esto funcionó bien.

Otra lección en el futuro, los nombres de las sucursales siempre deben estar en minúsculas para evitar este tipo de errores.

alexkb
fuente
1

Entiendo que esto ya está respondido, pero no funcionó para mí. No me importaron los cambios locales, ya que ya estaba subido, pero tenía problemas para retroceder. En mi caso, cambiamos a medio camino entre tener "revisión" como rama al sistema de carpetas y tener la carpeta principal como "revisión".

- revisión ---- revisión / 1234_bug ---- revisión / 3456_bug

Entonces recibí el siguiente error:

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

Después de buscar errores similares, finalmente encontré una solución en un hilo de discusión aquí .

git remote prune origin
Sanjay Zalke
fuente
0
git checkout -b hotfix/my-new-branch

ga
gm "my commit"

gp --set-upstream origin hotfix/subscribers-function
Deslumbrar
fuente
0

Cambie el nombre dev/suba dev/sub/something, luego puede crear una rama dev/sub/master.

catanorar
fuente