Errore push git '[telecomando rifiutato] master -> master (il ramo è attualmente estratto)'


961

Ieri ho pubblicato una domanda su come clonare un repository Git da una delle mie macchine a un'altra, Come posso "clonare Git " da un'altra macchina? .

Ora sono in grado di clonare con successo un repository Git dalla mia fonte (192.168.1.2) alla mia destinazione (192.168.1.1).

Ma quando ho apportato una modifica a un file, a git commit -a -m "test"e a git push, ricevo questo errore sulla mia destinazione (192.168.1.1):

git push                                                
hap@192.168.1.2'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://hap@192.168.1.2/media/LINUXDATA/working
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'git+ssh://hap@192.168.1.2/media/LINUXDATA/working'

Sto usando due diverse versioni di Git (1.7 sul telecomando e 1.5 sul computer locale). È una possibile ragione?


5
Qualcuno può cambiare la risposta accettata a stackoverflow.com/a/9283833/397872 e spostare il thread in archivio o qualcosa del genere? O cambiare proprietà o altro?
rishta,

9
In realtà ora avete un modo sicuro per spingere ad un repo non nudo con Git 2.3.0 (febbraio 2015) e git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309
VonC

Questo è il nuovo link del libro che @stigi ha menzionato: git-scm.com/book/en/v1/Git-on-the-Server
Abdelilah El Aissaoui,


Ma non capisco perché e come funziona? Funziona, sì, ma questo è tutto.
Tilak Maddy,

Risposte:


1149

Puoi semplicemente convertire il tuo repository remoto in un repository nudo (non esiste una copia funzionante nel repository nudo - la cartella contiene solo i dati del repository reale).

Eseguire il comando seguente nella cartella del repository remoto:

git config --bool core.bare true

Quindi eliminare tutti i file tranne .gitin quella cartella. E poi sarai in grado di eseguire git pushsul repository remoto senza errori.


4
Grazie. Ne avevo anche bisogno. Stavo seguendo il tutorial sui sottomoduli del Git Community Book e ho raggiunto questo blocco.
Shiki,

6
Non ero sicuro che avessi intenzione di eliminare i file sul server o sul client ... quindi non ho eliminato nulla e il problema scompare solo dopo averlo fatto git config --bool core.bare true. C'è qualche motivo particolare per cui alcuni file devono essere eliminati? In tal caso, puoi essere più preciso su ciò che deve essere eliminato?
Brian Vandenberg,

24
È la migliore risposta possibile e nessun altro l'ha fornita nella buca Interwebs. Penso che tutti noi abbiamo cercato su Google lo stesso messaggio di errore e siamo stati estremamente felici di leggere questo.
Sebastián Grignoli,

40
Sebbene abbia ottenuto molti voti, non credo che questa sia una risposta davvero adeguata a quella domanda specifica. Spiegare all'utente come creare in modo pulito un repository nudo sarebbe dimezzato, ma cosa succede se i file devono rimanere estratti, ad esempio quando si tratta del repository con cui l'utente sta lavorando su due computer?
nessun luogo, uomo,

9
La modifica del repository di origine in bare è eccessiva. Tutto quello che devi fare è spinta ad un nuovo ramo nel repository di origine, come sottolinea @ Robert: stackoverflow.com/a/2933656/402949 .
Dan Solovay,

708

Ho appena avuto lo stesso errore mentre ho iniziato a studiare Git . Alcune delle altre risposte non sono chiaramente per qualcuno che non conosce Git!

(Userò termini non tecnici per far passare l'idea.) Comunque, quello che sta succedendo è che hai due repository, uno è il primo che hai realizzato e l'altro quello che hai appena realizzato.

In questo momento sei nel tuo repository di lavoro e stai usando il ramo "master". Ma ti capita anche di essere "loggato" nel tuo repository originale allo stesso ramo "master". Ora, dato che sei "loggato" nell'originale, Git teme che potresti sbagliare perché potresti lavorare sull'originale e rovinare tutto. Quindi è necessario tornare al repository originale e fare un "git checkout someotherbranch", e ora puoi spingere senza problemi.

Spero che questo possa essere d'aiuto.


76
+1 Molto più utile, grazie Robert. Non aveva senso convertirmi in un repository nudo nel mio caso. Devi semplicemente "disattivare" il ramo in cui stai tentando di spingere. Ha senso.
Eric Muyser,

32
@ FMaz008: basta creare un ramo fittizio (checkout git -b fittizio)
Dror Cohen,

14
Amico, questo è molto meglio della risposta più votata :) Grazie. Anche se l'altra risposta ha un buon punto anche :)
Ivan Ivanić,

