Rebasing zdalnych gałęzi w Git

135

Używam pośredniego repozytorium Git do tworzenia kopii lustrzanej zdalnego repozytorium SVN, z którego ludzie mogą klonować i pracować nad nim. Repozytorium pośrednie ma co noc ponownie bazującą gałąź główną z wcześniejszego SVN-a i pracujemy nad gałęziami funkcji. Na przykład:

remote:
  master

local:
  master
  feature

Mogę z powodzeniem przesłać moją gałąź funkcji z powrotem do pilota i otrzymać to, czego oczekuję:

remote:
  master
  feature

local:
  master
  feature

Następnie ponownie konfiguruję gałąź, aby śledzić pilota:

remote:
  master
  feature

local:
  master
  feature -> origin/feature

I wszystko w porządku. To, co chciałbym teraz zrobić, to zmienić bazę gałęzi funkcji na gałąź główną na pilocie, ale chciałbym to zrobić z mojego lokalnego komputera. Chciałbym móc:

git checkout master
git pull
git checkout feature
git rebase master
git push origin feature

Aby zdalna gałąź funkcji była zawsze aktualna ze zdalnym serwerem głównym. Jednak ta metoda powoduje, że Git narzeka:

To <remote>
 ! [rejected]        feature -> feature (non-fast-forward)
error: failed to push some refs to '<remote>'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again.  See the
'Note about fast-forwards' section of 'git push --help' for details.

git pullzałatwia sprawę, ale powoduje zatwierdzenie scalające, którego chciałbym uniknąć. Obawiam się, że wiadomość mówi feature -> featureraczej niż, feature -> origin/featureale może to być tylko prezentacja.

Czy coś mi brakuje, czy robię to w zupełnie niewłaściwy sposób? Nie jest krytyczne, aby unikać wykonywania rebase na serwerze zdalnym, ale znacznie utrudnia to naprawianie wszelkich konfliktów scalania z rebase.

kfb
źródło
Miałem ten sam problem. Chciałem rozpocząć model rebase gałęzi (w ten sposób ). Potem zauważyłem, że popełniłem błąd: Jeśli chcesz zmienić bazę (nie powinieneś przesyłać zmian do funkcji zdalnej przed wykonaniem ponownej bazy na master) Więc zatwierdzasz kod do swojej funkcji. A teraz chcesz przesłać go do funkcji zdalnej. Zanim to zrobisz: - Powinieneś przynieść i pociągnąć swojego pana, jeśli zajdzie taka potrzeba. -Powinieneś zmienić bazę na master, jeśli nastąpiły jakieś zmiany na masterze, których nie masz w swojej funkcji. Teraz możesz uruchomić tę funkcję i nie będzie problemu.
Markus

Odpowiedzi:

185

Sprowadza się to do tego, czy funkcja jest używana przez jedną osobę, czy też inni pracują nad nią.

Możesz wymusić push po rebase, jeśli to tylko ty:

git push origin feature -f

Jeśli jednak inni nad tym pracują, należy scalić, a nie ponownie bazować na wzorcu.

git merge master
git push origin feature

Zapewni to wspólną historię z osobami, z którymi współpracujesz.

Na innym poziomie nie powinieneś wykonywać scalania wstecznego. To, co robisz, zanieczyszcza historię gałęzi funkcji innymi zatwierdzeniami, które nie należą do tej funkcji, co utrudnia późniejszą pracę z tą gałęzią - zmiana bazy lub nie.

To jest mój artykuł na temat o nazwie gałąź na funkcję .

Mam nadzieję że to pomoże.

Adam Dymitruk
źródło
29
+1 za if others are working on it, you should merge and not rebase off of master, rebase lepiej używać tylko na prywatnym oddziale.
Hendra Uzia
6
alternativ do funkcji git push origin - jeśli możesz również usunąć funkcję zdalną i ponownie wypchnąć funkcję
Markus
2
Scalenie mastera z twoją gałęzią utworzy zatwierdzenie scalające i spowoduje konflikty z każdą inną otwartą gałęzią funkcji z mastera po wprowadzeniu zmian.
Steven
+1 dla git push origin feature -f. W niektórych kontekstach może być konieczne wykonanie ponownej bazy nawet w przypadku odległych oddziałów. Istotą jest wiedzieć, co robisz. I powinniśmy przejąć, że możesz usuwać zatwierdzenia w zdalnym repozytorium.
enagra
33

Fajnie, że poruszyłeś ten temat.

Jest to ważna rzecz / koncepcja w git, o której wielu użytkowników gita skorzystałoby. git rebase to bardzo potężne narzędzie, które umożliwia zgniatanie zatwierdzeń, usuwanie zatwierdzeń itp. Ale tak jak w przypadku każdego potężnego narzędzia, po prostu musisz wiedzieć, co robisz, inaczej coś może pójść nie tak.

Kiedy pracujesz lokalnie i bawisz się z lokalnymi oddziałami, możesz robić, co chcesz, o ile nie wprowadziłeś zmian do centralnego repozytorium. Oznacza to, że możesz przepisać własną historię, ale nie historię innych. Tylko bawić się lokalnymi rzeczami, nic nie będzie miało żadnego wpływu na inne repozytoria.

Dlatego ważne jest, aby pamiętać, że po wypchnięciu zatwierdzeń nie należy ich później zmieniać. Powodem, dla którego jest to ważne, jest to, że inni ludzie mogą wciągać twoje zatwierdzenia i oprzeć swoją pracę na twoim wkładzie w bazę kodu, a jeśli później zdecydujesz się przenieść tę zawartość z jednego miejsca do drugiego (ponownie bazować) i popchnąć te zmiany, wtedy inne osoby będą miały problemy i będą musiały przebudować swój kod. Teraz wyobraź sobie, że masz 1000 programistów :) Powoduje to po prostu wiele niepotrzebnych przeróbek.

ralphtheninja
źródło
Głos za złym językiem: meta.stackexchange.com/questions/22232/…
Powers
1
Zaktualizowałem mój język.
ralphtheninja
5

Ponieważ ponownie bazowałeś featurena nowym master, twój lokalny featurenie jest już szybkim przewijaniem do przodu origin/feature. Tak więc myślę, że w tym przypadku całkowicie dobrze jest zastąpić kontrolę szybkiego przewijania do przodu, wykonując git push origin +feature. Możesz to również określić w swoim config

git config remote.origin.push +refs/heads/feature:refs/heads/feature

Jeśli inni ludzie będą pracować nad tym origin/feature, będzie im przeszkadzać ta wymuszona aktualizacja. Można tego uniknąć przez łączenie w nowym masterpod featurezamiast przebazowania. Rezultat będzie rzeczywiście szybki do przodu.

Tilman Vogel
źródło
1

Możesz wyłączyć sprawdzanie (jeśli naprawdę wiesz, co robisz), korzystając z --forceopcji git push.

Andrew Aylett
źródło
15
Problem w tym, że nie jestem pewien, czy naprawdę wiem, co robię :)
kfb
@r_: Przeczytaj moją odpowiedź. Może ci to pomóc w zrozumieniu tego, co robisz :)
ralphtheninja