Error de inserción de Git 'maestro [rechazado remotamente] -> maestro (la rama está actualmente desprotegida)'

961

Ayer, publiqué una pregunta sobre cómo clonar un repositorio Git de una de mis máquinas a otra, ¿cómo puedo 'clonar' desde otra máquina? .

Ahora puedo clonar con éxito un repositorio Git desde mi fuente (192.168.1.2) a mi destino (192.168.1.1).

Pero cuando hice una edición en un archivo, ay git commit -a -m "test"a git push, recibí 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 el control remoto y 1.5 en la máquina local). ¿Es esa una posible razón?

hap497
fuente
55
¿Puede cualquier veterano cambiar la respuesta aceptada a stackoverflow.com/a/9283833/397872 y mover el hilo al archivo o algo así? ¿O cambiar de dueño o lo que sea?
rishta
99
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
Ese es el nuevo enlace del libro que @stigi ha mencionado: git-scm.com/book/en/v1/Git-on-the-Server
Abdelilah El Aissaoui
Pero no entiendo por qué y cómo funciona. Está funcionando, sí, pero eso es todo.
Tilak Maddy

Respuestas:

1149

Simplemente puede convertir su repositorio remoto en repositorio básico (no hay una copia de trabajo en el repositorio básico; la carpeta contiene solo los datos reales del repositorio).

Ejecute el siguiente comando en su carpeta de repositorio remoto:

git config --bool core.bare true

Luego elimine todos los archivos excepto .giten esa carpeta. Y luego podrá realizar git pushel repositorio remoto sin ningún error.

Juan
fuente
44
Gracias. También necesitaba esto. Estaba siguiendo el tutorial de submódulos del Git Community Book y llegué a este obstáculo.
Shiki
66
No estaba seguro de si querías eliminar archivos en el servidor o en el cliente ... así que no eliminé nada y el problema desaparece después de hacerlo git config --bool core.bare true. ¿Hay alguna razón en particular para eliminar algunos archivos? Si es así, ¿puede ser más preciso sobre lo que debe eliminarse?
Brian Vandenberg
24
Es la mejor respuesta posible y nadie más la ha proporcionado en el agujero de Interwebs. Creo que todos buscamos en Google el mismo mensaje de error y todos estábamos extremadamente felices de leer esto.
Sebastián Grignoli
40
Aunque obtuvo muchos votos, no creo que esta sea una respuesta realmente adecuada a esa pregunta específica. Instruir al usuario sobre cómo crear limpiamente un repositorio desnudo sería la mitad de malo, pero ¿qué pasa si los archivos deben permanecer desprotegidos, por ejemplo, cuando es el repositorio con el que el usuario está trabajando en dos computadoras?
Nowhere man
99
Cambiar el repositorio de origen a desnudo es excesivo. Todo lo que necesita hacer es avanzar a una nueva sucursal en el repositorio de origen, como señala @Robert: stackoverflow.com/a/2933656/402949 .
Dan Solovay
708

Simplemente tuve el mismo error mientras comencé a aprender Git . ¡Algunas de las otras respuestas claramente no son para alguien nuevo en Git!

(Voy a usar términos no técnicos para comunicar la idea). De todos modos, lo que está sucediendo es que tienes dos repositorios, uno es el original que hiciste por primera vez y el otro el trabajo que acabas de hacer.

En este momento está en su repositorio de trabajo y está utilizando la rama "maestra". Pero también está "conectado" en su repositorio original a la misma rama "maestra". Ahora, dado que está "conectado" en el original, Git teme que pueda equivocarse porque podría estar trabajando en el original y arruinar las cosas. Por lo tanto, debe volver al repositorio original y hacer un "git checkout someotherbranch", y ahora puede presionar sin problemas.

Espero que esto ayude.

Robert Gould
fuente
76
+1 Mucho más útil, gracias Robert. No tenía sentido convertirme en un repositorio desnudo en mi caso. Simplemente tiene que 'desactivar' la rama a la que intenta empujar. Tiene sentido.
Eric Muyser 01 de
32
@ FMaz008: solo crea una rama ficticia (git checkout -b dummy)
Dror Cohen
14
Hombre, esto es mucho mejor que la respuesta más votada :) Gracias. Aunque la otra respuesta también hace buen punto :)
Ivan Ivanić
103
Sólo para hacer esto más claro, en el repositorio que es el objetivo de la presión: git checkout -b tmp. Luego, en la fuente de repo: git push. Luego de vuelta en el objetivo (opcional):git checkout master; git branch -d tmp
Hari Karam Singh
18
El comentario de Hari es la receta más simple. Solo tengo que decir que si bien git puede ser excelente en muchos sentidos, viniendo de svn o probablemente de cualquier otro rvs, todo esto es asombrosamente no intuitivo.
Incondicionalmente,
128

