Wymuś „git push”, aby zastąpić zdalne pliki

766

Chcę wypchnąć moje lokalne pliki i mieć je na zdalnym repozytorium, bez konieczności radzenia sobie z konfliktami scalania. Chcę tylko, aby moja wersja lokalna miała wyższy priorytet niż wersja zdalna.

Jak mogę to zrobić za pomocą Git?

opensas
źródło
106
Nie git push origin --forcedziałało dla ciebie?
Nie jest jasne, czy chcesz zastąpić tylko pliki .git lub powiązaną kopię roboczą. Jeśli jest to repozytorium git, odpowiedzią jest git push. Jeśli chcesz zaktualizować zdalną kopię roboczą, musisz użyć haka po odebraniu
Pierre-Olivier Vares
@Mike, który z jakiegoś powodu działa dla mnie ... zastanawiam się, co było z OP
Prawdopodobna przyczyna wymuszonego wypychania nie działa, ponieważ mogła zostać wyraźnie wyłączona na zdalnym repozytorium (aby upewnić się, że nic nie zostanie utracone z powodu idiotycznych i / lub złośliwych współpracowników): użyj, config receive.denyNonFastforwardsaby się dowiedzieć.
Frank Nocke,

Odpowiedzi:

1085

Powinieneś być w stanie wymusić lokalną wersję do zdalnego repozytorium za pomocą

git push -f <remote> <branch>

(np git push -f origin master.). Wyjście <remote>i <branch>wymusi wypchnięcie wszystkich lokalnych oddziałów, które zostały ustawione --set-upstream.

Ostrzegamy, że jeśli inne osoby współużytkują to repozytorium, ich historia zmian będzie w konflikcie z nowym. A jeśli mają jakieś lokalne zobowiązania po punkcie zmiany, staną się nieważne.

Aktualizacja : Myślałem, że dodam notatkę dodatkową. Jeśli tworzysz zmiany, które inni sprawdzą, nie jest rzadkością tworzenie gałęzi z tymi zmianami i okresowe wprowadzanie zmian w bazie, aby być na bieżąco z główną gałęzią programistyczną. Po prostu daj innym programistom do zrozumienia, że ​​tak się stanie, aby wiedzieli, czego się spodziewać.

Aktualizacja 2 : Z powodu rosnącej liczby widzów chciałbym dodać dodatkowe informacje na temat tego, co robić, gdy upstreampojawia się wymuszenie.

Powiedzmy, że sklonowałem twoje repozytorium i dodałem kilka takich zmian:

            D ---- E temat
           /
Rozwój A ---- B ---- C.

Ale później developmentgałąź trafia z rebase, co spowoduje, że otrzymam błąd taki jak po uruchomieniu git pull:

Rozpakowywanie obiektów: 100% (3/3), gotowe.
Od <repolokalizacja>
 * rozwój oddziału -> FETCH_HEAD
Automatyczne łączenie <plików>
KONFLIKT (treść): Scal konflikt w <lokalizacjach>
Automatyczne scalanie nie powiodło się; naprawić konflikty, a następnie zatwierdzić wynik.

Tutaj mogłem naprawić konflikty commit, ale to dałoby mi naprawdę brzydką historię popełnień:

       Temat C ---- D ---- E ---- F.
      / /
Rozwój A ---- B -------------- C.

Może wyglądać kusząco w użyciu, git pull --forceale bądź ostrożny, ponieważ pozostawi cię z osieroconymi zatwierdzeniami:

            D ---- E temat

Rozwój A ---- B ---- C '

Więc prawdopodobnie najlepszą opcją jest zrobienie git pull --rebase. Będzie to wymagać ode mnie rozwiązania wszelkich konfliktów, jak poprzednio, ale użyję każdego kroku zamiast popełnienia git rebase --continue. Na koniec historia zmian będzie wyglądać znacznie lepiej:

            Temat D '--- E'
           /
Rozwój A ---- B ---- C '

Aktualizacja 3: Możesz również użyć tej --force-with-leaseopcji jako „bezpieczniejszego” forsowania, jak wspomniał Cupcake w swojej odpowiedzi :

Wymuszone wypychanie z „dzierżawą” pozwala, aby wymuszone wypychanie nie powiodło się, jeśli na pilocie pojawią się nowe zatwierdzenia, których się nie spodziewałeś (technicznie rzecz biorąc, jeśli jeszcze nie wprowadziłeś ich do gałęzi zdalnego śledzenia), co jest przydatne, jeśli nie chcesz przypadkowo zastąpić cudzych zobowiązań, o których nawet jeszcze nie wiedziałeś, a po prostu chcesz zastąpić własne:

git push <remote> <branch> --force-with-lease

Możesz dowiedzieć się więcej o tym, jak korzystać --force-with-lease, czytając dowolne z poniższych:

Trevor Norris
źródło
5
Ponieważ jest to wybrana odpowiedź, skomentuję tutaj. Używanie siły nie stanowi problemu podczas samodzielnej pracy. Na przykład mój host w chmurze zaczyna się od własnego git. Jeśli pracuję lokalnie i buduję projekt i chcę go umieścić na moim hoście w chmurze (OpenShift), mam dwa osobne projekty git. Mój lokalny i mój OpenShift. Dostaję lokalny tak, jak lubię, ale teraz chcę go wyświetlić na moim OpenShift. Następnie naciskasz na OpenShift po raz pierwszy, używając -fflagi. Zasadniczo umieszczasz lokalnego git na OpenShift.
Wade
128

Chcesz wymusić push

W zasadzie chcesz wymusić wypchnięcie lokalnego oddziału, aby zastąpić zdalny.

Jeśli chcesz uzyskać bardziej szczegółowe objaśnienie każdego z poniższych poleceń, zobacz sekcję moje szczegóły poniżej. Zasadniczo masz 4 różne opcje forsowania za pomocą Git:

git push <remote> <branch> -f
git push origin master -f # Example

git push <remote> -f
git push origin -f # Example

git push -f

git push <remote> <branch> --force-with-lease

Jeśli chcesz uzyskać bardziej szczegółowe wyjaśnienie każdego polecenia, zobacz sekcję moich długich odpowiedzi poniżej.

Ostrzeżenie: wymuszone wypychanie zastąpi gałąź zdalną stanem gałęzi, którą wypychasz. Upewnij się, że to jest to, co naprawdę chcesz zrobić, zanim go użyjesz, w przeciwnym razie możesz zastąpić zatwierdzenia, które naprawdę chcesz zachować.

Wymuszaj pchanie szczegółów

Określanie zdalnego i rozgałęzienia

Możesz całkowicie określić określone gałęzie i pilota. -fFlaga jest krótka wersja--force

git push <remote> <branch> --force
git push <remote> <branch> -f

Pominięcie gałęzi

Kiedy gałąź do gałęzi push zostanie pominięta, Git odkryje ją na podstawie ustawień konfiguracji. W wersjach Git po wersji 2.0 nowe repozytorium będzie miało domyślne ustawienia wypychające aktualnie wyewidencjonowaną gałąź:

git push <remote> --force

w wersjach wcześniejszych niż 2.0 nowe repo będą miały domyślne ustawienia wypychania wielu lokalnych oddziałów. Ustawienia, o których mowa, to ustawienia remote.<remote>.pushi push.default(patrz poniżej).

Pominięcie pilota i oddziału

Gdy zarówno pilot, jak i gałąź zostaną pominięte, zachowanie just git push --forcejest określane przez push.defaultustawienia konfiguracji Git:

git push --force
  • Począwszy od Git 2.0, ustawienie domyślne simplepo prostu popchnie twoją obecną gałąź do jej zdalnej przeciwnej części. Zdalny jest określany przez ustawienie oddziału branch.<remote>.remote, aw przeciwnym razie domyślnie jest to repozytorium początkowe.

  • Przed wersją Git 2.0 ustawienie domyślne matchingpo prostu wypycha wszystkie gałęzie lokalne do gałęzi o tej samej nazwie na pilocie (domyślnie jest to początek).

Możesz przeczytać więcej push.defaultustawień, czytając git help configlub wersję online strony podręcznika git-config (1) .

Siła pchania bezpieczniej dzięki --force-with-lease

Wymuszone wypychanie z „dzierżawą” pozwala, aby wymuszone wypychanie nie powiodło się, jeśli na pilocie pojawią się nowe zatwierdzenia, których się nie spodziewałeś (technicznie rzecz biorąc, jeśli jeszcze nie wprowadziłeś ich do gałęzi zdalnego śledzenia), co jest przydatne, jeśli nie chcesz przypadkowo zastąpić cudzych zobowiązań, o których nawet jeszcze nie wiedziałeś, a po prostu chcesz zastąpić własne:

