Używamy git i mamy gałąź master i gałęzie deweloperskie. Muszę dodać nową funkcję, a następnie zmienić bazę zatwierdzeń na master, a następnie wypchnąć master na serwer CI.
Problem polega na tym, że jeśli mam konflikty podczas rebase, nie mogę wysłać do mojej zdalnej gałęzi programisty (na Github) po zakończeniu rebase, dopóki nie ściągnę mojej zdalnej gałęzi. Powoduje to zduplikowane zatwierdzenia. Gdy nie ma konfliktów, działa zgodnie z oczekiwaniami.
pytanie: jak zsynchronizować lokalne i zdalne gałęzie dewelopera bez tworzenia zduplikowanych zatwierdzeń po zmianie bazy i rozwiązaniu konfliktu
Ustawiać:
// master branch is the main branch
git checkout master
git checkout -b myNewFeature
// I will work on this at work and at home
git push origin myNewFeature
// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master
// we have conflicts
// solve conflict
git rebase --continue
//repeat until rebase is complete
git push origin myNewFeature
//ERROR
error: failed to push some refs to '[email protected]:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
// do what git says and pull
git pull origin myNewFeature
git push origin myNewFeature
// Now I have duplicate commits on the remote branch myNewFeature
EDYTOWAĆ
Wygląda więc na to, że przerwie to przepływ pracy:
developer1 pracujący nad myNewFeature developer2 pracujący nad hisNewFeature obaj używają mastera jako głównej gałęzi
developer2 łączy myNewFeature z hisNewFeature
developer1 ponownie bazuje, rozwiązuje konflikty, a następnie wymusza wypychanie do zdalnego oddziału dla myNewFeature
kilka dni później developer2 ponownie łączy myNewFeature z jegoNewFeature
Czy to spowoduje, że inni deweloperzy znienawidzą programistę Developer1?
we
? czy jesteś w zespole złożonym z czegoś więcej niż tylko ty?they
powiedz (ludziom, którzy wiedzą więcej niż ja), że jeśli udostępniasz swój kod, nie powinieneś go używaćrebase
. Dlaczego po prostu nie robiszgit pull
igit merge
?force
nacisk)rewriting history
, to jestrebase
Odpowiedzi:
Po pierwsze, ty i ci, z którymi pracujesz, musicie ustalić, czy gałąź tematyczna / rozwojowa jest przeznaczona do wspólnego rozwoju, czy tylko do twojego. Inni programiści wiedzą, że nie powinni łączyć się w moich gałęziach programistycznych, ponieważ w dowolnym momencie zostaną ponownie utworzeni. Zwykle przepływ pracy wygląda następująco:
Następnie, aby być na bieżąco z pilotem, wykonam następujące czynności:
Robię to z dwóch powodów. Po pierwsze, ponieważ pozwala mi sprawdzić, czy są zdalne zmiany bez konieczności przełączania się z mojej gałęzi rozwojowej. Po drugie, jest to mechanizm bezpieczeństwa, który zapewnia, że nie nadpisuję żadnych niezachowanych / zatwierdzonych zmian. Ponadto, jeśli nie mogę szybko połączyć się z główną gałęzią, oznacza to, że ktoś zmienił bazę zdalnego mastera (za co musi zostać poważnie chłostany) lub przypadkowo zdecydowałem się na master i muszę wyczyścić mój koniec.
Następnie, gdy pilot ma zmiany i przewinęłam do najnowszego, ponownie bazuję:
Inni programiści wiedzą wtedy, że będą musieli przebudować swoje gałęzie deweloperskie na moje najnowsze:
Co skutkuje dużo czystszą historią:
Nie łącz zobowiązań w tę iz powrotem według własnego uznania. Nie tylko tworzy duplikaty zatwierdzeń i uniemożliwia śledzenie historii, ale znalezienie regresji z określonej zmiany staje się prawie niemożliwe (dlatego właśnie używasz kontroli wersji w pierwszej kolejności, prawda?). Problem, który masz, jest wynikiem zrobienia tego.
Wygląda też na to, że inni programiści mogą wprowadzać zmiany do twoich gałęzi deweloperskich. Czy możesz to potwierdzić?
Scalanie odbywa się tylko wtedy, gdy gałąź tematyczna jest gotowa do zaakceptowania
master
.Na marginesie. Jeśli wielu programistów zatwierdza to samo repozytorium, wszyscy powinniście rozważyć nazwane gałęzie, aby rozróżnić gałęzie deweloperskie. Na przykład:
Zatem wszystkie gałęzie tematów deweloperów znajdują się we własnym zagnieżdżonym zestawie.
źródło
--force
flagi, kiedy to robiszgit push -f origin devel0
?git push
nie można przewinąć do przodu (np. Historia sha się nie zgadza), musisz wymusić wypychanie, aby nadpisać poprzednią historię nową historią wygenerowaną z plikugit rebase
.Musisz wymusić push, ponieważ przesuwałeś zatwierdzenia dalej w dół wiersza, którego git oczekuje, że dodasz zatwierdzenia na końcu gałęzi.
git push -f origin myNewFeature
rozwiąże twój problem.Wskazówka: Powyższe to uzasadnione użycie siły. Nigdy, przenigdy nie przepisuj historii w publicznie dostępnym repozytorium, bo wiele osób cię nienawidzi.
źródło
git push --force-with-lease
jest znacznie bezpieczniejsze niż używaniegit push --force
git push --force-with-lease origin HEAD
- zakładając, że Twoja docelowa gałąź jest już--force-with-lease
?Najważniejszą rzeczą, o której należy pamiętać, jest to, co pull i rebase robią za kulisami.
Wyciąganie zasadniczo robi dwie rzeczy: pobieranie i scalanie. Gdy włączysz --rebase, zamiast scalania wykona rebase.
Ponowna baza jest prawie jak przechowywanie wszystkich lokalnych zmian od momentu rozgałęzienia, szybkie przekazywanie gałęzi do ostatniego zatwierdzenia celu i usuwanie zmian w kolejności na górze.
(To wyjaśnia, dlaczego możesz otrzymać wiele monitów o rozwiązanie konfliktu podczas wykonywania rebase w porównaniu z jednym rozwiązaniem konfliktu, które możesz uzyskać przy scalaniu. Masz możliwość rozwiązania konfliktu na KAŻDYM zatwierdzeniu, które jest zmieniane, aby w inny sposób zachować swoje zatwierdzenia. )
Nigdy nie chcesz wypychać zmian opartych na rebase do zdalnych gałęzi, ponieważ jest to przepisywanie historii. Z grubsza, nigdy nie jest zbyt mocny, ponieważ prawie zawsze są wyjątki. Sytuacja, w której musisz utrzymywać zdalną wersję lokalnego repozytorium, aby na przykład pracować w określonym środowisku.
Będzie to wymagało czasami wprowadzania zmian opartych na rebase za pomocą siły:
W niektórych przypadkach administrator mógł usunąć możliwość wymuszenia, więc musisz usunąć i odtworzyć:
W każdym przypadku musisz mieć absolutną pewność, że wiesz, co robisz, jeśli ktoś inny współpracuje z tobą w zdalnym oddziale. Może to oznaczać, że na początku pracujesz razem ze scaleniami i przebudowujesz je na łatwiejszy w zarządzaniu format zatwierdzania tuż przed przejściem do mastera i usunięciem gałęzi roboczej.
Pamiętaj, że prawie zawsze możesz wrócić do GC git, korzystając z:
Jest to OGROMNA ochrona życia, ponieważ możesz zresetować z powrotem do bardziej stabilnego stanu, jeśli zgubisz się w całym zarządzaniu rebase / konfliktami.
źródło
Musisz wykonać wymuszony pchnięcie, tj
git push -f origin myNewFeature
Aha, i lepiej upewnij się, że ludzie nie opierają niczego na twojej gałęzi deweloperskiej - zwykle nie powinieneś publikować gałęzi, w których w ogóle przepisujesz historię (lub raczej nie przepisujesz historii po opublikowaniu). Jednym ze sposobów byłoby użycie nazwy gałęzi, takiej jak,
wip/myNewFeature
a następnie wspomnienie, żewip
gałęzie będą od czasu do czasu przebudowywane na master.źródło
git push --force-with-lease
jest znacznie bezpieczniejsze niż używaniegit push --force
-f
w przypadku normalnego wymuszonego pchnięcia :)Ogólna odpowiedź, która już została udzielona - do wykorzystania
git push -f origin myNewFeature
przy wprowadzaniu zmian opartych na rebase - jest dobrym punktem wyjścia. Piszę tę odpowiedź, aby zająć się edycją o tym, czy przerwie ona twój przepływ pracy.Jeśli założymy, że masz zamiar używać
git pull --rebase ...
(lub pewne różnice na tym), a następnie przez siły-push do odległego oddziału, potem coś, co łamie workflow w przykładzie developer2 zlewamyNewFeature
sięhisNewFeature
. Przebudowa własnej gałęzi funkcji ma sens, o ile nikt inny nie pracuje nad tą gałęzią, więc potrzebujesz reguł wyznaczających terytorium gałęzi.Możesz to obejść, a) ustanawiając regułę, z której tylko się łączysz
master
, lub b) tworząc kolektywnądevelop
gałąź, na której opierasz swoją własnąmyNewFeature
gałąź i ustanawiając regułę, z której tylko łączysz siędevelop
.master
będzie wtedy zarezerwowana tylko dla kamieni milowych lub wydań (lub jakkolwiek chcesz to skonfigurować) idevelop
będzie tam, gdzie będziesz wypychać każdą funkcję, gdy będzie gotowa do zintegrowania z innymi gałęziami funkcji.Uważam, że można to uznać za uproszczoną wersję przepływu pracy Gitflow.
źródło
Zgadzam się z MrCholo i może Trevor Norris mógłby rozważyć aktualizację jego dobrej odpowiedzi, aby zastąpić
z
źródło