El mensaje de error describe lo que sucedió. Las versiones más modernas de Git se niegan a actualizar una rama a través de un push si esa rama está desprotegida.

La forma más fácil de trabajar entre dos repositorios no descubiertos es

  1. siempre actualice los repositorios mediante extracción (o recuperación y fusión) o, si es necesario,

  2. empujando a una rama separada (una rama de importación) y luego fusionando esa rama en la rama maestra en la máquina remota.

La razón de esta restricción es que la operación de inserción solo funciona en el repositorio remoto de Git, no tiene acceso al índice ni al árbol de trabajo. Por lo tanto, si se permite, un empuje en la rama desprotegida cambiaría el HEAD para ser inconsistente con el índice y el árbol de trabajo en el repositorio remoto.

Esto haría muy fácil cometer accidentalmente un cambio que deshaga todos los cambios empujados y también hace que sea muy difícil distinguir entre los cambios locales que no se han comprometido y las diferencias entre el nuevo HEAD, el índice y el árbol de trabajo que se han causado por empuje en movimiento HEAD.

CB Bailey
fuente
1
Gracias. Entonces, ¿cómo puedo solucionar mi problema? En mi cuadro 192, hice '$ cd (directorio del proyecto) $ git init $ (agregue algunos archivos) $ git add'. y luego en mi cuadro 191, hice un 'git clone' y edité algunos archivos y luego intenté 'git push'.
hap497
16
Bueno, describí las posibilidades en mi respuesta. Puede ir al cuadro 192 y buscar desde el cuadro 191 (es posible que desee agregar el cuadro 191 como un control remoto con nombre, mire git remote add box191 <191url>), o puede pasar del cuadro 191 a una rama con un nombre alternativo (por ejemplo git push origin master:refs/heads/upload), luego a la casilla 192 y fusionar (por ejemplo git merge upload).
CB Bailey
3
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 : ya no necesita la opción 2.
VonC
122

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.

Existen múltiples soluciones, según sus necesidades.

Solución 1: Use un repositorio desnudo

Como se sugiere, si en una máquina no necesita el directorio de trabajo, puede pasar a un repositorio vacío. Para evitar jugar con el repositorio, puede simplemente clonarlo:

machine1$ cd ..
machine1$ mv repo repo.old
machine1$ git clone --bare repo.old repo

Ahora puede enviar todo lo que desee a la misma dirección que antes.

Solución 2: empuje a una rama 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 originy está en la rama maestra. Entonces podrías hacer

machine2$ git push origin master:master+machine2

Luego debe fusionarlo cuando esté en el originrepositorio remoto:

machine1$ git merge master+machine2

Autopsia del problema

Cuando se desprotege una rama, la confirmación agregará una nueva confirmación con la cabeza de la rama actual como padre y moverá la cabeza 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 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 branch1, 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
3
Una corrección técnica a la "autopsia": git no se separará HEADen el repositorio. HEADtodavía apuntará a la rama, y ​​la rama a su vez apuntará a los nuevos commit (s) empujados; pero el directorio de trabajo y el índice / área de ensayo no se modificarán. Quien esté trabajando en el repositorio forzado ahora tiene que trabajar duro para recuperarse de los efectos del forzado: averigüe si hay cambios para guardar y, si es así, haga arreglos para guardarlos.
torek
Para agregar información adicional a su respuesta, hay muy pocas razones por las que desearía un repositorio remoto que la gente empuje para que no esté desnudo, por lo que usar un repositorio desnudo es la mejor solución.
2
En realidad, encontré muchas situaciones en las que necesito empujar a un repositorio no desnudo, y uso bastante la solución 2. Además, la rama donde presiono el repositorio no desnudo no es de ninguna manera una rama temporal, tiene un propósito similar al de una rama de seguimiento remoto.
Nowhere man
Creé una carpeta GIT en mi servidor que alojará TODOS los repositorios creados por múltiples usuarios que usan SourceTree. Creé un masterrepositorio en mi PC local. Agregué elremotes archivo a la carpeta del servidor e intenté insertar mi repositorio en el servidor para que otro usuario pueda extraerlo y buscarlo para trabajar. Recibo el siguiente error: ! [remote rejected] master -> master (branch is currently checked out)¿Cómo puedo registrarlo?
SearchForKnowledge
1
@SearchForKnowledge, ¿te das cuenta de que estás haciendo exactamente la pregunta que estoy respondiendo?
Hombre de ninguna parte
65

Puede evitar esta "limitación" editando .git/configen el servidor de destino. Agregue lo siguiente para permitir que se inserte un repositorio git incluso si está "desprotegido":

[receive]
denyCurrentBranch = warn

o

[receive]
denyCurrentBranch = false

El primero permitirá el empuje mientras advierte sobre la posibilidad de estropear la rama, mientras que el segundo lo permitirá en silencio.

Esto se puede usar para "implementar" código en un servidor que no está destinado a la edición. Este no es el mejor enfoque, pero sí uno rápido para implementar el código.

