Error de Git Push: negarse a actualizar la rama desprotegida

196

He resuelto algunos conflictos de combinación, me comprometí y luego intenté impulsar mis cambios y recibí el siguiente error:

c:\Program Files (x86)\Git\bin\git.exe push --recurse-submodules=check "origin" master:master
Done
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error: 
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error: 
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To C:/Development/GIT_Repo/Project
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'C:/Development/GIT_Repo/Project'

¿Alguien sabe qué podría estar causando este error?

Miedoso
fuente
66
En realidad, ahora tiene una forma segura de avanzar a un repositorio no descubierto con Git 2.3.0 (febrero de 2015) y git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309
VonC
Posible duplicado del error de inserción
Sören

Respuestas:

229

Motivo: está empujando a un repositorio no descubierto

Hay dos tipos de repositorios: desnudos y no desnudos.

Los repositorios desnudos no tienen una copia que funcione y puede enviarlos a ellos. ¡Esos son los tipos de repositorios que obtienes en Github! Si desea crear un repositorio simple, puede usar

git init --bare

Entonces, en resumen, no puede empujar a un repositorio no descubierto(Editar: Bueno, no puede pasar a la rama actualmente desprotegida de un repositorio. Con un repositorio desnudo, puede pasar a cualquier rama ya que ninguna está desprotegida. Aunque es posible, no es común pasar a repositorios no desnudos) . Lo que puede hacer es buscar y fusionarse desde el otro repositorio. Así es como funciona lo pull requestque puedes ver en Github. Les pides que se alejen de ti y no los empujas a la fuerza.


Actualización : Gracias a VonC por señalar esto, en las últimas versiones de git (actualmente 2.3.0), es posible pasar a la rama desprotegida de un repositorio no desnudo . Sin embargo, todavía no puede empujar a un árbol de trabajo sucio , que de todos modos no es una operación segura.

Shahbaz
fuente
1
¡Si! Esto es correcto, gracias! Como tengo alrededor de un millón de cosas que hacer, accidentalmente cloné el directorio de trabajo ... ¡sí!
Funky
25
En realidad, puede empujar a un repositorio no desnudo muy bien, simplemente no puede empujar a la rama que está actualmente desprotegida .
Hombre de ninguna parte
1
Hay docenas de otros escenarios, en realidad. Por ejemplo, algunos de mis repositorios están solo en mi estación de trabajo y mi computadora portátil (no código, sino notas que tomo). En cada uno tengo dos ramas, "estación de trabajo" y "computadora portátil". En la estación de trabajo, solo reviso "estación de trabajo", y solo presiono a la rama "estación de trabajo" en la computadora portátil (y viceversa).
Hombre de ninguna parte
8
En realidad, ahora tiene una forma segura de pasar a un repositorio no descubierto con Git 2.3.0 (febrero de 2015) y git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309
VonC
1
@skelly Tu clon no está desnudo, mientras que la copia en github. Entonces, si bien ambos clones tienen todo el historial, la copia en github no tiene confirmación confirmada, ¡pero su copia sí, para que pueda trabajar!
Shahbaz
115

Resolví este problema verificando primero que el control remoto no tenía nada verificado (realmente no se suponía que lo hiciera), y luego lo descubrí con:

$ git config --bool core.bare true

Después de ese empujón git funcionó bien.

Sasha Pachev
fuente
3
Esta es la solución única que estaba buscando ... pero tal vez explique los repositorios no desnudos como la respuesta
@shahbaz
Esto permitirá que se empuje el historial de cambios, pero esos cambios no se reflejarán en el repositorio no descubierto.
jhill515
¿verdad git config core.bare falsey git reset --hard ?
Avión
1
Como se mencionó anteriormente, el control remoto no se modificará cuando lo presione.
user1097111
46

Resumen

No puede pasar a la rama desprotegida de un repositorio porque se dañaría con el usuario de ese repositorio de una manera que probablemente terminará con la pérdida de datos e historial . Pero puede empujar a cualquier otra rama del mismo repositorio.

Como los repositorios desnudos nunca tienen una rama desprotegida, siempre puede pasar a cualquier rama de un repositorio desnudo.

Autopsia del problema

Cuando se desprotege una rama, la confirmación agregará una nueva confirmación con el encabezado de la rama actual como padre y moverá la cabeza de la rama para que sea ese nuevo compromiso.

Entonces

A ← B
    ↑
[HEAD,branch1]

se convierte

A ← B ← C
        ↑
    [HEAD,branch1]

Pero si alguien pudiera empujar a esa rama intermedia, el usuario se pondrí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 pedido explícitamente que revise otra rama. Peor aún, el usuario ahora está fuera de cualquier rama , y cualquier nueva confirmación simplemente estará colgando :

      [HEAD]
        ↓
        C
      ↙
A ← B ← X
        ↑
       [branch1]

Hipotéticamente, si en este punto, el usuario comprueba otra rama, entonces este compromiso colgante se convierte en un juego justo para el recolector de basura de Git .