103
Proprio per rendere più chiara, nel repository che è l'obiettivo della spinta: git checkout -b tmp. Poi nella sorgente di pronti contro termine: git push. Poi di nuovo nel bersaglio (opzionale):git checkout master; git branch -d tmp
Hari Karam Singh,

18
Il commento di Hari è la ricetta più semplice. Devo solo dire che mentre git può essere fantastico in molti modi, proveniente da svn o probabilmente da qualsiasi altro camper, tutta questa cosa è incredibilmente non intuitiva.
Incondizionatamente

128

Il messaggio di errore descrive cosa è successo. Le versioni più moderne di Git si rifiutano di aggiornare un ramo tramite push se quel ramo viene estratto.

Il modo più semplice per lavorare tra due repository non nudi è o

  1. aggiorna sempre i repository tramite pull (o recupera e unisci) o, se necessario,

  2. spingendo verso un ramo separato (un ramo di importazione) e quindi unendo quel ramo nel ramo principale sul computer remoto.

Il motivo di questa limitazione è che l'operazione push funziona solo sul repository Git remoto, non ha accesso all'indice e all'albero di lavoro. Quindi, se consentito, una spinta sul ramo di check-out cambierebbe HEAD in incoerente con l'indice e l'albero di lavoro sul repository remoto.

Ciò renderebbe molto semplice il commit accidentale di una modifica che annulla tutte le modifiche inviate e rende anche molto difficile distinguere tra eventuali modifiche locali che non sono state impegnate e differenze tra il nuovo HEAD, l'indice e l'albero di lavoro che sono state causato dalla spinta in movimento HEAD.


1
Grazie. Quindi, come posso risolvere il mio problema? Nella mia casella 192, ho fatto '$ cd (directory-progetto) $ git init $ (aggiungi alcuni file) $ git add.' e poi nella mia casella 191, ho fatto un 'clone git' e ho modificato alcuni file e poi ho provato a 'git push'.
hap497,

16
Bene, ho descritto le possibilità nella mia risposta. O puoi andare alla casella 192 e recuperare dalla casella 191 (potresti voler aggiungere la casella 191 come telecomando con nome - guarda git remote add box191 <191url>), oppure puoi spingere dalla casella 191 a un ramo con nome alternativo (ad esempio git push origin master:refs/heads/upload), quindi nella casella 192 e unisci (ad esempio git merge upload).
CB Bailey,

3
In realtà ora hai un modo sicuro per passare a un repository non nudo con Git 2.3.0 (febbraio 2015) e git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309 : non hai più bisogno dell'opzione 2.
VonC

122

Sommario

Non è possibile eseguire il push su un ramo estratto di un repository perché rovinerebbe l'utente di quel repository in un modo che molto probabilmente finirà con la perdita di dati e cronologia . Ma puoi spingere in qualsiasi altro ramo dello stesso repository.

Dato che i repository nudi non hanno mai verificato alcun ramo, è sempre possibile eseguire il push in qualsiasi ramo di un repository nudo.

Esistono più soluzioni, a seconda delle tue esigenze.

Soluzione 1: utilizzare un repository nudo

Come suggerito, se su una macchina non è necessaria la directory di lavoro, è possibile passare a un repository nudo. Per evitare di scherzare con il repository, puoi semplicemente clonarlo:

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

Ora puoi inviare tutto ciò che vuoi allo stesso indirizzo di prima.

Soluzione 2: spingete verso un ramo non estratto

Ma se devi controllare il codice sul tuo telecomando <remote>, puoi usare un ramo speciale per spingere. Diciamo che nel tuo repository locale hai chiamato il tuo telecomando origine sei sul branch master. Allora potresti fare

machine2$ git push origin master:master+machine2

Quindi è necessario unirlo quando ci si trova nel originrepository remoto:

machine1$ git merge master+machine2

Autopsia del problema

Quando un ramo viene estratto, il commit aggiungerà un nuovo commit con la testa del ramo corrente come suo genitore e sposta la testa del ramo in quel nuovo commit.

Così

A ← B
    ↑
[HEAD,branch1]

diventa

A ← B ← C
        ↑
    [HEAD,branch1]

Ma se qualcuno potesse spingere verso quel ramo tra di loro, l'utente si metterebbe in quella che git chiama modalità testa staccata :

A ← B ← X
    ↑   ↑
[HEAD] [branch1]

Ora l'utente non è più in branch1, senza aver esplicitamente chiesto di estrarre un altro branch. Peggio ancora, l'utente è ora fuori da qualsiasi ramo e ogni nuovo commit sarà semplicemente sospeso :

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

Ipoteticamente, se a questo punto, l'utente verifica un altro ramo, questo commit penzolante diventa un gioco leale per il garbage collector di Git .