Kris
fuente
77
Usar esto para "implementar" código en un servidor no funcionará. Incluso si deshabilita la advertencia para poder pasar a la rama desprotegida, la copia de trabajo NUNCA se actualiza al presionar.
Arrowmaster
10
Estoy usando el método anterior con cd .. && git reset --hardgancho posterior a la recepción para implementar. Hackish, pero funciona.
jholster
99
la versión de línea de comando de este último seríagit config receive.denyCurrentBranch warn
Andre Holzner,
44
Esta debería ser la respuesta aceptada. Algunos de nosotros sabemos lo que estamos haciendo y no somos principiantes de Git. Esta es la respuesta para esas personas.
Qix - MONICA FUE MAL TRATADA el
2
Ja, pero la pregunta no fue hecha por esas personas.
Nowhere man
46

git config --local receive.denyCurrentBranch updateInstead

https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

Use eso en el repositorio del servidor, y también actualiza el árbol de trabajo si no se produce una sobrescritura sin seguimiento.

Fue agregado en Git 2.3 como lo menciona VonC en los comentarios.

He compilado Git 2.3 y lo he probado. Uso de la muestra:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

Salida:

a
b

Yay, bme empujaron!

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
@VonC gracias! Es mi obsesión con ejemplos mínimos en el trabajo :-)
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
¿Tiene algún problema para confirmar cambios que no están actualizados con el servidor?
akozi
@akozi No estoy seguro de lo que quieres decir, si te comprometes localmente antes de tirar, se comportará exactamente como un --bareclon tradicional , creo: --forcees necesario presionar, y te hará "perder" los compromisos en el control remoto.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功 No te preocupes ahora. Busqué el significado de las opciones. Pensé que updateInstead era sinónimo de fuerza.
akozi
updateInstead ya no es un valor válido para
recibir.denyCurrentBranch
41

Me gusta la idea de seguir teniendo un repositorio utilizable en la caja remota, pero en lugar de una rama ficticia, me gusta usar:

git checkout --detach

Esta parece ser una característica muy nueva de Git : estoy usando git versión 1.7.7.4.

apilar
fuente
8
Y luego, después de impulsar los cambios, puede usar: git checkout masterpara volver a la rama maestra. Solo entonces se aplican sus cambios.
MAZDAK
30

Tuve el mismo problema. Para mí, uso Git push para mover el código a mis servidores. Nunca cambio el código en el lado del servidor, así que esto es seguro.

En el repositorio, está presionando para escribir:

git config receive.denyCurrentBranch ignore

Esto le permitirá cambiar el repositorio mientras sea una copia de trabajo.

Después de ejecutar un Git push, vaya a la máquina remota y escriba esto:

git checkout -f

Esto hará que los cambios que presionó se reflejen en la copia de trabajo de la máquina remota.

Tenga en cuenta que esto no siempre es seguro si realiza cambios en la copia de trabajo que está presionando.

Orbital_sMiedo
fuente
gracias un registro, fusiono su sugerencia denyCurrentBranchy puse git checkout -fdentro de la hookscarpeta como @ jack-senechal publicado aquí
Éderson T. Szlachta
¿Hay alguna manera de hacer que los archivos aparezcan en el repositorio Remoto sin tener que ir y ejecutar este comando? ¿A saber por un comando del local?
Royi
24

Puede volver a crear el repositorio de su servidor y pasar del maestro de sucursal local al maestro del servidor.

En su servidor remoto:

mkdir myrepo.git
cd myrepo.git
git init --bare

OK, desde su sucursal local:

git push origin master:master
nau
fuente
3
Gracias, esta fue la solución para mí, ya que había omitido '--bare' en el servidor remoto. Parece que las respuestas a esta pregunta dependen de si está utilizando el repositorio del servidor remoto como un directorio de trabajo o no, y para el caso posterior, esta es la respuesta correcta.
Cas
2
No entiendo: SI trató de crear y clonar un repositorio desnudo, pero el clon no descargó nada y no cargó nada, así que esto no funciona ... :-) Leí tutoriales sobre repositorios desnudos, pero dicen que un repositorio desnudo no contiene archivos ... Eso definitivamente no es lo que estoy buscando ...
inf3rno
22

Lo que probablemente hiciste para causar esto:

Este tipo de cosas suceden cuando vas a sacar un pequeño programa. Estás a punto de cambiar algo que ya estaba funcionando, por lo que lanzas tu hechizo de nivel 3 de inutilización perpetua:

machine1:~/proj1> git init

y comienzas a agregar / comprometerse. Pero luego , el proyecto comienza a involucrarse más y desea trabajar en él desde otra computadora (como la PC o computadora portátil de su casa), por lo que debe hacer algo como

machine2:~> git clone ssh://machine1/~/proj1

