Błąd Git Push: odmowa aktualizacji wyewidencjonowanego oddziału

196

Rozwiązałem niektóre konflikty scalania, zatwierdziłem, a następnie spróbowałem przekazać zmiany i otrzymałem następujący błąd:

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

Czy ktoś wie, co może być przyczyną tego błędu?

Odjechany
źródło
6
W rzeczywistości masz teraz bezpieczny sposób na przeforsowanie repozytorium non-go z Git 2.3.0 (luty 2015) i git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309
VonC

Odpowiedzi:

229

Powód: Naciskasz na repozytorium non-bare

Istnieją dwa rodzaje repozytoriów: nagie i nie-nagie

Nagie repozytoria nie mają kopii roboczej i można do nich pchać. To są typy repozytoriów, które otrzymujesz w Github! Jeśli chcesz utworzyć puste repozytorium, możesz użyć

git init --bare

Krótko mówiąc, nie można naciskać na repozytorium inne niż nagie(Edycja: Cóż, nie możesz wypychać do aktualnie wyewidencjonowanej gałęzi repozytorium. W nagim repozytorium możesz wypychać do dowolnej gałęzi, ponieważ żadne nie jest wyewidencjonowane. Chociaż jest to możliwe, wypychanie do repozytoriów innych niż nagie nie jest powszechne) . Co możesz zrobić, to pobrać i połączyć z drugiego repozytorium. Tak działa to pull request, co widać w Github. Prosisz ich, aby cię odciągnęli, i nie zmuszasz się do nich.


Aktualizacja : Dzięki VonC za zwrócenie na to uwagi, w najnowszych wersjach git (obecnie 2.3.0) możliwe jest wypychanie do wyewidencjonowanej gałęzi repozytorium non-go . Niemniej jednak nadal nie możesz przepchnąć się do brudnego drzewa roboczego, co i tak nie jest bezpieczną operacją.

Shahbaz
źródło
1
Tak! To prawda, dziękuję! Ponieważ mam około miliona rzeczy do zrobienia, przypadkowo sklonowałem katalog roboczy .... doh!
Funky
25
W rzeczywistości możesz przepchnąć do niepublicznego repozytorium w porządku, po prostu nie możesz wypchnąć do jednej gałęzi, która jest obecnie wyewidencjonowana .
Nigdzie,
1
W rzeczywistości istnieją dziesiątki innych scenariuszy. Na przykład niektóre z moich repozytoriów znajdują się tylko na mojej stacji roboczej i laptopie (nie kod, ale notatki, które robię). Na każdym mam dwa oddziały: „stację roboczą” i „laptop”. Na stacji roboczej sprawdzam tylko „stację roboczą” i pcham tylko do gałęzi „stacji roboczej” na laptopie (i odwrotnie).
Nigdzie człowiek
8
Masz teraz bezpieczny sposób na przeforsowanie repozytorium non-go z Git 2.3.0 (luty 2015) i git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309
VonC
1
@skelly Twój klon nie jest pusty, a kopia na github. Tak więc, chociaż oba klony mają całą historię, kopia na github nie ma żadnego zatwierdzonego sprawdzenia, ale twoja kopia ma, aby umożliwić ci pracę!
Shahbaz
115

Rozwiązałem ten problem, najpierw sprawdzając, czy pilot nie ma niczego sprawdzonego (tak naprawdę nie powinien), a następnie ujawniłem:

$ git config --bool core.bare true

Po tym git push działał dobrze.

Sasha Pachev
źródło
3
To jest poprawka jednoliniowa, której szukałem ... ale może wyjaśnij nagie nie-nagie repo, takie jak odpowiedź
@shahbaz
Umożliwi to wypchnięcie historii zmian, ale zmiany te nie zostaną odzwierciedlone w repozytorium non-bare.
jhill515
będziesz git config core.bare falsei git reset --hard ?
samolot
1
Jak wspomniano powyżej, pilot nie zostanie zmodyfikowany po naciśnięciu go.
user1097111
46

Podsumowanie

Nie można wypychać do tej sprawdzonej gałęzi repozytorium, ponieważ bałaganiłby użytkownika tego repozytorium w sposób, który najprawdopodobniej zakończy się utratą danych i historii . Ale możesz wypychać do dowolnej innej gałęzi tego samego repozytorium.

Ponieważ nagie repozytoria nigdy nie mają wypisanej żadnej gałęzi, zawsze możesz wypchnąć do dowolnej gałęzi nagiego repozytorium.

Autopsja problemu

Kiedy gałąź jest wyewidencjonowana, zatwierdzanie doda nowe zatwierdzenie z nagłówkiem bieżącej gałęzi jako jej rodzicem i przesunie główkę gałęzi, aby była nowym zatwierdzeniem.

Więc

A ← B
    ↑
[HEAD,branch1]

staje się

A ← B ← C
        ↑
    [HEAD,branch1]

Ale gdyby ktoś mógł przepchnąć się do tej gałęzi między nimi, użytkownik znalazłby się w trybie, który git nazywa odłączonym trybem głowy :

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

Teraz użytkownik nie znajduje się już w gałęzi 1, bez wyraźnego poproszenia o sprawdzenie innej gałęzi. Co gorsza, użytkownik jest teraz poza jakimkolwiek oddziałem , a każde nowe zatwierdzenie będzie po prostu zwisać :

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

Hipotetycznie, jeśli w tym momencie użytkownik sprawdzi inny oddział, wówczas ten zwisający zatwierdzenie staje się uczciwą grą dla śmieciarza Gita .

Człowiek znikąd
źródło
Rozwijałem się trochę na stackoverflow.com/questions/2816369/...
Nigdzie,
21