3
Una correzione tecnica all '"autopsia": git in realtà non si staccherà HEADnel repository push-to. HEADindicherà comunque il ramo e il ramo a sua volta indicherà i nuovi commit inviati; ma la directory di lavoro e l'area di indice / staging non saranno modificate. Chiunque stia lavorando al repository push-to ora deve lavorare sodo per riprendersi dagli effetti della push: capire se ci sono cambiamenti da salvare, e se così organizzare con cura per salvarli.
torek,

Per aggiungere ulteriori informazioni alla tua risposta, ci sono pochissime ragioni per cui vorresti un repository remoto che le persone spingono per essere non nude, quindi usare un repository nudo è la soluzione migliore.

2
In realtà, ho trovato molte situazioni in cui ho bisogno di passare a un repository non nudo e uso parecchio la soluzione 2. Inoltre, il ramo in cui spingo sul repository non nudo non è in alcun modo un ramo temporaneo, ha uno scopo simile a un ramo di tracciamento remoto.
Nessun uomo,

Ho creato una cartella GIT sul mio server che ospiterà TUTTI i repository creati da più utenti utilizzando SourceTree. Ho creato un masterrepository nel mio PC locale. Ho aggiunto il remotesalla cartella del server e ho provato a inserire il mio repository nel server in modo che un altro utente possa estrarlo / recuperarlo su cui lavorare. Viene visualizzato il seguente errore: ! [remote rejected] master -> master (branch is currently checked out)Come posso registrarlo?
SearchForKnowledge

1
@SearchForKnowledge, ti rendi conto che stai facendo esattamente la domanda a cui sto rispondendo ?!
nessun posto, uomo,

65

È possibile aggirare questa "limitazione" modificando .git/configsul server di destinazione. Aggiungere quanto segue per consentire il push di un repository git anche se è "estratto":

[receive]
denyCurrentBranch = warn

o

[receive]
denyCurrentBranch = false

Il primo consentirà la spinta mentre avverte della possibilità di confondere il ramo, mentre il secondo lo consentirà semplicemente in silenzio.

Questo può essere usato per "distribuire" il codice su un server che non è pensato per essere modificato. Questo non è l'approccio migliore, ma rapido per la distribuzione del codice.


7
Usarlo per "distribuire" il codice su un server non funzionerà. Anche se si disabilita l'avviso in modo da poter eseguire il push nel ramo estratto, la copia di lavoro non viene MAI aggiornata su un push.
Arrowmaster

10
Sto usando il metodo sopra con cd .. && git reset --hardhook post-ricezione da distribuire. Hackish, ma funziona.
Jholster,

9
la versione da riga di comando di quest'ultima sarebbegit config receive.denyCurrentBranch warn
Andre Holzner,

4
Questa dovrebbe essere la risposta accettata. Alcuni di noi sanno cosa stiamo facendo e non sono principianti di Git. Questa è la risposta per quelle persone.
Qix - MONICA È STATA MISTREATA il

2
Ah, ma la domanda non è stata posta da quelle persone.
Nessun uomo,

46

git config --local receive.denyCurrentBranch updateInstead

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

Usalo sul repository del server e aggiorna anche l'albero di lavoro se non si verifica una sovrascrittura non tracciata.

È stato aggiunto in Git 2.3 come menzionato da VonC nei commenti.

Ho compilato Git 2.3 e l'ho provato. Esempio di utilizzo:

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

Produzione:

a
b

Yay, bsono stato spinto!


@VonC grazie! È la mia ossessione per gli esempi minimi al lavoro :-)
Ciro Santilli 12 冠状 病 六四 事件 法轮功

Ci sono problemi con il commit di modifiche che non sono aggiornate con il server?
akozi,

@akozi Non sono sicuro di cosa intendi, se ti impegni localmente prima di tirare, si comporterà esattamente come un --bareclone tradizionale penso: --forceè necessario spingere, e ti farà "perdere" commit sul telecomando.
Ciro Santilli 24 冠状 病 六四 事件 法轮功

1
@CiroSantilli 新疆 改造 中心 六四 事件 法轮功 Nessun problema ora. Ho cercato il significato delle opzioni. Ho pensato che updateInstead fosse sinonimo di forza.
akozi,

updateInstead non è più un valore valido per
receive.denyCurrentBranch

41

Mi piace l'idea di avere ancora un repository utilizzabile sulla casella remota, ma invece di un ramo fittizio, mi piace usare:

git checkout --detach

Questa sembra essere una novità di Git : sto usando la versione 1.7.7.4 di git.


8
E poi, dopo aver inviato le modifiche, puoi usare: git checkout masterper tornare al ramo principale. Solo allora vengono applicate le modifiche.
MAZDAK,