y se clona y todo se ve bien, así que trabajas en tu código desde machine2.

Entonces ... intenta empujar sus confirmaciones de machine2, y recibe el mensaje de advertencia en el título.

La razón de este mensaje es porque el repositorio de git del que sacó estaba destinado a usarse solo para esa carpeta en la máquina1. Puedes clonar bien, pero empujar puede causar problemas. La forma "adecuada" de administrar el código en dos ubicaciones diferentes es con un repositorio "desnudo", como se ha sugerido. Un repositorio simple no está diseñado para que se realice ningún trabajo en él, está destinado a coordinar las confirmaciones de múltiples fuentes. Esta es la razón por la cual la respuesta mejor calificada sugiere eliminar todos los archivos / carpetas que no sean la carpeta .git después de usted git config --bool core.bare true.

Aclarando la respuesta mejor calificada: muchos de los comentarios a esa respuesta dicen algo así como "No eliminé los archivos que no son .git de la máquina1 y aún podía confirmar desde la máquina2". Así es. Sin embargo, esos otros archivos están completamente "divorciados" del repositorio de git, ahora. Vaya intente git statusallí y debería ver algo como "fatal: esta operación debe ejecutarse en un árbol de trabajo". Por lo tanto, la sugerencia de eliminar los archivos no es para que funcione el commit de machine2 ; es para que no te confundas y pienses que git sigue rastreando esos archivos. Pero, eliminar los archivos es un problema si aún desea trabajar en los archivos de la máquina1, ¿no es así?

Entonces, ¿qué deberías hacer realmente?

Depende de cuánto planee seguir trabajando en machine1 y machine2 ...

Si ha terminado de desarrollar desde machine1 y ha movido todo su desarrollo a machine2 ... simplemente haga lo que sugiere la respuesta mejor calificada: git config --bool core.bare truey luego, opcionalmente, elimine todos los archivos / carpetas que no sean .git de esa carpeta, ya que No se realiza un seguimiento y es probable que cause confusión.

Si su trabajo en machine2 fue solo una vez, y no necesita continuar el desarrollo allí ... entonces no se moleste en hacer un repositorio simple; solo ftp / rsync / scp / etc. sus archivos de la máquina * 2 * encima de los archivos de la máquina * 1 *, confirme / envíe desde la máquina * 1 * y luego elimine los archivos de la máquina * 2 *. Otros han sugerido crear una rama, pero creo que es un poco desordenado si solo desea fusionar un desarrollo que hizo una vez desde otra máquina.

Si necesita continuar con el desarrollo tanto en la máquina1 como en la máquina2 ... entonces necesita configurar las cosas correctamente. Necesitas convertir tu repositorio en un simple, luego debes hacer un clon de eso en la máquina1 para que puedas trabajar . Probablemente la forma más rápida de hacerlo es hacerlo

machine1:~/proj1> git config --bool core.bare true
machine1:~/proj1> mv .git/ ../proj1.git
machine1:~/proj1> cd ..
machine1:~> rm -rf proj1
machine1:~> git clone proj1.git
machine1:~> cd proj1

Muy importante: debido a que movió la ubicación del repositorio de proj1 a proj1.git, debe actualizar esto en el archivo .git / config en machine2 . Después de eso, puede confirmar sus cambios desde machine2. Por último, trato de mantener mis repositorios desnudos en una ubicación central, lejos de mis árboles de trabajo (es decir, no coloque 'proj1.git' en la misma carpeta principal que 'proj1'). Le aconsejo que haga lo mismo, pero quería que los pasos anteriores fueran lo más simples posible.

Jemenake
fuente
Muy detallado y útil. Mi caso fue el último, y sus instrucciones funcionaron como un encanto.
pojda
Estoy en el caso 3 e hice algo ligeramente diferente: mk git-server; mv .git git-server / proj.git y luego git clone git-server / proj.git a 1 y 2 (u origen remoto de git ...), utilizando un prefijo ssh: // apropiado para la máquina 2. De esta manera Mantendré una copia maestra desnuda que será como la que normalmente está en GH u otro servidor HTTP y seguiré usando push / pull en ambas máquinas.
zakmck
18

Con unos pocos pasos de configuración, puede implementar fácilmente los cambios en su sitio web utilizando una línea como

git push production

Lo cual es agradable y simple, y no tiene que iniciar sesión en el servidor remoto y hacer un tirón ni nada. ¡Tenga en cuenta que esto funcionará mejor si no utiliza su pago de producción como una rama de trabajo! (El OP estaba funcionando dentro de un contexto ligeramente diferente, y creo que la solución de @Robert Gould lo abordó bien. Esta solución es más apropiada para la implementación en un servidor remoto).

Primero debe configurar un repositorio desnudo en algún lugar de su servidor, fuera de su raíz web.

mkdir mywebsite.git
cd mywebsite.git
git init --bare

Luego cree el archivo hooks/post-receive:

