Git rozdzielił się po rebase


112

Przebudowałem lokalnie gałąź, która została już przeniesiona.

Git informuje, że mój oddział i pilot rozeszły się i że:

"i mają odpowiednio 109 i 73 różne zatwierdzenia"

Czy wypchnięcie mojej gałęzi rozwiąże ten problem - tj. Czy można się tego spodziewać po rebase?


Mam ten sam problem. Czy można powiedzieć, że „właściwą drogą” jest przebudowa lokalnego oddziału i dopiero wtedy forsowanie?
— Mher Didaryan,

Odpowiedzi:


154

Kiedy przebudowujesz gałąź, musisz przepisać zatwierdzenia dla każdego zatwierdzenia, które znajduje się powyżej zatwierdzeń w gałęzi, na której ponownie bazujesz. Dzieje się tak, ponieważ jedną z właściwości zatwierdzenia jest jego rodzic (lub rodzice). Kiedy dokonujesz rebase, zmieniasz rodzica najstarszego lokalnego zatwierdzenia w twojej gałęzi - a tym samym zmieniasz skróty zatwierdzeń wszystkich lokalnych zatwierdzeń, ponieważ ta zmiana przenosi się przez zatwierdzenia przejściowo.

Ponieważ już wypchnąłeś gałąź, powinieneś był połączyć się z gałęzią źródłową, zamiast opierać się na niej. Możliwe jest "wymuszenie wypchnięcia" twojej nowej gałęzi (używając -fflagi), ale normalny push nie zadziała, ponieważ integralność historii gałęzi zostanie zakłócona. Jeśli współpracujesz z innymi osobami w tej gałęzi, forsowanie siły jest złym pomysłem, ponieważ spowoduje, że inni współpracownicy będą bardzo zdezorientowani, gdy ich historia nagle się nie zgadza.

TL; DR - Jeśli nie współpracujesz, wypchnij gałąź za pomocą push -f. Jeśli tak, zresetuj gałąź do poprzedniego stanu i zamiast tego scal ją w gałęzi źródłowej.


1
„Skoro już wypchnąłeś gałąź, powinieneś był włączyć ją do gałęzi źródłowej” - dlaczego tak jest?
— hammett

1
Pierwsze zdanie @HamiltonVerissimo Jasona: „Kiedy przebudowujesz gałąź, musisz przepisać zatwierdzenia dla każdego zatwierdzenia, które znajduje się powyżej zatwierdzeń w gałęzi, na której ponownie bazujesz.” Mimo że zmiany uchwycone w "powyższych" zatwierdzeniach mają tę samą logiczną zawartość, są one stosowane do innej bazy i dlatego są różnymi zatwierdzeniami z różnymi skrótami. Jeśli inni programiści pracują z gałęzi pre-rebased, wykonanie polecenia git push -f mogłoby bardzo zakłócić ich przepływ pracy. Tak więc, skoro ta gałąź została zepchnięta do publicznego źródła, powinien był się połączyć.
— awolf

4
możesz również użyć push --force-with-lease, jeśli nie jesteś pewien, czy ktoś inny już coś zrobił.
— Konsola

1
@ jason-lebrun Czy nie jest wadą scalania zewnętrznych zmian, że możesz nadpisać własną pracę bez ostrzeżenia? Czy konflikty scalania są wykrywane w taki sam sposób, jak podczas ponownego bazowania? Na przykład, jeśli usunę sekcję z pliku w mojej gałęzi, ponieważ nie jest już potrzebna, ale ktoś inny wprowadził trywialną zmianę w tej samej sekcji w górnej części, na przykład usunięcie jakiejś białej spacji lub jakiejś globalnej akcji znajdowania / zamieniania, nie scalenie tego na górze mojej gałęzi zastąpić moje usunięcie ich trywialnie zmienioną wersją?
— Chris Bloom,

1
Czy połączenie drugiej gałęzi z Twoją nie jest złym pomysłem? Np. Scalanie mastera w gałąź funkcji - czy to nie stworzy nowego zatwierdzenia? Czy nie spowoduje to dodatkowego zatwierdzenia po rozgałęzieniu tej funkcji, jeśli później zostanie scalone z wzorcem?
— Ross

55

Wszystkie twoje zatwierdzenia zmieniły identyfikatory, więc dywersja nie jest tak naprawdę rozbieżna.