Hombre de ningún lado
fuente
Me expandí un poco en stackoverflow.com/questions/2816369/…
Nowhere man
21

cd en el directorio repo / que está presionando en la máquina remota e ingrese

$ git config core.bare true
Ricky
fuente
Esto no funciona. El repositorio permanece vacío después de empujarlo.
Sören
como dijo jhil515 arriba, los archivos no desnudos no se actualizan, solo las bases de datos.
Denis Cousineau
19

Para mí, lo siguiente hizo el truco:

git config --global receive.denyCurrentBranch updateInstead

Configuré la unidad F :, casi en su totalidad, para sincronizar entre mi escritorio de Windows 10 y mi computadora portátil con Windows 10, usando Git. Terminé ejecutando el comando anterior en ambas máquinas.

Primero compartí la unidad F del escritorio en la red. Luego pude clonarlo en mi computadora portátil ejecutando:

F: git clone 'file://///DESKTOP-PC/f'

Desafortunadamente, todos los archivos terminaron en "F: \ f \" en mi computadora portátil, no en F: \ directamente. Pero pude cortarlos y pegarlos manualmente. Git todavía trabajó desde la nueva ubicación después.

Luego intenté hacer algunos cambios en los archivos de la computadora portátil, comprometerlos y volver a colocarlos en el escritorio. Eso no funcionó hasta que ejecuté el comando git config mencionado anteriormente.

Tenga en cuenta que ejecuté todos estos comandos desde Windows PowerShell, en ambas máquinas.

ACTUALIZACIÓN: Todavía tenía problemas para impulsar los cambios, en algunos casos. Finalmente, comencé a realizar cambios, ejecutando lo siguiente en la computadora en la que quiero obtener los últimos commit (s) para:

git pull --all --prune

Stephen G Tuggy
fuente
1
Prefiero este local al repositorio git:git config receive.denyCurrentBranch updateInstead
klor
14

Como ya hay un repositorio existente, ejecutándose

git config --bool core.bare true

en el repositorio remoto debería ser suficiente

De la documentación de core.bare

Si es verdadero (desnudo = verdadero), se supone que el repositorio está vacío sin ningún directorio de trabajo asociado. Si este es el caso, se deshabilitarán varios comandos que requieren un directorio de trabajo, como git-add o git-merge (pero podrá presionarlo).

Git-clone o git-init adivinan automáticamente esta configuración cuando se crea el repositorio. Por defecto, se supone que un repositorio que termina en "/.git" no está vacío (desnudo = falso), mientras que se supone que todos los demás repositorios están desnudos (desnudo = verdadero).

Johnny
fuente
12

TLDR

  1. Pull & empujar de nuevo: git pull &&& git push.
  2. ¿Sigue siendo un problema? Empuje en una rama diferente: git push origin master:fooy combínelo en un repositorio remoto.
  3. Alternativamente, fuerce el empuje agregando -f( denyCurrentBranchdebe ignorarse).

Básicamente, el error significa que su repositorio no está actualizado con el código remoto (su índice y árbol de trabajo es inconsistente con lo que presionó).

Normalmente, pullprimero debe obtener los cambios recientes y pushnuevamente.

Si no ayuda, intente ingresar a una rama diferente, por ejemplo:

git push origin master:foo

luego combine esta rama en el repositorio remoto con master.

Si cambió intencionalmente algunas confirmaciones pasadas a través de git rebasey desea anular el repositorio con sus cambios, probablemente desee forzar la inserción agregando -f/ --forceparámetro (no recomendado si no lo hizo rebase). Si todavía no funciona, usted necesita fijar receive.denyCurrentBrancha ignoredel mando a distancia como se sugiere en un mensaje a través de git:

git config receive.denyCurrentBranch ignore
kenorb
fuente
3

Tal vez su repositorio remoto esté en la rama que desea empujar. Puede intentar pagar otra sucursal en su máquina remota. Hice esto, entonces estos errores desaparecieron, y llevé el éxito a mi repositorio remoto. Tenga en cuenta que uso ssh para conectar mi propio servidor en lugar de github.com.

Jzau
fuente
1

Tengo este error porque el repositorio git se inicializó (accidentalmente) dos veces en la misma ubicación: primero como un repositorio no desnudo y poco después como un repositorio desnudo. Debido a que la carpeta .git permanece, git asume que el repositorio no está desnudo. Eliminar la carpeta .git y los datos del directorio de trabajo resolvió el problema.

xastor
fuente
1
En mi situación, este fue el caso. La eliminación de la .gitcarpeta en el control remoto me permitió empujar la confirmación inicial.
tim.rohrer
0

Recibí este error cuando estaba jugando mientras leía progit. Hice un repositorio local, luego lo busqué en otro repositorio en el mismo sistema de archivos, hice una edición e intenté empujar. Después de leer la respuesta de NowhereMan, una solución rápida fue ir al directorio "remoto" y verificar temporalmente otra confirmación, presionar desde el directorio en el que hice los cambios, luego regresar y volver a poner la cabeza en el maestro.

Nathan Chappell
fuente