#!/bin/sh
GIT_WORK_TREE=/path/to/webroot/of/mywebsite git checkout -f

Y haga que el archivo sea ejecutable:

chmod +x hooks/post-receive

En su máquina local,

git remote add production [email protected]:mywebsite.git
git push production +master:refs/heads/master

¡Todo listo! ¡Ahora en el futuro puede usar git push productionpara implementar sus cambios!

El crédito para esta solución va a http://sebduggan.com/blog/deploy-your-website-changes-using-git/ . Busque allí una explicación más detallada de lo que está sucediendo.

Jack Senechal
fuente
Su sugerencia me ayudó mucho, pero no la utilicé bare, seguí esto y me fusioné con hooks(que sugirió) y funcionó a la perfección.
Éderson T. Szlachta
11

Solo debe empujar a un repositorio desnudo. Un repositorio simple es un repositorio que no tiene ramas desprotegidas. Si tuviera que cd a un directorio de repositorio simple, solo vería el contenido de un directorio .git.

RibaldEddie
fuente
99
No hay nada de malo en pasar a una rama no registrada en un repositorio no descubierto. Esta es una forma de trabajo perfectamente válida.
CB Bailey
Bastante justo, eso funcionaría. Pero eso no es lo que está haciendo el usuario.
RibaldEddie
13
No es el hecho de que no esté usando un repositorio desnudo lo que está "mal"; Es el hecho de que está empujando a una sucursal desprotegida. No hay evidencia de que tenga o quiera un repositorio desnudo separado, por lo que su declaración general de que solo debería estar presionando a un repositorio no desnudo no le está dando al solicitante todas las opciones; uno de los cuales podría resolver más fácilmente su problema inmediato.
CB Bailey
10

Tienes 3 opciones

  1. Tire y empuje nuevamente:

    git pull; git push
    
  2. Empuje en una rama diferente:

    git push origin master:foo
    

    y fusionarla del mando a distancia (ya sea por gito pull-petición )

    git merge foo
    
  3. Forzarlo (no recomendado a menos que haya cambiado deliberadamente las confirmaciones a través de rebase):

    git push origin master -f
    

    Si aún se rechaza, deshabilite denyCurrentBranch en el repositorio remoto:

    git config receive.denyCurrentBranch ignore
    
kenorb
fuente
La opción 2 funciona para mí. maestro de origen de empuje de git local de inicio remoto de git: fusión de git remoto de rama HECHO
Jacky Chong
7

De hecho, establecer el control remoto en una rama no extraída es suficiente. Después de retirar su control remoto en una rama diferente, puede presionar.

sebthemonster
fuente
7

Comprueba tu .git/configen el proyecto de destino:

$ cat .git/config 
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[receive]
    denyCurrentBranch = updateInstead

Si el core. barees falso, puede establecerlo en verdadero:

$ git config core.bare true

y luego en su empuje local a remoto:

git push remote_repo   // suppose the destination repo is remote_repo

tendrá éxito, en remote_repo puede verificar la versión de git.

$ git log -1
commit 0623b1b900ef7331b9184722a5381bbdd2d935ba
Author: aircraft < [email protected]>
Date:   Thu May 17 21:54:37 2018 +0800

y ahora no puedes usar git en tu "espacio de trabajo":

$ git status
fatal: This operation must be run in a work tree

deberías bare.barevolver a ponerlo en falso.

$ git config core.bare false
aeronave
fuente
5

Tuve el mismo problema al usar Git para sincronizar repositorios en mi teléfono y computadora portátil Android. La solución para mí fue hacer un tirón en lugar de un empujón, como sugirió @CharlesBailey.

git push origin master en el repositorio de Android me falla con los mismos mensajes de error que recibió @ hap497 debido a un empuje a un pago no comprobado de un repositorio + copia de trabajo.

git pull droid masteren el repositorio de la computadora portátil y la copia de trabajo funciona para mí. Por supuesto, debe haber ejecutado previamente algo así git remote add droid /media/KINGSTON4GB/notes_repo/.

placas
fuente
4

Las versiones anteriores de Git solían permitir los envíos a la rama actualmente desprotegida de un repositorio no descubierto.

Resulta que esto era una cosa terriblemente confusa para permitir. Entonces agregaron el mensaje de advertencia que ves, que también es terriblemente confuso.

Si el primer repositorio solo está actuando como un servidor, conviértalo en un repositorio desnudo como lo recomiendan las otras respuestas y termine con él.

Sin embargo, si necesita tener una rama compartida entre dos repositorios que están en uso, puede lograrlo con la siguiente configuración

Repo1: actuará como servidor y también se utilizará para el desarrollo

Repo2 - será solo para desarrollo

Configure Repo1 de la siguiente manera

Crea una rama para compartir el trabajo.

git branch shared_branch