30

Ho avuto lo stesso problema. Per me, utilizzo Git push per spostare il codice sui miei server. Non cambio mai il codice sul lato server, quindi è sicuro.

Nel repository, stai spingendo per digitare:

git config receive.denyCurrentBranch ignore

Ciò ti consentirà di modificare il repository mentre è una copia funzionante.

Dopo aver eseguito un push Git, vai al computer remoto e digita questo:

git checkout -f

Ciò renderà le modifiche che hai premuto verranno riflesse nella copia di lavoro della macchina remota.

Si noti che ciò non è sempre sicuro se si apportano modifiche alla copia di lavoro a cui si sta spingendo.


grazie un log, mi si uniscono suggerimento denyCurrentBranche metto git checkout -fdentro hooksla cartella come @ jack-Senechal postato qui
Ederson T. Szlachta

C'è un modo per far apparire i file sul repository remoto senza accedervi e fare questo comando? Vale a dire da un comando dal locale?
Royi

24

È possibile ricreare il repository del server e passare dal master della filiale locale al master del server.

Sul tuo server remoto:

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

OK, dalla tua filiale locale:

git push origin master:master

3
Grazie, questa è stata la soluzione per me poiché avevo omesso '--bare' sul server remoto. Sembra che le risposte a questa domanda dipendano dal fatto che si stia utilizzando o meno il repository del server remoto come directory di lavoro e per il caso successivo questa è la risposta corretta.
Caso

2
Non capisco: SI ha provato a creare e clonare un repository nudo, ma il clone non ha scaricato nulla e non ha caricato nulla caricato, quindi questo non funziona ... :-) Ho letto tutorial sui repository nudi, ma dicono che un repository nudo non contiene file ... Non è sicuramente quello che sto cercando ...
inf3rno

22

Cosa probabilmente hai fatto per causare questo:

Questo genere di cose succede quando vai a sbattere fuori un piccolo programma. Stai per cambiare qualcosa che stava già funzionando, quindi lanci il tuo incantesimo di livello 3 di perenne annullabilità:

machine1:~/proj1> git init

e inizi ad aggiungere / impegnare. Ma poi , il progetto inizia a essere più coinvolto e vuoi lavorarci da un altro computer (come il tuo PC o laptop di casa), quindi fai qualcosa di simile

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

e clona e tutto sembra a posto, quindi lavori sul tuo codice da machine2.

Quindi ... provi a inviare i tuoi commit da machine2 e ricevi il messaggio di avviso nel titolo.

Il motivo di questo messaggio è dovuto al fatto che il repository git da cui è stato estratto era in qualche modo destinato a essere utilizzato solo per quella cartella su machine1. Puoi clonarlo bene, ma spingere può causare problemi. Il modo "corretto" di gestire il codice in due posizioni diverse è con un repository "nudo", come è stato suggerito. Un repository nudo non è progettato per essere svolto in esso, ma intende coordinare i commit da più fonti. Questo è il motivo per cui la risposta più votata suggerisce di eliminare tutti i file / cartelle diversi dalla cartella .git dopo di te git config --bool core.bare true.

Chiarire la risposta più votata: molti dei commenti a quella risposta dicono qualcosa del tipo "Non ho cancellato i file non .git dalla macchina1 ed ero ancora in grado di eseguire il commit dalla macchina2". Giusto. Tuttavia, questi altri file sono completamente "divorziati" dal repository git, ora. Vai a provare git statuslì e dovresti vedere qualcosa di simile a "fatale: questa operazione deve essere eseguita in un albero di lavoro". Pertanto, il suggerimento di eliminare i file non è in modo che il commit da machine2 funzioni ; è così che non ti confondi e pensi che git stia ancora monitorando quei file. Ma eliminare i file è un problema se vuoi ancora lavorare sui file su machine1, non è vero?

Quindi, cosa dovresti davvero fare?

Dipende da quanto pensi di lavorare ancora su machine1 e machine2 ...

Se hai finito di sviluppare da machine1 e hai spostato tutto il tuo sviluppo su machine2 ... fai solo quello che suggerisce la risposta più votata: git config --bool core.bare truee, facoltativamente, elimina tutti i file / cartelle diversi da .git da quella cartella, poiché non sono tracciati e possono causare confusione.

Se il tuo lavoro su machine2 era solo una volta e non hai bisogno di continuare lo sviluppo lì ... allora non preoccuparti di fare un repository nudo; solo ftp / rsync / scp / etc. i file dalla macchina * 2 * sopra i file sulla macchina * 1 *, esegui il commit / push dalla macchina * 1 *, quindi elimina i file dalla macchina * 2 *. Altri hanno suggerito di creare un ramo, ma penso che sia un po 'disordinato se vuoi solo unire lo sviluppo che hai fatto su una volta da un'altra macchina.

