Git push-fout ‘[extern afgewezen] master -> master (filiaal is momenteel uitgecheckt)’

Gisteren heb ik een vraag gepost over het klonen van een Git-repository van een van mijn machines naar een andere, Hoe kan Ik ‘git clone’ van een andere machine?.

Ik kan nu met succes een Git-repository klonen van mijn bron (192.168.1.2) naar mijn bestemming (192.168.1.1).

Maar toen ik een bewerking aan een bestand deed, een git commit -a -m "test"en een git push, krijg ik deze foutmelding op mijn bestemming ( 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'

Ik gebruik twee verschillende versies van Git (1.7 op de afstandsbediening en 1.5 op de lokale computer). Is dat een mogelijke reden?


Antwoord 1, autoriteit 100%

De foutmelding error: refusing to update checked out branch: refs/heads/masterbij te werken wordt uitgezonden door de remote repository en het betekent dat je code probeert te pushen naar een remote niet-bare repository die heeft momenteel een andere code uitgecheckt in de werkdirectory. De beste manier om dit probleem te vermijden, is door alleen naar bare repositories te pushen – dit probleem kan nooit optreden met een bare repository.

U kunt uw externe repository eenvoudig converteren naar bare repository (er is geen werkkopie in de bare repository – de map bevat alleen de daadwerkelijke repositorygegevens).

Voer de volgende opdracht uit in uw externe repository-map:

git config --bool core.bare true

Verwijder vervolgens alle bestanden behalve .gitin die map. En dan kun je zonder fouten git pushnaar de externe repository uitvoeren.


Antwoord 2, autoriteit 62%

Ik had net dezelfde fout toen ik Gitbegon te leren. Sommige van de andere antwoorden zijn duidelijk niet voor iemand die nieuw is bij Git!

Ik ga niet-technische termen gebruiken om het idee over te brengen. Hoe dan ook, wat er gebeurt, is dat je twee repositories hebt, de ene is het origineel dat je eerst hebt gemaakt en de andere het werk dat je zojuist hebt gemaakt.

Op dit moment ben je in je werkrepository en gebruik je de masterbranch. Maar je bent ook “ingelogd” in je originele repository op dezelfde masterbranch. Nu je bent “ingelogd” in het origineel, vreest Git dat je het verprutst omdat je misschien aan het origineel werkt en dingen verknoeit. Dus je moet terug naar de originele repository en git checkout someotherbranchdoen, en nu kun je zonder problemen pushen.


Antwoord 3, autoriteit 11%

De foutmelding beschrijft wat er is gebeurd. Modernere versies van Git weigeren een branch bij te werken via een push als die branch is uitgecheckt.

De gemakkelijkste manier om tussen twee niet-kale repositories te werken, is om

  1. werk de repositories altijd bij door te trekken (of op te halen en samen te voegen) of, als het moet,

  2. door naar een aparte branch (een import-branch) te pushen en die branch vervolgens samen te voegen met de master-branch op de externe machine.

De reden voor deze beperking is dat de push-bewerking alleen werkt op de externe Git-repository, het heeft geen toegang tot de index en de werkboom. Dus, indien toegestaan, zou een push op de uitgecheckte branch deHEADinconsequent maken met de index en de werkboom op de externe repository.

Dit zou het heel gemakkelijk maken om per ongeluk een wijziging door te voeren die alle gepushte wijzigingen ongedaan maakten het maakt het ook erg moeilijk om onderscheid te maken tussen lokale wijzigingen die niet zijn doorgevoerd en verschillen tussen de nieuwe HEAD, de index en de werkboom die zijn veroorzaakt door het pushen van HEAD.


Antwoord 4, autoriteit 11%

Samenvatting

Je kunt niet pushen naar de ene uitgecheckte branch van een repository, omdat het de gebruiker van die repository zou knoeien op een manier die hoogstwaarschijnlijk zal eindigen met verlies van gegevens en geschiedenis. Maar je kunt naar elke andere tak van dezelfde repository pushen.

Omdat bare repositories nooit een branch hebben uitgecheckt, kun je altijd pushen naar elke branch van een bare repository.

Er zijn meerdere oplossingen, afhankelijk van uw behoeften.

Oplossing 1: gebruik een kale repository

Zoals gesuggereerd, als je op één machine de werkdirectory niet nodig hebt, kun je naar een kale repository gaan. Om te voorkomen dat je met de repository knoeit, kun je hem gewoon klonen:

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

Je kunt nu alles naar hetzelfde adres pushen als voorheen.

Oplossing 2: doorsturen naar een niet-uitgecheckt filiaal

Maar als je de code op je externe <remote>moet bekijken, dan kun je een speciale branch gebruiken om te pushen. Laten we zeggen dat je in je lokale repository je remote originhebt aangeroepen en dat je op branch master zit. Dan zou je kunnen doen

machine2$ git push origin master:master+machine2

Vervolgens moet u het samenvoegen wanneer u zich in de originexterne repo bevindt:

machine1$ git merge master+machine2

Autopsie van het probleem

Als een branch is uitgecheckt, zal committing een nieuwe commit toevoegen met de head van de huidige branch als ouder en de head van de branch verplaatsen om die nieuwe commit te zijn.

Dus

A ← B
    ↑
[HEAD,branch1]

wordt

A ← B ← C
        ↑
    [HEAD,branch1]

Maar als iemand naar die branch daartussen zou kunnen pushen, zou de gebruiker in wat git de modus detached headnoemt:

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

De gebruiker bevindt zich nu niet meer in branch1, zonder expliciet gevraagd te hebben om een ​​andere branch uit te checken. Erger nog, de gebruiker bevindt zich nu buiten elke branch, en elke nieuwe commit zal gewoon bungelen:

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

Hypothetisch, als de gebruiker op dit punt een andere branch uitcheckt, dan wordt deze bungelende commit een eerlijk spel voor Git’s vuilnisophaler.


Antwoord 5, autoriteit 6%

Je kunt deze “beperking” omzeilen door de .git/configop de doelserver te bewerken. Voeg het volgende toe om toe te staan ​​dat een git-repository wordt gepusht, zelfs als deze is “uitgecheckt”:

[receive]
denyCurrentBranch = warn

of

[receive]
denyCurrentBranch = false

De eerste laat het pushen toe terwijl het waarschuwt voor de mogelijkheid om de branch te verknoeien, terwijl de tweede het stilletjes toelaat.

Dit kan worden gebruikt om code te “implementeren” naar een server die niet bedoeld is om te bewerken. Dit is niet de beste aanpak, maar wel een snelle manier om code te implementeren.


Antwoord 6, autoriteit 4%

git config --local receive.denyCurrentBranch updateInstead

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

Gebruik dat op de serverrepository, en het werkt ook de werkboom bij als er geen ongecontroleerde overschrijving zou plaatsvinden.

Het is toegevoegd in Git 2.3als vermeld door VonCin de opmerkingen.

Ik heb Git 2.3 gecompileerd en geprobeerd. Voorbeeldgebruik:

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

Uitvoer:

a
b

Ja, bis gepusht!


Antwoord 7, autoriteit 4%

Ik hou van het idee om nog steeds een bruikbare repository op de remote box te hebben, maar in plaats van een dummy branch, gebruik ik graag:

git checkout --detach

Dit lijkt een heel nieuwe functie te zijn van Git– ik ben met git-versie 1.7.7.4.


Antwoord 8, autoriteit 3%

Ik had hetzelfde probleem. Voor mij gebruik ik Git push om code naar mijn servers te verplaatsen. Ik verander nooit de code aan de serverkant, dus dit is veilig.

In de repository druk je om te typen:

git config receive.denyCurrentBranch ignore

Hiermee kun je de repository wijzigen terwijl het een werkkopie is.

Nadat je een Git-push hebt uitgevoerd, ga je naar de externe machine en typ je dit:

git checkout -f

Hierdoor worden de door u doorgevoerde wijzigingen doorgevoerd in de werkkopie van de externe machine.

Let op, dit is niet altijd veilig als je wijzigingen aanbrengt in de werkkopie waarnaar je pusht.


Antwoord 9, autoriteit 2%

U kunt uw serverrepository opnieuw maken en van uw lokale filiaalmaster naar de servermaster pushen.

Op uw externe server:

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

OK, van uw lokale vestiging:

git push origin master:master

10

U moet alleen naar een blote repository duwen. Een blote repository is een repository die geen uitcheckt takken heeft. Als u naar CD naar een BARE Repository-directory was, ziet u alleen de inhoud van een .git-directory.


11

Stel in feite de afstandsbediening in op een niet-gecontroleerde tak is voldoende. Nadat u uw afstandsbediening hebt ingecheckt in een andere branche, kunt u duwen.


Antwoord 12

OK, als je een normale externe repository wilt, maak dan een extra branch aan en check het uit. Duw het naar een branch (die niet is uitgecheckt) en merge het met een die momenteel actief is, later na het pushen van lokaal.

Bijvoorbeeld op een externe server:

git branch dev
git checkout dev

Op de lokale installatie:

git push 

Op externe server:

git merge dev

Antwoord 13

Hier is één test die u kunt doen om te zien hoe de bareserver-dingen werken:

Stel je hebt een werkstation en een server waarop een live site wordt gehost, en je wilt deze site van tijd tot tijd bijwerken (dit geldt ook voor een situatie waarin twee ontwikkelaars hun werk heen en weer sturen een blote tussenpersoon).

Initialisatie

Maak een map op uw lokale computer en cderin, en voer dan deze opdrachten uit:

# initialization
git init --bare server/.git
git clone server content
git clone server local
  1. Eerst maak je een kale serverdirectory aan (let op de .git aan het einde). Deze map zal alleen dienen als een container voor uw repository-bestanden.
  2. Kloon vervolgens uw serverrepository naar een nieuw aangemaakte content-directory. Dit is uw live/productiedirectory die door uw serversoftware wordt bediend.
  3. De eerste twee directory’s bevinden zich op uw server, de derde is een lokale directory op uw werkstation.

Werkstroom

Hier is nu de basisworkflow:

  1. Voer de localdirectory in, maak enkele bestanden aan en leg ze vast. Duw ze tenslotte naar de server:

    # create crazy stuff
    git commit -av
    git push origin master
    
  2. Voer nu de contentdirectory in en werk de inhoud van de server bij:

    git pull
    
  3. Herhaal 1-2. Hier kan contenteen andere ontwikkelaar zijn die ook naar de server kan pushen, en localzoals je van hem kunt halen.


Antwoord 14

Door dit te gebruiken om het naar de afgelegen stroomopwaartse tak te pushen, loste dit probleem voor mij op:

git push <remote> master:origin/master

De afstandsbediening had geen toegang tot de upstream-repo, dus dit was een goede manier om de laatste wijzigingen in die afstandsbediening te krijgen


Antwoord 15

Ik moest git --initopnieuw uitvoeren in een bestaande bare repository, en dit had een .gitdirectory aangemaakt in de bare repository tree – ik realiseerde me dat na het typen van git statusdaar. Ik heb dat verwijderd en alles was weer in orde 🙂

(Al deze antwoorden zijn geweldig, maar in mijn geval was het iets heel anders (voor zover ik kan zien), zoals beschreven.)


Antwoord 16

Ik weet zeker dat de meeste mensen die deze vraag bekijken, stoppen bij de eerste twee enorme antwoorden, maar ik wil toch graag mijn oplossing aanbieden.

Ik had een Eclipse + EGit-webprojectconfiguratie toen ik de beschreven fout tegenkwam. Wat me hielp, was gewoon de GitHub-app gebruiken, die het probleem op magische wijze leek op te lossen. Terwijl EGit altijd de push zou weigeren, zou de GitHub-desktopapp gewoon zijn schouders ophalen en mijn wijzigingen doordrukken. Misschien handelt het de multi-login-situatie eleganter af.


Antwoord 17

De beste manier om dit te doen is:

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

Hiermee wordt de repository gekloond, maar er worden geen werkende kopieën gemaakt in .../remote. Als je naar de afstandsbediening kijkt, zie je één map gemaakt, genaamd currentrepo.git, wat waarschijnlijk is wat je wilt.

Vervolgens vanuit je lokale Git-repository:

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

Nadat u wijzigingen heeft aangebracht, kunt u:

git push remoterepo master

Antwoord 18

Ik kwam dit probleem net tegen met een deployment git-repository op Heroku.

Ik weet niet waarom Heroku een niet-kale repository aan hun kant heeft, maar als tijdelijke oplossing kon ik de remote repository resetten en opnieuw uploaden.

Je moet Heroku’s kopie van je repository niet gebruiken als je enige git-repository voor samenwerking, maar voor het geval dat, zal ik duidelijk zeggen: Doe dit niet tenzij je zeker weet dat je een volledige kopie van je repository hebt. repository veilig ergens anders dan Heroku opgeslagen. Als u een reset uitvoert, wordt de inhoud van de repository verwijderd.

Te resetten:

  1. Installeer de Heroku toolbelt(die de opdrachtregelclient bevat) als je dat nog niet hebt gedaan.
  2. Installeer de heroku-repo plug-inals je dat nog niet hebt gedaan.

    heroku plugins:install https://github.com/heroku/heroku-repo.git
    
  3. Voer de reset uit, waardoor de repository wordt verwijderd en een nieuwe, lege wordt gemaakt

    heroku repo:reset
    
  4. Duw naar je Heroku-afstandsbediening zoals je normaal zou doen; het zal alles opnieuw uploaden.


Antwoord 19

Je moet het configuratiebestand op de externe server wijzigen zodra je een lege (kale) repository hebt gemaakt, bijvoorbeeld

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

daar zie je

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

Je maakt dit van onwaar tot waar en ik heb logallrefupdates = true verwijderd (niet zeker van het gebruik ervan!)

naar

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

U kunt het volgende testen

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

Deze HEAD-tak: (onbekend) wordt getoond als je niet in staat bent om te DRUKKEN. Dus als de HEAD-branch niet bekend is, moet u bare veranderen in true en na succesvolle push kunt u de

opnieuw gebruiken

git remote show origin

en je zult zien

HEAD branch: master

Antwoord 20

Voor mij is de werkende oplossing:

OP AFSTAND:

git checkout -b some_tmp_name

OP LOKAAL:

git push 

OP AFSTAND:

git checkout master
git branch -d some_tmp_name

Maar dit is niet de echte oplossing, het is gewoon een tijdelijke oplossing.


Antwoord 21

Voor het geval iemand het nuttig vindt. Voor mij was het een probleem met de git-serverpermissies. Ik heb het project vanaf het begin bekeken en een eenvoudig bestand gepusht en toen kreeg ik de melding “Push afgewezen: Push to origin/master werd afgewezen”


Antwoord 22

Met Git kunnen twee reguliere (niet-bare) opslagplaatsen niet rechtstreeks bestanden heen en weer pushen/trekken. Er moet een tussenliggende kale repository zijn. Blijkbaar is het zoiets als een getrouwd stel dat een kind heeft, en het paar gaat scheiden. De ouders praten niet met elkaar, maar communiceren via het kind.

Dus je hebt één repository, je kloont deze repository naar een kale repository en dan kloon je die naar een derde. De eerste en de derde kunnen informatie uitwisselen via de tweede repository, de kale. Ik denk dat dit logisch is, omdat je niet wilt dat iemand dingen in je repository kan inchecken zonder je toestemming, omdat dat merge-conflicten kan veroorzaken & dergelijke.

Hier is een voorbeeld:

Op pc, in ~/werkruimte

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

Op laptop, in ~/werkruimte (doe geen git init, etc.)

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

// Maak vervolgens verschillende commits en push ze:

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

Vervolgens terug op pc, in ~/werkruimte

git pull

// Maak vervolgens verschillende commits en push ze:

git push 

Op laptop
git pull

enzovoort..

Hier is een absoluut concreet voorbeeld, allemaal op één machine, rechtstreeks gekopieerd uit het opdrachtvenster, zodat we weten dat er geen stappen zijn weggelaten, dat het echt werkte, enz.:

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

Antwoord 23

Ik kwam dit probleem tegen toen ik een opslagplaats op mijn NAS had gekloond en die opslagplaats vervolgens naar mijn machines had gekloond.

De opzet is ongeveer als volgt:

ORIGINEEL (github):

  • gekloond naar netwerkopslag in mijn privé-thuisnetwerk (mijn thuisnetwerk)
    • filiaal uitgecheckt: DEVELOPMENT
  • gekloond naar andere machines (laptops, kleine datacenterserver in mijn kantoor, enz.)
    • filiaal uitgecheckt: DEVELOPMENT

Toen ik probeerde verbinding te maken met de laptop naar de NAS-server, is de fout die verschijnt

! [remote rejected]   development -> development (branch is currently checked out)

De hoofdoorzaak is dat de tak DEVELOPMENTis uitgecheckt op de NAS-server. Mijn oplossing was op de NAS-repository om naar een andere branch over te schakelen. Hierdoor kon ik mijn wijzigingen vastleggen.

Other episodes