Para estar seguro, también debe crear un $ (REPO) .git / hooks / update que rechace cualquier cambio a cualquier otra cosa que no sea shared_branch, porque no desea que las personas se burlen de sus sucursales privadas.

repo1/.git/hooks  (GIT_DIR!)$ cat update
#!/bin/sh
refname="$1"
oldrev="$2"
newrev="$3"

if [ "${refname}" != "refs/heads/shared_branch" ]
then
   echo "You can only push changes to shared_branch, you cannot push to ${refname}"
   exit 1
fi

Ahora crea una sucursal local en repo1 donde harás tu trabajo real.

git checkout -b my_work --track shared_branch
Branch my_work set up to track local branch shared_branch.
Switched to a new branch 'my_work'

(puede ser necesario git config --global push.default upstreamparagit push trabajar)

Ahora puedes crear repo2 con

git clone path/to/repo1 repo2 
git checkout shared_branch 

En este punto, tiene la configuración repo1 y repo2 para trabajar en las sucursales locales que empujan y shared_branchextraen de repo1, sin necesidad de preocuparse por ese mensaje de error o que el directorio de trabajo no esté sincronizado en repo1. Cualquier flujo de trabajo normal que use debería funcionar.

Andrew C
fuente
3

OK, en caso de que desee un repositorio remoto normal, cree una rama adicional y compruébelo. Empújelo en una rama (que no está desprotegida) y combínelo con uno que esté activo actualmente más tarde después de presionar desde localmente.

Por ejemplo, en un servidor remoto:

git branch dev
git checkout dev

En la configuración local:

git push 

En servidor remoto:

git merge dev
Sr. codificador
fuente
2

Aquí hay una prueba que puede hacer para ver cómo funcionan las barecosas del servidor:

Imagine que tiene una estación de trabajo y un servidor con un sitio en vivo alojado en él, y desea actualizar este sitio de vez en cuando (esto también se aplica a una situación en la que dos desarrolladores envían su trabajo de un lado a otro a través de un intermediario).

Inicialización

Cree un directorio en su computadora local y cden él, luego ejecute estos comandos:

# initialization
git init --bare server/.git
git clone server content
git clone server local
  1. Primero crea un serverdirectorio simple (observe el .git al final). Este directorio servirá como contenedor solo para sus archivos de repositorio.
  2. Luego clone el repositorio de su servidor en un contentdirectorio recién creado . Este es su directorio live / production que será servido por su software de servidor.
  3. Los dos primeros directorios residen en su servidor, el tercero es un directorio local en su estación de trabajo.

Flujo de trabajo

Ahora aquí está el flujo de trabajo básico:

  1. Ingrese al localdirectorio, cree algunos archivos y confírmelos. Finalmente empujarlos al servidor:

    # create crazy stuff
    git commit -av
    git push origin master
    
  2. Ahora ingrese el contentdirectorio y actualice el contenido del servidor:

    git pull
    
  3. Repetir 1-2. Aquí contentpuede haber otro desarrollador que también puede empujar al servidor, y localcomo puede sacar de él.

simo
fuente
2

Usar esto para llevarlo a la rama ascendente remota me resolvió este problema:

git push <remote> master:origin/master

El control remoto no tenía acceso al repositorio ascendente, por lo que esta era una buena manera de obtener los últimos cambios en ese control remoto

jontro
fuente
1
Más generalmente (ya que este es el efecto neto del comando), usando git push <remote> master:newbranch. La idea es que inserte una nueva rama en el control remoto, que luego se puede fusionar. De esta manera, evita cualquiera de los problemas de inconsistencia mencionados en el mensaje de error.
Clay
1

Tuve que volver a ejecutar git --initen un repositorio vacío existente, y esto había creado un .gitdirectorio dentro del árbol del repositorio vacío. Me di cuenta de eso después de escribir git statusallí. Lo borré y todo volvió a estar bien :)

(Todas estas respuestas son geniales, pero en mi caso fue algo completamente diferente (hasta donde puedo ver), como se describe).

ene
fuente
1

Estoy seguro de que la mayoría de las personas que ven esta pregunta se detendrán en las dos primeras respuestas importantes, pero aún así me gustaría ofrecer mi solución.

Tuve una configuración de proyecto web Eclipse + EGit cuando encontré el error descrito. Lo que me ayudó fue simplemente usar la aplicación GitHub, que parecía resolver mágicamente el problema. Si bien EGit siempre rechazaría el impulso, la aplicación de escritorio GitHub simplemente se encogería de hombros y presionaría mis cambios. Tal vez maneja la situación de inicio de sesión múltiple con más gracia.

pila
fuente
1

Un artículo que encontré que podría ser útil para otros es Git en 5 minutos .

Tenía un proyecto Xcode bajo control de versión Git que quería impulsar a un Ethernet distribuido virtual (VDE) que tengo en un DC. El VDE ejecuta Centos 5.