cd do katalogu repo /, do którego wypychasz na zdalnym komputerze i naciśnij enter

$ git config core.bare true
Ricky
źródło
To nie działa. Repozytorium pozostaje puste po wepchnięciu do niego.
Sören,
jak powiedział jhil515 powyżej, pliki inne niż nagie nie są aktualizowane, tylko bazy danych.
Denis Cousineau,
20

Dla mnie załatwiłem sprawę:

git config --global receive.denyCurrentBranch updateInstead

Skonfigurowałem dysk F: prawie w całości, aby synchronizować między komputerem stacjonarnym z systemem Windows 10 a laptopem z systemem Windows 10 za pomocą Git. W końcu uruchomiłem powyższe polecenie na obu komputerach.

Najpierw udostępniłem dysk F na pulpicie w sieci. Następnie udało mi się sklonować go na moim laptopie, uruchamiając:

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

Niestety wszystkie pliki znalazły się pod „F: \ f \” na moim laptopie, a nie bezpośrednio pod F: \. Ale udało mi się je wyciąć i wkleić ręcznie. Później Git nadal pracował z nowej lokalizacji.

Potem próbowałem wprowadzić pewne zmiany w plikach na laptopie, zatwierdzając je i wypychając z powrotem na pulpit. To nie działało, dopóki nie uruchomiłem wyżej wymienionej komendy git config.

Zauważ, że uruchomiłem wszystkie te polecenia z Windows PowerShell, na obu komputerach.

AKTUALIZACJA: W niektórych przypadkach nadal miałem problemy z wypychaniem zmian. W końcu właśnie zacząłem pobierać zmiany, uruchamiając następujące polecenia na komputerze, do którego chcę pobrać najnowsze zatwierdzenia:

git pull --all --prune

Stephen G. Tuggy
źródło
1
Wolę ten lokalny od repozytorium git:git config receive.denyCurrentBranch updateInstead
klor
14

Ponieważ istnieje już repozytorium, działa

git config --bool core.bare true

w zdalnym repozytorium powinno wystarczyć

Z dokumentacji core.bare

Jeśli true (bare = true), zakłada się, że repozytorium jest puste, bez powiązanego katalogu roboczego. W takim przypadku kilka poleceń, które wymagają katalogu roboczego, zostanie wyłączonych, takich jak git-add lub git-merge (ale będziesz mógł to zrobić).

To ustawienie jest automatycznie odgadywane przez git-clone lub git-init podczas tworzenia repozytorium. Domyślnie zakłada się, że repozytorium, które kończy się na „/.git”, nie jest puste (bare = false), podczas gdy wszystkie pozostałe repozytoria są puste (bare = true).

Jasio
źródło
12

TLDR

  1. Ponownie pociągnij i pchnij: git pull &&& git push .
  2. Nadal masz problem? Wciśnij w inny oddział:git push origin master:foo i połącz ją za pomocą zdalnego repo.
  3. Alternatywnie wymusz push, dodając -f( denyCurrentBranchnależy zignorować).

Zasadniczo błąd oznacza, że ​​twoje repozytorium nie jest aktualne z kodem zdalnym (jego indeks i drzewo pracy jest niezgodne z tym, co wypchnąłeś).

Zwykle należy pullnajpierw uzyskać najnowsze zmiany ipush to ponownie.

Jeśli to nie pomoże, spróbuj przepchnąć się do innej gałęzi, np .:

git push origin master:foo

następnie scal tę gałąź w zdalnym repozytorium z powrotem z masterem.

Jeśli celowo zmieniłeś niektóre wcześniejsze zatwierdzenia git rebasei chcesz zastąpić repozytorium swoimi zmianami, prawdopodobnie chcesz wymusić wypychanie przez dodanie parametru -f/ --force(nie zalecane, jeśli tego nie zrobiłeś rebase). Jeśli nadal nie będzie działać, trzeba ustawić receive.denyCurrentBranchsię ignorena odległy jak sugeruje komunikat git poprzez:

git config receive.denyCurrentBranch ignore
kenorb
źródło
3

Może Twoje zdalne repozytorium znajduje się w gałęzi, którą chcesz przekazać. Możesz spróbować pobrać inny oddział na zdalnym komputerze. Zrobiłem to, po czym ten błąd zniknął i odepchnąłem sukces do mojego zdalnego repo. Zauważ, że używam ssh do połączenia własnego serwera zamiast github.com.

JZAU
źródło
1

Wystąpił ten błąd, ponieważ repozytorium git zostało (przypadkowo) zainicjowane dwukrotnie w tej samej lokalizacji: najpierw jako repozytorium non-go, a wkrótce potem jako repo. Ponieważ folder .git pozostaje, git zakłada, że ​​repozytorium nie jest puste. Usunięcie folderu .git i danych katalogu roboczego rozwiązało problem.

Xastor
źródło
1
W mojej sytuacji tak było. Usunięcie .gitfolderu na pilocie pozwoliło mi wcisnąć początkowe zatwierdzenie.
tim.rohrer
0

Wystąpił ten błąd, gdy bawiłem się podczas czytania progit. Utworzyłem lokalne repozytorium, a następnie pobrałem je w innym repozytorium w tym samym systemie plików, dokonałem edycji i próbowałem pchnąć. Po przeczytaniu odpowiedzi NowhereMan szybka poprawka polegała na przejściu do katalogu „zdalnego” i tymczasowym sprawdzeniu kolejnego zatwierdzenia, wypchnięciu z katalogu, w którym dokonałem zmian, a następnie cofnięciu się i przywróceniu głowy z powrotem do mastera.

Nathan Chappell
źródło