Se hai bisogno di continuare lo sviluppo su machine1 e machine2 ... allora devi impostare le cose correttamente. Devi convertire il tuo repository in un nudo, quindi devi crearne uno clone su machine1 per poter lavorare . Probabilmente il modo più veloce per farlo è fare

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

Molto importante: poiché hai spostato la posizione del repository da proj1 a proj1.git, devi aggiornarlo nel file .git / config su machine2 . Successivamente, puoi eseguire il commit delle modifiche da machine2. Infine, provo a mantenere i miei repository nudi in una posizione centrale, lontano dai miei alberi di lavoro (cioè non metto "proj1.git" nella stessa cartella principale di "proj1"). Ti consiglio di fare lo stesso, ma volevo mantenere i passaggi precedenti il ​​più semplice possibile.


Molto dettagliato e utile. Il mio caso è stato l'ultimo e le tue istruzioni hanno funzionato come un incantesimo.
Pojda,

Sono nel caso 3 e ho fatto qualcosa di leggermente diverso: mk git-server; mv .git git-server / proj.git e poi git clona git-server / proj.git su 1 e 2 (o git remote origin ...), usando un prefisso ssh: // corretto per la macchina 2. In questo modo Terrò una copia master nuda che sarà come quella normalmente su GH o altri server HTTP e continuerò a usare push / pull su entrambe le macchine.
zakmck,

18

Con alcuni passaggi di configurazione puoi facilmente implementare le modifiche al tuo sito Web utilizzando un one-liner come

git push production