Ninguno de los artículos que leí sobre Git hablaba de repositorios desnudos. Todo sonaba tan simple hasta que probé lo que pensé que debería ser fácil de un fondo SVN .

Las sugerencias aquí para hacer que el repositorio remoto funcione desnudo. Aún mejor para mis requisitos fue clonar el proyecto Xcode paraprojectname.git , copiarlo en el servidor remoto; luego empuja mágicamente trabajado. El siguiente paso será hacer que Xcode empuje sin errores sobre commits, pero por ahora estoy bien haciéndolo desde Terminal.

Entonces:

cd /tmp (or another other directory on your system)<br/>
git clone --bare /xcode-project-directory projectname.git<br/>
scp -r projectname.git [email protected]:repos/<br/>

Para impulsar los cambios de su proyecto Xcode después de haberse comprometido en Xcode:

cd /xcode-project-directory<br/>
git push [email protected]:repos/projectname.git<br/>

Estoy seguro de que hay una manera más suave y sofisticada de hacer lo anterior, pero como mínimo esto funciona. Para que todo esté claro, aquí hay algunas aclaraciones: /xcode-project-directoryes el directorio en el que se almacena su proyecto xcode. Probablemente sea/Users/Your_Name/Documents/Project_Name . nombre del proyecto es literalmente el nombre del proyecto, pero puede ser cualquier cosa que quieras llamarlo. A Git no le importa, lo harás.

Para utilizar scp, debe tener una cuenta de usuario en el servidor remoto que permita el acceso SSH . Cualquiera que ejecute su propio servidor tendrá esto. Si está utilizando alojamiento compartido o similar, es posible que no tenga suerte.

remotehost.comes el nombre de tu host remoto. Podrías usar fácilmente su dirección IP. Solo para mayor claridad, estoy usando Gitosis en el host remoto con claves SSH, por lo que no se me solicitan contraseñas cuando presiono. El artículo Hosting Git Repositories, la manera fácil (y segura) le dice cómo configurar todo eso.

Korutech App Solutions
fuente
1

La mejor manera de hacer esto es:

mkdir ..../remote
cd ..../remote
git clone --bare .../currentrepo/

Esto clonará el repositorio, pero no hará ninguna copia de trabajo .../remote. Si observa el control remoto, verá un directorio creado, llamado currentrepo.git, que probablemente sea lo que desea.

Luego, desde su repositorio Git local:

git remote add remoterepo ..../remote/currentrepo.git

Después de realizar cambios, puede:

git push remoterepo master
Bill Donahue
fuente
1

Acabo de encontrarme con este problema con un repositorio git de implementación en Heroku .

No sé por qué Heroku tiene un repositorio no desnudo de su lado, pero como solución alternativa pude restablecer el repositorio remoto y volver a cargarlo.

No debe usar la copia de Heroku de su repositorio como su único repositorio git para colaboración, pero por si acaso, diré claramente: No haga esto a menos que esté seguro de tener una copia completa de su repositorio almacenada de forma segura en otro lugar que no sea Heroku Hacer un reinicio eliminará el contenido del repositorio.

Reiniciar:

  1. Instale el cinturón de herramientas Heroku (que contiene el cliente de línea de comando) si aún no lo ha hecho.
  2. Instala el complemento heroku-repo si aún no lo has hecho.

    heroku plugins:install https://github.com/heroku/heroku-repo.git
    
  3. Realice el reinicio, que elimina el repositorio y crea uno nuevo y vacío

    heroku repo:reset
    
  4. Empuje a su control remoto Heroku como lo haría normalmente; volverá a cargar todo.

rakslice
fuente
Es posible que deba instalar las herramientas de repositorio de Heroku para que esto funcione. Hacerheroku plugins:install https://github.com/heroku/heroku-repo.git
Noah
1

Deberá cambiar el archivo de configuración en el servidor remoto una vez que haya creado un repositorio vacío (desnudo), digamos

root@development:/home/git/repository/my-project# cat config 

ahi veras

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true

Harás esto desnudo a falso a verdadero y eliminé logallrefupdates = true (¡no estoy seguro de su uso!)

a

[core]
repositoryformatversion = 0
filemode = true
bare = true

Puedes probar siguiendo

$ git remote show origin
* remote origin
Fetch URL: my-portal@development:/home/XYZ/repository/XYZ
Push  URL: my-portal@development:/home/XYZ/repository/XYZ
HEAD branch: (unknown)

Esta rama HEAD: (desconocida) se mostrará si no puede EMPUJAR. Por lo tanto, si la rama HEAD no se conoce, debe cambiar de desnudo a verdadero y después de presionar con éxito puede reutilizar el

git remote show origin

y tu verás

 HEAD branch: master
vimal krishna
fuente
0

Para mí la solución de trabajo es:

EN REMOTO:

git checkout -b some_tmp_name

EN LOCAL:

git push