git push <remote> <branch> --force-with-lease

Możesz dowiedzieć się więcej o tym, jak korzystać --force-with-lease, czytając dowolne z poniższych:

Społeczność
źródło
Masz rację, ale tak naprawdę powinno się tego używać tylko w wyjątkowych sytuacjach.
Scott Berrevoets
1
@ ScottBerrevoets „ Wolałbym przesuwać to, co mam i pozwolić, aby zastąpiło je zdalnie, niż integrować. ” Dałem OP dokładnie to, o co prosił.
Wiem, ale OP może nie być świadomy konsekwencji takiego postępowania. Technicznie odpowiedziałeś na pytanie, ale myślę, że ostrzeżenie, aby tego nie robić, nie jest nie na miejscu.
Scott Berrevoets,
1
@ScottBerrevoets Staram się, aby moderator połączył moją odpowiedź w kanoniczny, ponieważ wspominam o nowej --force-with-leaseopcji;)
32

Inną opcją (aby uniknąć wymuszonego wypychania, które może być problematyczne dla innych autorów) jest:

  • umieść swoje nowe commity w dedykowanym oddziale
  • zresetować masterONorigin/master
  • połącz swój dedykowany oddział z master, zawsze zachowując zatwierdzenia z dedykowanego oddziału (co oznacza tworzenie nowych poprawek, masterktóre będą odzwierciedlały dedykowany oddział).
    Zobacz „ Polecenie git, aby utworzyć jedną gałąź jak drugą ”, aby poznać strategie symulowania git merge --strategy=theirs.

W ten sposób możesz przepchnąć mistrza do pilota bez konieczności zmuszania czegokolwiek.

VonC
źródło
Czym różni się wynik od „siły nacisku”?
alexkovelsky
6
@alexkovelsky Każde wymuszone push zmieniłoby historię, zmuszając innych użytkowników repozytorium do zresetowania własnego repozytorium lokalnego, aby pasowało do nowo wypchniętych zatwierdzeń. Takie podejście tworzy tylko nowe zatwierdzenia i nie wymaga wymuszonego wypychania.
VonC
1
Proponuję dodać nagłówek do swojej odpowiedzi: „Nie chcesz wymuszać wypychania” :)
alexkovelsky 15.01.2018
@alexkovelsky Dobra uwaga. Odpowiednio zredagowałem odpowiedź.
VonC
4

git push -f jest nieco destrukcyjny, ponieważ resetuje wszelkie zdalne zmiany, które zostały wprowadzone przez kogoś innego w zespole. Bezpieczniejszą opcją jest {git push --force-with-lease}.

To, co robi {--force-with-lease}, to odmowa aktualizacji oddziału, chyba że tego oczekujemy; tzn. nikt nie zaktualizował oddziału powyżej. W praktyce działa to poprzez sprawdzenie, czy referencja w górę jest tym, czego oczekujemy, ponieważ referencje są skrótami i domyślnie kodują łańcuch rodziców do ich wartości. Możesz powiedzieć {--force-with-lease} dokładnie, co należy sprawdzić, ale domyślnie sprawdzi bieżący zdalny ref. W praktyce oznacza to, że kiedy Alice zaktualizuje swój oddział i wypchnie go do zdalnego repozytorium, głowa wskazująca oddział zostanie zaktualizowana. Teraz, chyba że Bob wykona ściąganie z pilota, jego lokalne odniesienie do pilota będzie nieaktualne. Kiedy pójdzie do wypychania za pomocą {--force-with-lease}, git sprawdzi lokalnego ref względem nowego pilota i odmówi wymuszenia push. {--force-with-lease} skutecznie pozwala na wymuszanie push tylko wtedy, gdy nikt inny nie przekazał w międzyczasie zmian do pilota. Jest {--force} z zapiętym pasem bezpieczeństwa.

Lando Ke
źródło
3

Pracuje dla mnie:

git push --set-upstream origin master -f
Jithish PN
źródło
0

Proste kroki przy użyciu tortoisegit

GIT podający zatwierdzanie plików lokalnych i wypychanie do repozytorium git.

Kroki :

1) skrytka zmienia nazwę skrytki

2) pociągnij

3) stash pop

4) zatwierdzić 1 lub więcej plików i podać opis zmian zmian autora i datę

5) push

Nagnath Mungade
źródło