2009-09-04 25 views
171

Miałem repozytorium, które miało kilka złych poprawek (D, E i F w tym przykładzie).Reset Git - trudne i zdalne repozytorium

A-B-C-D-E-F Master i początek/Master

I został zmodyfikowany lokalne repozytorium specyficznie z git reset --hard. Wziąłem gałąź przed resetem więc teraz mam repo, który wygląda tak:

A-B-C master 
    \ D-E-F old_master 

A-B-C-D-E-F origin/master 

Teraz potrzebne jakieś części tych złych zobowiązuje więc wiśniowe zrywane bity potrzebowałem i wykonanych kilka nowych zobowiązuje więc teraz mam następujące lokalnie:

A-B-C-G-H master 
    \ D-E-F old_master 

Teraz chcę wprowadzić ten stan rzeczy do zdalnego repo. Jednak, gdy próbuję zrobić git push Git grzecznie daje mi od szczotki:

$ git push origin +master:master --force 
Total 0 (delta 0), reused 0 (delta 0) 
error: denying non-fast forward refs/heads/master (you should pull first) 
To [email protected]:myrepo.git 
! [remote rejected] master -> master (non-fast forward) 
error: failed to push some refs to '[email protected]:myrepo.git' 

Jak uzyskać zdalnego repo do podjęcia aktualny stan lokalnego repo?

+2

Jest to "prawie" duplikat kilku "jak przesłać zmienione pytania dotyczące historii", np. zobacz odpowiedź tutaj http://stackoverflow.com/questions/253055/how-do-i-push-amended-commit-to-the-remote-git-repo/255080#255080 –

+2

To prawda i przeszukałem StackOverflow dla odpowiedź przed wysłaniem. Jednak moje poszukiwania tylko pojawiły się odpowiedzi, w których git push - force naprawił problem. Dziękuję za link do Twojego wpisu :) – robertpostill

+1

Wkrótce (git1.8.5, Q4 2013) będziesz w stanie [zrobić "git push -force" bardziej ostrożnie] (http://stackoverflow.com/a/18505634/6309) . – VonC

Odpowiedz

251

Jeśli zmuszając push nie pomaga („git push --force origin«lub»git push --force origin master” powinno wystarczyć), może to oznaczać, że zdalny serwer odmawia non Przewijanie do przodu popycha za pośrednictwem receive.denyNonFastForwards zmienna config (patrz git config strona podręcznika opis), lub za pośrednictwem haka update/pre-receive.

Starszym Gitem można obejść to ograniczenie, usuwając "git push origin :master" (patrz ":" przed nazwą oddziału), a następnie ponownie tworząc "git push origin master" podaną gałąź.

Jeśli nie można zmienić, to jedynym rozwiązaniem byłoby zamiast przepisywania historii do stworzyć popełnić reverting zmian w DEF:

 
A-B-C-D-E-F-[(D-E-F)^-1] master 

A-B-C-D-E-F        origin/master 
+2

@ JakubNarębski, dziękuję. 'get revert HEAD ~ N' pomógł. 'N' to liczba zatwierdzeń. Np. Jeśli potrzebuję poprzedniego zatwierdzenia, użyję 'git revert HEAD ~ 1'' –

+4

Mogę potwierdzić, że' '' git push --force master''' działa i uratowało mi wiele bólów głowy. – FearlessFuture

23

celu uzupełnienia odpowiedź Jakuba, jeśli masz dostęp do zdalny serwer git w ssh, można przejść do katalogu zdalnego git i ustawić:

[email protected]$ git config receive.denyNonFastforwards false 

Następnie wróć do lokalnego repo, spróbuj ponownie, aby wykonać commit z --force:

[email protected]$ git push origin +master:master --force 

I wreszcie przywrócić ustawienia serwera w oryginalnym chronionego państwa:

[email protected]$ git config receive.denyNonFastforwards true 
+0

Zobacz także http://pete.akeo.ie/2011/02/denying-non-fast-forward-and.html dla sourceforge dostosowane informacje na ten temat. – hlovdal

+0

Szczegółowe instrukcje dotyczące wyłączania opcji denyNonFastForwards za pomocą 'vi' znajdują się w tym wpisie SO: stackoverflow.com/a/43721579/2073804 – ron190

1

zamiast ustalania swój „master” oddział, to sposób łatwiej zamienić go z „pożądany-master” przez zmianę nazwy gałęzie. Zobacz https://stackoverflow.com/a/2862606/2321594. W ten sposób nie zostawisz nawet śladu wielu dzienników przywracania.

0

Cała operacja resetowania git wyglądała na dalszą komplikację dla mnie.

Więc zrobiłem coś wzdłuż linii, aby mój katalog src w stanie miałem kilka commity temu

# reset the local state 
git reset <somecommit> --hard 
# copy the relevant part e.g. src (exclude is only needed if you specify .) 
tar cvfz /tmp/current.tgz --exclude .git src 
# get the current state of git 
git pull 
# remove what you don't like anymore 
rm -rf src 
# restore from the tar file 
tar xvfz /tmp/current.tgz 
# commit everything back to git 
git commit -a 
# now you can properly push 
git push 

ten sposób stan rzeczy w src jest przechowywany w pliku tar i git jest zmuszony do zaakceptowania tego stanu bez zbytniego manipulowania w zasadzie katalog src jest zastępowany stanem, który miał kilka zatwierdzeń temu.

Powiązane problemy