EN REMOTO:

git checkout master
git branch -d some_tmp_name

Pero esta no es la solución real, es solo una solución.

jmarceli
fuente
Esta es una solución válida si no tiene un repositorio central.
Rick
0

Por si alguien lo encuentra útil. Para mí fue un problema de permisos del servidor git. Revisé el proyecto desde el principio y empujé un archivo simple y luego recibí el mensaje "Push rechazado: Push to origin / master fue rechazado"

PbxMan
fuente
-1

Con Git, dos repositorios regulares (no desnudos) no pueden empujar / extraer archivos directamente de un lado a otro. Debe haber un repositorio desnudo intermediario. Aparentemente, es como una pareja casada que tiene un hijo, y la pareja se está divorciando. Los padres no se hablarán entre sí, pero se comunicarán a través del niño.

Entonces, tiene un repositorio, clona este repositorio en un repositorio desnudo y luego lo clona en un tercero. El primero y el tercero pueden intercambiar información a través del segundo repositorio, el simple. Supongo que esto tiene sentido, ya que no querrás que alguien pueda registrar cosas en tu repositorio sin tu consentimiento, ya que eso podría causar conflictos de fusión y cosas por el estilo.

Entonces, aquí hay un ejemplo:

En PC, en ~ / workspace

git init
echo "line 1" > afile.txt
git add .
git commit -m ‘initial import’
git clone --bare . ../remote-repository.git
git remote add origin ../remote-repository.git
git push --set-upstream origin master

En la computadora portátil, en ~ / espacio de trabajo (no haga git init, etc.)

git clone //LJZ-DELLPC/remote-repository.git/ .

// Luego realiza varios commits y empuja:

echo "line 2" > afile.txt
git add afile.txt
git commit -m 'added line 2'
git push    

Luego de vuelta en la PC, en ~ / workspace

git pull

// Luego realiza varios commits y empuja:

git push

En la computadora portátil git pull

Etcétera..

Aquí hay un ejemplo concreto absoluto en una sola máquina, copiado directamente de la ventana de comandos, para que sepamos que no se omitieron pasos, que realmente funcionó, etc.

lylez@LJZ-DELLPC ~
$ cd gitdir
/home/lylez/gitdir

lylez@LJZ-DELLPC ~/gitdir
$ ls

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1
/home/lylez/gitdir/repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git init
Initialized empty Git repository in /home/lylez/gitdir/repo1/.git/

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 1" > afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'initial import'
[master (root-commit) f407e12] initial import
 1 file changed, 1 insertion(+)
 create mode 100644 afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git clone --bar . ../repo1-bare-clone
Cloning into bare repository '../repo1-bare-clone'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git remote add origin ../repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push --set-upstream origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ..

lylez@LJZ-DELLPC ~/gitdir
$ ls
repo1  repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1-remote

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1-remote
/home/lylez/gitdir/repo1-remote

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git clone ../repo1-bare-clone .
Cloning into '.'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ echo "line 2" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git commit -m 'added line 2'
[master 5ad31e0] added line 2
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 260 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   f407e12..5ad31e0  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cd ../repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../repo1-bare-clone
   f407e12..5ad31e0  master     -> origin/master
Updating f407e12..5ad31e0
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 3" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'added line 3'
[master 3fa569e] added line 3
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 265 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ../repo1-bare-clone
   5ad31e0..3fa569e  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ../repo1-remote/

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   5ad31e0..3fa569e  master     -> origin/master
Updating 5ad31e0..3fa569e
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2
line 3

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git --version
git version 2.1.1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
Lyle Z
fuente
Es un ejemplo de lo que funciona y una explicación de por qué. No hay ninguna información errónea aquí, excepto por su comentario.
Lyle Z
1
"Con Git, dos repositorios regulares (no desnudos) no pueden empujar / extraer archivos directamente de un lado a otro", excepto que sí pueden.
Andrew C
Bien, publique un ejemplo concreto en lugar de un ataque.
Lyle Z
¿O podrías googlearlo? stackoverflow.com/questions/1764380/…
Andrew C
La primera respuesta en el hilo que su sitio comienza con, "... pero de acuerdo con git ready y el wiki oficial de git, solo debe empujar a un repositorio desnudo". La siguiente respuesta dice: "Si quieres probar simplemente presionando master -> master, entonces el comando es solo: git push origin", y eso simplemente no funciona, y hay un millón de publicaciones a ese efecto. La última respuesta comienza con: "Sugeriría tener un repositorio desnudo y un repositorio local de trabajo (no desnudo) en su servidor", que es exactamente lo que propuse.
Lyle Z
-3

Mi solución (en uso)

  1. Pago "maestro" en el servidor remoto
  2. Trabajar localmente en la rama "dev"
  3. Empuje cambios a desarrollo remoto
  4. Fusionar dev en master en remoto

bingo

decibelios.
fuente