Aby rozwiązać problem , musisz nadpisać zdalną gałąź:

git push -f origin experiment

http://git-scm.com/book/ch3-6.html

Wyjaśnienie:

Zobacz, jak na tym obrazku C3 nie jest wstawiane jako C3 po rebase, ale jako C3 '. Dzieje się tak, ponieważ nie jest to dokładnie C3, ale ma wszystkie zmiany w kodzie.

Rebase

Na tym drugim obrazie widać, co widzi rebase, gdy w grę wchodzi pilot, i dlaczego występuje przekierowanie.

odejdź i popchnij

W każdym razie, po wykonaniu wymuszonego pchnięcia, powie ci, że wykonał (wymuszoną aktualizację), w tym momencie powinno być dobrze.

Sprawdź link u góry i wyszukaj „git push --force”. Zobaczysz bardziej szczegółowe wyjaśnienie.


3
Tak. Myślę, że to rozwiązuje problem. Jednak pchnięcie siły może nie działać, gdy pracujesz w zespole, gdy naciśnięcie może nadpisać ostatnią pracę wymuszoną przez innych. Czy mam rację?
— Hari Krishna Ganji

Może nie przynieść pożądanych efektów. Upewnij się, że scaliłeś swoje zmiany „szybko do przodu” przed wykonaniem rebase.
— mimoralea

1

Udało mi się odejść od rebase, wykonując następujące czynności:

git checkout mybranch
git pull
git push origin mybranch

Pociągnięcie rozwiązało rozbieżność.

PRZED pociągnięciem

Your branch and 'origin/mybranch' have diverged,
and have 2 and 1 different commit(s) each, respectively.

Wyjście PULL

Scalanie rekurencyjne. mypath / myfile.py | 12 +++++++++++ - 1 plik zmieniony, 11 wstawień (+), 1 usunięcia (-)

PO pociągnięciu

Twoja gałąź wyprzedza „origin / mybranch” o 3 zatwierdzenia.

PO PUSH

mybranch wyprzedza gałąź o 3, ale nadal ma otwartą wiadomość pull request dodaną do historii zatwierdzeń Połącz gałąź mybranch of remote do mybranch

Zakładam, że jest to prawdopodobnie to, co robi pchnięcie siły i nie zweryfikowałem.

Jak powiedzieli inni, unikaj ponownego bazowania, jeśli masz już otwarte żądanie ściągnięcia. Podaję ten przykład jako coś, co zadziałało dla mnie.


1

Można to naprawić bez pchania siły, przenosząc gałąź docelową do bieżącej gałęzi lokalnej, przełączając się na gałąź docelową, a następnie przekształcając gałąź lokalną w docelową. To się nie różni, ponieważ zmiany, których może brakować, są dodawane i nie trzeba ich już tworzyć. Przykład łatwiejszego wyjaśnienia:

  1. główna gałąź jest rozwijana
  2. Kupujesz nową funkcję oddziału / doing_stuff
  3. Członek zespołu popycha nowe zobowiązanie do rozwoju

Jeśli NIE zaktualizowałeś swojej gałęzi deweloperskiej, wtedy "git checkout develop" && "git rebase feature / doing_stuff" będzie działać poprawnie, ponieważ nie dodano żadnych zatwierdzeń od czasu twojego zamówienia. Jeśli jednak sprawdziłeś program i usunąłeś nowy commit, zobaczysz tę rozbieżność, jeśli spróbujesz zmienić bazę z powodu zobaczenia nowego zatwierdzenia. Łatwym rozwiązaniem bez naciskania na siłę (zwykle nie jest to dobry pomysł w środowisku zespołowym) jest:

  1. git checkout feature / doing_stuff
  2. git rebase rozwijać
  3. git checkout rozwijać
  4. git rebase feature / doing_stuff

Rebase z kroku 2 przenosi brakujące zatwierdzenie do feature / doing_stuff, więc gdy pojawia się krok 4, jest aktualny i nie ma potrzeby tworzenia nowego zatwierdzenia dla zmiany.

Jest to rozwiązanie, o którym wiem, że działa, ponieważ właśnie na to wpadłem i wykonałem powyższe kroki, aby pomyślnie uruchomić programowanie bez użycia siły. Pracuję w ponad 50-osobowym zespole programistów, więc nie wolno wymuszać niczego innego niż moje własne gałęzie testowe, więc musiałem znaleźć rozwiązanie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.