Error de Git Push '[remoto rechazado] maestro -> maestro (la rama está actualmente desprotegida)'
Ayer publiqué una pregunta sobre cómo clonar un repositorio Git de una de mis máquinas a otra. ¿Cómo puedo 'clonar git' desde otra máquina? .
Ahora puedo clonar con éxito un repositorio Git desde mi origen (192.168.1.2) a mi destino (192.168.1.1).
Pero cuando edité un archivo, a git commit -a -m "test"
y a git push
, aparece este error en mi destino (192.168.1.1):
git push
[email protected]'s password:
Counting objects: 21, done.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 1010 bytes, done.
Total 11 (delta 9), reused 0 (delta 0)
error: refusing to update checked out branch: refs/heads/master
error: By default, updating the current branch in a non-bare repository
error: is denied, because it will make the index and work tree inconsistent
error: with what you pushed, and will require 'git reset --hard' to match
error: the work tree to HEAD.
error:
error: You can set 'receive.denyCurrentBranch' configuration variable to
error: 'ignore' or 'warn' in the remote repository to allow pushing into
error: its current branch; however, this is not recommended unless you
error: arranged to update its work tree to match what you pushed in some
error: other way.
error:
error: To squelch this message and still keep the default behaviour, set
error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To git+ssh://[email protected]/media/LINUXDATA/working
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'git+ssh://[email protected]/media/LINUXDATA/working'
Estoy usando dos versiones diferentes de Git (1.7 en la máquina remota y 1.5 en la máquina local). ¿Es esa una posible razón?
El mensaje de error error: refusing to update checked out branch: refs/heads/master
lo emite el repositorio remoto y significa que está intentando enviar código a un repositorio remoto no básico que tiene un código diferente actualmente desprotegido en el directorio de trabajo. La mejor manera de evitar este problema es enviar únicamente a repositorios básicos; este problema nunca puede ocurrir con un repositorio básico.
Simplemente puede convertir su repositorio remoto en un repositorio simple (no hay una copia de trabajo en el repositorio simple; la carpeta contiene solo los datos reales del repositorio).
Ejecute el siguiente comando en la carpeta de su repositorio remoto:
git config --bool core.bare true
Luego elimine todos los archivos excepto .git
los de esa carpeta. Y luego podrá acceder git push
al repositorio remoto sin ningún error.
Tuve el mismo error mientras comenzaba a aprender Git . ¡Algunas de las otras respuestas claramente no son para alguien nuevo en Git!
Voy a utilizar términos no técnicos para transmitir la idea. De todos modos, lo que pasa es que tienes dos repositorios, uno es el original que hiciste primero y el otro el trabajo que acabas de hacer.
Ahora mismo estás en tu repositorio de trabajo y estás usando la master
rama. Pero resulta que también "has iniciado sesión" en tu repositorio original en la misma master
rama. Ahora que estás "conectado" en el original, Git teme que puedas equivocarte porque podrías estar trabajando en el original y arruinar las cosas. Entonces necesitas regresar al repositorio original y hacerlo git checkout someotherbranch
, y ahora puedes presionar sin problemas.
El mensaje de error describe lo que ha sucedido. Las versiones más modernas de Git se niegan a actualizar una rama mediante un push si esa rama está desprotegida.
La forma más sencilla de trabajar entre dos repositorios no básicos es
actualice siempre los repositorios mediante extracción (o búsqueda y combinación) o, si es necesario,
presionando a una rama separada (una rama de importación) y luego fusionando esa rama en la rama maestra en la máquina remota.
El motivo de esta restricción es que la operación de inserción opera solo en el repositorio Git remoto, no tiene acceso al índice ni al árbol de trabajo. Por lo tanto, si se permite, presionar la rama desprotegida haría que HEAD
sea inconsistente con el índice y el árbol de trabajo en el repositorio remoto.
Esto haría que fuera muy fácil confirmar accidentalmente un cambio que deshaga todos los cambios introducidos y también haría muy difícil distinguir entre los cambios locales que no se han confirmado y las diferencias entre el HEAD
árbol nuevo, el índice y el de trabajo que se han realizado. causado por el movimiento de empuje HEAD
.
Resumen
No puede enviar a la rama desprotegida de un repositorio porque afectaría al usuario de ese repositorio de una manera que muy probablemente terminará con la pérdida de datos e historial . Pero puedes enviar a cualquier otra rama del mismo repositorio.
Como los repositorios básicos nunca tienen ninguna rama desprotegida, siempre puedes enviar a cualquier rama de un repositorio básico.
Existen múltiples soluciones, dependiendo de sus necesidades.
Solución 1: utilice un repositorio básico
Como se sugirió, si en una máquina no necesita el directorio de trabajo, puede pasar a un repositorio simple. Para evitar jugar con el repositorio, puedes simplemente clonarlo:
machine1$ cd ..
machine1$ mv repo repo.old
machine1$ git clone --bare repo.old repo
Ahora puedes enviar todo lo que quieras a la misma dirección que antes.
Solución 2: enviar a una sucursal no registrada
Pero si necesita verificar el código en su control remoto <remote>
, puede usar una rama especial para presionar. Digamos que en su repositorio local ha llamado a su control remoto origin
y está en la rama maestra. Entonces podrías hacer
machine2$ git push origin master:master+machine2
Luego debes fusionarlo cuando estés en el origin
repositorio remoto:
machine1$ git merge master+machine2
Autopsia del problema
Cuando se retira una rama, la confirmación agregará una nueva confirmación con el encabezado de la rama actual como padre y moverá el encabezado de la rama para que sea esa nueva confirmación.
Entonces
A ← B
↑
[HEAD,branch1]
se convierte
A ← B ← C
↑
[HEAD,branch1]
Pero si alguien pudiera acceder a esa rama intermedia, el usuario entraría en lo que git llama modo de cabeza separada :
A ← B ← X
↑ ↑
[HEAD] [branch1]
Ahora el usuario ya no está en la rama1, sin haber solicitado explícitamente verificar otra rama. Peor aún, el usuario ahora está fuera de cualquier rama y cualquier nueva confirmación quedará suspendida :
[HEAD]
↓
C
↙
A ← B ← X
↑
[branch1]
Hipotéticamente, si en este punto el usuario revisa otra rama, entonces este compromiso pendiente se convierte en un juego limpio para el recolector de basura de Git .