Che è bello e semplice, e non è necessario accedere al server remoto e fare un pull o altro. Nota che funzionerà meglio se non usi il tuo checkout di produzione come ramo funzionante! (L'OP funzionava in un contesto leggermente diverso e penso che la soluzione di @Robert Gould lo abbia affrontato bene. Questa soluzione è più appropriata per la distribuzione su un server remoto.)

Per prima cosa devi impostare un repository nudo da qualche parte sul tuo server, al di fuori del tuo root web.

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

Quindi crea il file hooks/post-receive:

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

E rendere eseguibile il file:

chmod +x hooks/post-receive

Sul tuo computer locale,

git remote add production git@myserver.com:mywebsite.git
git push production +master:refs/heads/master

Tutto stabilito! Ora in futuro puoi utilizzare git push productionper distribuire le tue modifiche!

Il merito di questa soluzione va a http://sebduggan.com/blog/deploy-your-website-changes-using-git/ . Guarda lì per una spiegazione più dettagliata di ciò che sta succedendo.


Il tuo suggerimento mi ha aiutato molto, ma non ho usato bare, seguo questo e si fondono con hooks(che avete suggerito) e funzionava perfettamente.
Éderson T. Szlachta,

11

Dovresti solo spingere verso un repository nudo. Un repository nudo è un repository che non ha rami estratti. Se dovessi eseguire il cd in una directory di repository vuota, vedresti solo i contenuti di una directory .git.


9
Non c'è niente di sbagliato nel spingere verso un ramo non estratto in un repository non nudo. Questo è un modo di lavorare perfettamente valido.
CB Bailey,

Abbastanza giusto, funzionerebbe. Ma non è quello che sta facendo l'utente.
RibaldEddie,

13
Non è il fatto che non stia usando un repository nudo che è "sbagliato"; è il fatto che sta spingendo verso un ramo verificato. Non ci sono prove che abbia o voglia un repository nudo separato, quindi la tua affermazione generale che dovrebbe solo spingere in un repository non nudo non sta dando al richiedente tutte le opzioni; uno dei quali potrebbe risolvere più facilmente il suo problema immediato.
CB Bailey,

10

Hai 3 opzioni

  1. Tirare e spingere di nuovo:

    git pull; git push
    
  2. Inserire in un altro ramo:

    git push origin master:foo
    

    e uniscilo sul telecomando (tramite gito pull-request )

    git merge foo
    
  3. Forzalo (non raccomandato a meno che tu non abbia deliberatamente modificato i commit tramite rebase):

    git push origin master -f
    

    Se ancora rifiutato, disabilitare denyCurrentBranch sul repository remoto:

    git config receive.denyCurrentBranch ignore
    

L'opzione 2 funziona per me. remote git init local git push origin master: branch remote git merge DONE
Jacky Chong

7

In effetti, impostare il telecomando su un ramo non estratto è sufficiente. Dopo aver verificato il telecomando in un altro ramo, è possibile spingere.


7

Controlla il tuo .git/confignel progetto di destinazione:

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

Se il valore core. bareè falso, puoi impostarlo su true:

$ git config core.bare true

e quindi nella tua spinta locale verso il telecomando:

git push remote_repo   // suppose the destination repo is remote_repo

avrà successo, in remote_repo puoi controllare la versione di git.

$ git log -1
commit 0623b1b900ef7331b9184722a5381bbdd2d935ba
Author: aircraft < aircraft_xxx@126.com>
Date:   Thu May 17 21:54:37 2018 +0800

e ora non puoi usare git nel tuo "spazio di lavoro":

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

dovresti bare.baretornare a false.

$ git config core.bare false

5

Ho avuto lo stesso problema usando Git per sincronizzare i repository sul mio telefono e laptop Android. La soluzione per me era fare una spinta invece di una spinta, come suggerito da @CharlesBailey.

git push origin master sul repository Android non riesce per me con gli stessi messaggi di errore che @ hap497 ha ricevuto a causa di una spinta a un checkout non banale di un repository + working-copy.

git pull droid mastersul repository laptop e working-copy funziona per me. Ovviamente, devi aver eseguito in precedenza qualcosa del genere git remote add droid /media/KINGSTON4GB/notes_repo/.


4

Le versioni precedenti di Git erano utilizzate per consentire push al ramo attualmente estratto di un repository non bare.

Si scopre che questa era una cosa terribilmente confusa da permettere. Quindi hanno aggiunto il messaggio di avviso che vedi, che è anche terribilmente confuso.

Se il primo repository funge solo da server, convertilo in un repository nudo come raccomandato dalle altre risposte ed eseguilo.

Se tuttavia è necessario disporre di un ramo condiviso tra due repository che sono entrambi in uso, è possibile ottenerlo con la seguente configurazione

Repo1: fungerà da server e verrà utilizzato anche per lo sviluppo

Repo2 - sarà solo per lo sviluppo

Configurare Repo1 come segue

Crea un ramo su cui condividere il lavoro.

git branch shared_branch

Per sicurezza, dovresti anche creare un $ (REPO) .git / hooks / update che rifiuta qualsiasi modifica diversa da shared_branch, perché non vuoi che le persone si confondano con le tue filiali private.

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

Ora crea una filiale locale in repo1 dove eseguirai il tuo vero lavoro.

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'

(potrebbe essere necessario git config --global push.default upstreamper git pushfunzionare)

Ora puoi creare repo2 con

git clone path/to/repo1 repo2 
git checkout shared_branch 

A questo punto hai sia repo1 che repo2 setup per lavorare su rami locali che fanno push e pull da shared_branchin repo1, senza preoccuparti di quel messaggio di errore o avere la directory di lavoro fuori sincronia in repo1. Qualunque sia il normale flusso di lavoro che usi, dovrebbe funzionare.


3

OK, nel caso in cui si desideri un normale repository remoto, quindi creare un ramo aggiuntivo e verificarlo. Spingilo in un ramo (che non è stato estratto) e uniscilo con uno che è attualmente attivo in seguito dopo aver spinto da localmente.

Ad esempio, su un server remoto:

git branch dev
git checkout dev

Sull'installazione locale:

git push 

Sul server remoto:

git merge dev

2

Ecco un test che puoi fare per vedere come funzionano le barecose del server:

Immagina di avere una workstation e un server con un sito live ospitato su di esso e di voler aggiornare questo sito di volta in volta (questo vale anche per una situazione in cui due sviluppatori inviano il loro lavoro avanti e indietro attraverso un intermediario nudo).

Inizializzazione

Crea una directory sul tuo computer locale e cdal suo interno, quindi esegui questi comandi:

# initialization
git init --bare server/.git
git clone server content
git clone server local
  1. Per prima cosa crei una serverdirectory vuota (nota il .git alla fine). Questa directory fungerà da contenitore solo per i file del repository.
  2. Quindi clonare il repository del server in una contentdirectory appena creata . Questa è la tua directory live / di produzione che sarà servita dal tuo software server.
  3. Le prime due directory risiedono sul tuo server, la terza è una directory locale sulla tua workstation.

Flusso di lavoro

Ora ecco il flusso di lavoro di base:

  1. Immettere la localdirectory, creare alcuni file e impegnarli. Infine spingerli sul server:

    # create crazy stuff
    git commit -av
    git push origin master
    
  2. Ora inserisci la contentdirectory e aggiorna il contenuto del server:

    git pull
    
  3. Ripeti 1-2. Qui contentpotrebbe esserci un altro sviluppatore che può anche spingere sul server e localcome puoi estrarre da lui.


2

Usarlo per inviarlo al ramo remoto a monte ha risolto questo problema per me:

git push <remote> master:origin/master

Il telecomando non aveva accesso al repository upstream, quindi questo era un buon modo per ottenere le ultime modifiche in quel telecomando


1
Più in generale (poiché questo è l'effetto netto del comando), usando git push <remote> master:newbranch. L'idea è di inviare un nuovo ramo al telecomando, che può quindi essere unito. In questo modo si evitano i problemi di incoerenza menzionati nel messaggio di errore.
Clay,

1

Ho dovuto ripetere l'esecuzione git --initin un repository nudo esistente, e questo aveva creato una .gitdirectory all'interno dell'albero del repository nudo - mi sono reso conto che dopo averlo digitato git statuslì. L'ho cancellato e tutto è andato di nuovo bene :)

(Tutte queste risposte sono fantastiche, ma nel mio caso è stato qualcosa di completamente diverso (per quanto posso vedere), come descritto.)


1

Sono sicuro che molte persone che visualizzano questa domanda si fermeranno alle prime due enormi risposte, ma mi piacerebbe comunque offrire la mia soluzione.

Ho riscontrato una configurazione del progetto Web Eclipse + EGit quando ho riscontrato l'errore descritto. Ciò che mi ha aiutato è stato semplicemente l'utilizzo dell'app GitHub, che sembrava risolvere magicamente il problema. Mentre EGit rifiuta sempre la spinta, l'app desktop GitHub si stringe nelle spalle e spinge le mie modifiche. Forse gestisce la situazione multi-login con più grazia.


1

Un articolo che ho trovato utile per gli altri è Git in 5 minuti .

Avevo un progetto Xcode sotto il controllo della versione di Git che volevo trasferire su una Virtual Distributed Ethernet (VDE) che ho in un controller di dominio . VDE esegue Centos 5.

Nessuno degli articoli che ho letto su Git parlava di repository nudi. Sembrava tutto così semplice fino a quando ho provato quello che pensavo potesse essere facile provenire da uno sfondo SVN .

I suggerimenti qui per rendere il repository remoto completamente funzionante. Ancora meglio per le mie esigenze era clonare il progetto Xcode projectname.git, copiarlo sul server remoto; quindi spinge magicamente lavorato. Il prossimo passo sarà far sì che Xcode esegua il push senza errori di commit, ma per ora sto bene eseguendolo dal Terminale.

Così:

cd /tmp (or another other directory on your system)<br/>
git clone --bare /xcode-project-directory projectname.git<br/>
scp -r projectname.git sshusername@remotehost.com:repos/<br/>

Per inviare le modifiche dal tuo progetto Xcode dopo aver eseguito il commit in Xcode:

cd /xcode-project-directory<br/>
git push sshusername@remotehost.com:repos/projectname.git<br/>

Sono certo che esiste un modo più semplice e sofisticato di fare quanto sopra, ma almeno funziona. Solo così tutto è chiaro, ecco alcuni chiarimenti: /xcode-project-directoryè la directory in cui è archiviato il tuo progetto xcode. Probabilmente /Users/Your_Name/Documents/Project_Name. projectname è letteralmente il nome del progetto, ma può essere qualsiasi cosa ti interessi chiamarlo. A Git non importa, lo farai.

Per utilizzare scp è necessario disporre di un account utente sul server remoto a cui sia consentito l' accesso SSH . Chiunque esegua il proprio server avrà questo. Se stai utilizzando hosting condiviso o simili, potresti essere sfortunato.

remotehost.comè il nome del tuo host remoto. È possibile utilizzare facilmente il suo indirizzo IP. Solo per maggiore chiarezza sto usando Gitosis sull'host remoto con le chiavi SSH, quindi non mi viene richiesta la password quando premo. L'articolo Hosting Git Repositories, The Easy (and Secure) Way ti spiega come impostare tutto ciò.


1

Il modo migliore per farlo è:

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

Questo clonerà il repository, ma non farà alcuna copia funzionante .../remote. Se guardi il telecomando, vedrai una directory creata, chiamata currentrepo.git, che è probabilmente quello che vuoi.

Quindi dal tuo repository Git locale:

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

Dopo aver apportato le modifiche, è possibile:

git push remoterepo master

1

Ho appena riscontrato questo problema con un repository git di distribuzione su Heroku .

Non so perché Heroku abbia un repository non nudo dalla loro parte, ma come soluzione alternativa sono stato in grado di ripristinare il repository remoto e ricaricare.

Non dovresti usare la copia di Heroku del tuo repository come unico repository git per la collaborazione, ma per ogni evenienza, dirò chiaramente: non farlo a meno che tu non sia sicuro di avere una copia completa del tuo repository archiviata in modo sicuro in un luogo diverso da Heroku. Effettuando un reset si cancellano i contenuti del repository.

Resettare:

  1. Installa la cintura degli strumenti Heroku (che contiene il client della riga di comando) se non l'hai già fatto.
  2. Installa il plug-in heroku-repo se non l'hai già fatto.

    heroku plugins:install https://github.com/heroku/heroku-repo.git
    
  3. Esegui il ripristino, che elimina il repository e ne crea uno nuovo e vuoto

    heroku repo:reset
    
  4. Premi sul tuo telecomando Heroku come faresti normalmente; ricaricherà tutto.


Potrebbe essere necessario installare gli strumenti di repository Heroku per farlo funzionare. Doheroku plugins:install https://github.com/heroku/heroku-repo.git
Noah,

1

Sarà necessario modificare il file di configurazione sul server remoto dopo aver creato un repository vuoto (vuoto), ad esempio

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

lì vedrai

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

Renderai questo da nudo a falso a vero e ho rimosso logallrefupdates = true (non sono sicuro del suo utilizzo!)

per

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

È possibile verificare di seguito

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

Questo ramo HEAD: (sconosciuto) verrà mostrato se non sei in grado di premere PUSH. Quindi, se il ramo HEAD è sconosciuto, dovresti passare da nudo a vero e dopo aver premuto con successo puoi riutilizzare il file

git remote show origin

e vedrai

 HEAD branch: master

0

Per me la soluzione di lavoro è:

SUL TELECOMANDO:

git checkout -b some_tmp_name

SUL LOCALE:

git push

SUL TELECOMANDO:

git checkout master
git branch -d some_tmp_name

Ma questa non è la vera soluzione, è solo una soluzione alternativa.


Questa è una soluzione valida se non si dispone di un repository centrale.
Rick,

0

Nel caso in cui qualcuno lo trovi utile. Per me è stato un problema con le autorizzazioni del server git. Ho controllato il progetto dall'inizio e ho inviato un semplice file e ho ottenuto "Push respinto: Push to origin / master rifiutato"


-1

Con Git, due repository regolari (non bare) non possono eseguire il push / pull dei file avanti e indietro direttamente. Ci deve essere un repository nudo intermediario. Apparentemente, è un po 'come una coppia sposata che ha un figlio e la coppia sta divorziando. I genitori non si parleranno, ma comunicheranno attraverso il bambino.

Quindi, hai un repository, cloni questo repository in un repository nudo e quindi lo cloni in un terzo. Il primo e il terzo possono scambiare informazioni tramite il secondo repository, quello nudo. Immagino che abbia un senso, dal momento che non vorresti che qualcuno fosse in grado di controllare le cose nel tuo repository senza il tuo consenso, in quanto ciò potrebbe causare unire conflitti e simili.

Quindi, ecco un esempio:

Su PC, in ~ / 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

Su laptop, in ~ / workspace (non eseguire git init, ecc.)

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

// Quindi effettua vari commit e spingili:

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

Quindi di nuovo su PC, in ~ / workspace

git pull

// Quindi effettua vari commit e spingili:

git push

Su laptop git pull

e così via..

Ecco un esempio assolutamente concreto tutto su una macchina, copiato direttamente dalla finestra di comando, in modo che sapremo che non sono stati esclusi passaggi, che ha funzionato davvero, ecc:

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

È un esempio di ciò che funziona e una spiegazione del perché. Non c'è alcuna disinformazione qui, a parte il tuo commento.
Lyle Z,

1
"Con Git, due repository regolari (non nudi) non possono spingere / estrarre i file direttamente e avanti" - Tranne che possono.
Andrew C

Bene, pubblica un esempio concreto invece di un attacco.
Lyle Z,

O potresti cercarlo su Google? stackoverflow.com/questions/1764380/...
Andrew C,

La prima risposta nel thread con il tuo sito inizia con "... ma secondo git ready e il wiki ufficiale di git, dovresti solo spingere verso un repository nudo". La prossima risposta afferma: "Se vuoi provare a spingere semplicemente master -> master, allora il comando è solo: git push origin", e semplicemente non funziona, e ci sono un milione di post su quell'effetto. L'ultima risposta inizia con "Suggerirei di avere un repository nudo e un repository di lavoro locale (non nudo) nel tuo server", che è esattamente ciò che ho proposto.
Lyle Z,

-3

La mia soluzione (in uso)

  1. Acquista "master" sul server remoto
  2. Lavora localmente sul ramo "dev"
  3. Invia le modifiche allo sviluppatore remoto
  4. Unisci dev in master sul telecomando

tombola

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.