Jaki jest najlepszy (i najbezpieczniejszy) sposób połączenia gałęzi Git w master?


2101

Utworzono nowy oddział z master, nazywamy go test.

Istnieje kilku programistów, którzy albo zobowiązują się, masteralbo tworzą inne gałęzie, a następnie łączą się z nimi master.

Załóżmy, że praca testtrwa kilka dni i chcesz być na testbieżąco z zatwierdzeniami w środku master.

Zrobiłbym git pull origin masterz test.

Pytanie 1: Czy to właściwe podejście? Inni programiści mogliby z łatwością pracować na tych samych plikach, co ja btw.


Moja praca testjest zakończona i jestem gotowy, aby połączyć ją z powrotem master. Oto dwa sposoby, o których mogę myśleć:

ZA:

git checkout test
git pull origin master
git push origin test
git checkout master
git pull origin test 

B:

git checkout test
git pull origin master
git checkout master
git merge test

Nie używam, --rebaseponieważ z mojego zrozumienia, rebase pobierze zmiany masteri ułoży moje na wierzchu, dzięki czemu może zastąpić zmiany dokonane przez innych ludzi.

Pytanie 2: Która z tych dwóch metod jest odpowiednia? Jaka jest tam różnica?

Wszystko to ma na celu informowanie mojej testgałęzi o bieżących wydarzeniach, mastera później mógłbym połączyć je z powrotem w masternadziei, że oś czasu będzie możliwie jak najbardziej liniowa.


18
nie ... rebase nigdy nie zastępuje, po prostu stara się osiągnąć czystszą historię. przez ponowne dołączenie (lub sfałszowanie) historii do późnego punktu mistrza
Junchen Liu

7
rebase nie nadpisuje twoich zobowiązań. Cofa zatwierdzenia, stosuje zatwierdzenia w gałęzi master do gałęzi testowej, a następnie ponownie wprowadza zatwierdzenia do testowania.
zundi

Odpowiedzi:


2991

Jak bym to zrobił

git checkout master
git pull origin master
git merge test
git push origin master

Jeśli mam oddział lokalny ze zdalnego, nie czuję się dobrze z połączeniem innych oddziałów niż ten ze zdalnym. Nie będę też naciskał na moje zmiany, dopóki nie będę zadowolony z tego, co chcę naciskać, a także nie będę w ogóle naciskał na rzeczy, które są tylko dla mnie i mojego lokalnego repozytorium. W twoim opisie wydaje się, że testto tylko dla ciebie? Więc nie ma powodu, aby go opublikować.

git zawsze stara się szanować twoje i inne zmiany, i tak też będzie --rebase. Nie sądzę, że potrafię to odpowiednio wytłumaczyć, więc spójrz na książkę Git - Rebasing lub gotowa na git: wprowadzenie do rebasingu dla krótkiego opisu. To całkiem fajna funkcja


2
git merge testdaje mi fatal: 'test' does not point to a commit. Muszę poszukać git logpunktu zatwierdzenia na gałęzi testowej, przełączyć się z powrotem na gałąź master, a następnie zrobić git merge 0f37d3154abbf52a4cbbbb5109f08af6a7567234.
Duncanmoo,

17
@Duncanmoo Cóż, oczywiście gałąź testmusi istnieć. Oczywiście możesz zamiast tego użyć skrótu zatwierdzenia, ale zwykle łatwiej jest użyć nazwy gałęzi. Wewnętrznie po prostu pobiera skrót HEADgałęzi.
KingCrunch,

44
@shanyangqu Aby uzyskać najnowsze zmiany z pilota. Jeśli pracujesz sam i tylko z jednym systemem, nie ma problemu. Ale kiedy zostaną wprowadzone zmiany z innego systemu (prawdopodobnie od innego programisty), zobaczysz konflikt, gdy tylko spróbujesz odepchnąć scalenie z powrotem (czwarty krok). Jedynym rozwiązaniem jest teraz połączenie twojego lokalnego mistrza z pilotem zdalnego, co kończy się dość brzydkim „scalonym masterem w origin / master”. Dlatego zawsze dobrym pomysłem jest zrobienie tego przed połączeniem
KingCrunch

7
„W twoim opisie wydaje się, że ten test jest tylko dla ciebie? Więc nie ma powodu, aby go opublikować.” Możesz zepchnąć swój oddział lokalny na serwer, jeśli na przykład serwer ten zapewnia kopię zapasową w przypadku awarii dysku lokalnego lub jeśli nie masz innego sposobu na wykonanie kopii zapasowej.
Eric

5
„... Nie wprowadzałbym też moich zmian, dopóki nie będę zadowolony z tego, co chcę wypchnąć ...”, dlaczego nie naciskać ze względu na kopię zapasową kodu, na wypadek gdyby Twoje maszyny lokalne zginęły i dni wysiłku znikły?
Rich Stone

400

To bardzo praktyczne pytanie, ale wszystkie powyższe odpowiedzi nie są praktyczne.

Lubić

git checkout master
git pull origin master
git merge test
git push origin master

Podejście to ma dwa problemy :

  1. Jest to niebezpieczne, ponieważ nie wiemy, czy występują jakiekolwiek konflikty między gałęzią testową a gałęzią główną.

  2. Spowodowałoby to „ściśnięcie” wszystkich zatwierdzeń testowych w jednym zatwierdzeniu scalania na wzorcu; to znaczy w gałęzi master, nie widzimy wszystkich dzienników zmian gałęzi testowej.

Kiedy więc podejrzewamy, że wystąpią jakieś konflikty, możemy wykonać następujące operacje git:

git checkout test
git pull 
git checkout master
git pull
git merge --no-ff --no-commit test

Testuj mergewcześniej commit, unikaj zatwierdzania szybkiego przewijania do przodu --no-ff,

Jeśli wystąpi konflikt, możemy uruchomić, git statusaby sprawdzić szczegóły dotyczące konfliktów i spróbować je rozwiązać

git status

Kiedy rozwiążemy konflikty lub jeśli nie będzie konfliktu, my commiti pushoni

git commit -m 'merge test branch'
git push

Ale w ten sposób utracona zostanie historia zmian zalogowana w gałęzi testowej i utrudniłoby to gałęzi master zrozumienie historii projektu przez innych programistów.

Najlepszą metodą jest, aby rebasezamiast tego zastosować merge(załóżmy, że w tym czasie rozwiązaliśmy konflikty gałęzi).

Poniżej znajduje się jeden prosty przykład, dla zaawansowanych operacji, patrz http://git-scm.com/book/en/v2/Git-Branching-Rebasing

git checkout master
git pull
git checkout test
git pull
git rebase -i master
git checkout master
git merge test

Tak, kiedy skończysz cholewkę, wszystkie zatwierdzenia gałęzi Test zostaną przeniesione na głowę gałęzi Master. Główną zaletą bazowania jest to, że otrzymujesz liniową i znacznie czystszą historię projektu.

Jedyne, czego musisz unikać: nigdy nie używaj rebasew oddziale publicznym, takim jak oddział główny.

Nigdy nie wykonuj takich operacji jak:

git checkout master
git rebase -i test

Szczegóły dotyczące https://www.atlassian.com/git/tutorials/merging-vs-rebasing/the-golden-rule-of-rebasing

dodatek:


4
Zgadzam się na zmianę gałęzi testowej w celu późniejszego scalenia z masterem. Nawet inne odpowiedzi są poprawne, to zachowa historię zmian testu gałęzi w głowie mistrza, ponieważ autor wspomina „masz linijkę i znacznie czystszy projekt”, co jest celem systemu kontroli wersji.
le0diaz

16
Stwierdzenie „nie jest to jedna droga bezpieczeństwa, ponieważ nie wiemy, czy występują jakiekolwiek konflikty między gałęzią testową a gałęzią główną” nie jest prawdą: zawsze można przerwać scalanie. I nawet jeśli nie ma konfliktów, zawsze możesz cofnąć ostatnie zatwierdzenie lokalne, o ile nie zostanie ono wypchnięte. Bez prawidłowego zrozumienia git niektóre rzeczy mogą wydawać się nieco przerażające lub niejasne, ale „niebezpieczne” jest po prostu w jakikolwiek sposób nieprawidłowe. Uważaj, aby nie pomylić innych z niepoprawnymi informacjami.
Paul van Leeuwen,

4
Zgadzam się z @PaulvanLeeuwen, kiedy git scalić oddział testowy do opanowania, użytkownik zostanie powiadomiony o konfliktach, i ów, gdzie można wkroczyć i scalić zmiany. Po zakończeniu dokonaj scalenia i odepchnij. Jeśli żałujesz lub nie możesz poprawnie połączyć, zawsze możesz odrzucić swoją pracę i ponownie odciągnąć od mistrza. Więc to zdecydowanie nie jest niebezpieczne ...
Juan

3
dlaczego rebase -i?
MushyPeas

8
Rebasing jest z natury bardziej niebezpieczny niż scalanie. Błędem jest proponowanie zmiany bazy jako bezpieczniejszej opcji łączenia. Rebasing jest prawidłową strategią, ale zawiera więcej ostrzeżeń, których użytkownik powinien się wystrzegać.
Ikke

90

Ani rebase, ani scalanie nie powinny nadpisywać niczyich zmian (chyba że zdecydujesz się to zrobić podczas rozwiązywania konfliktu).

Zwykłe podejście podczas opracowywania to

git checkout master
git pull
git checkout test
git log master.. # if you're curious
git merge origin/test # to update your local test from the fetch in the pull earlier

Kiedy będziesz gotowy ponownie połączyć się z mistrzem,

git checkout master
git log ..test # if you're curious
git merge test
git push

Jeśli martwisz się zerwaniem czegoś podczas scalania, git merge --abortjest do Twojej dyspozycji.

Używanie push, a następnie pull jako sposobu łączenia jest głupie. Nie jestem również pewien, dlaczego przesuwasz test do pochodzenia.


1
Ten proces zwiększy liczbę zatwierdzeń, za każdym razem, gdy przełączasz się między oddziałami, musisz zatwierdzić swój oddział.
iBug

2
Co? Czy mówisz, że zwiększy liczbę zatwierdzeń za każdym razem, gdy zmieniasz oddziały? A może mówisz, że za każdym razem, gdy zmieniasz oddziały, musisz „zatwierdzić swój oddział”? Pierwszy jest nieprawdziwy i nie jestem pewien, co oznacza drugi.
raylu

przed kasą musisz zatwierdzić oddział. tak mówię
iBug

11
Ty nie: to jest (jedna z rzeczy) po git stashto.
msanford,

1
Możesz też poprawić swój ostatni zatwierdzenie (w lokalnym oddziale) i uczynić go idealnym przed wypchnięciem.
whihathac,

42

Najpierw uczynię gałąź, która ma zostać połączona, tak czystą, jak to możliwe. Uruchom testy, upewnij się, że stan jest taki, jak chcesz. Oczyść nowe zatwierdzenia przez git squash .

Oprócz odpowiedzi KingCrunches , sugeruję użyć

git checkout master
git pull origin master
git merge --squash test
git commit
git push origin master

Być może dokonałeś wielu zmian w drugiej gałęzi, która powinna być tylko jedną zmianą w gałęzi głównej. Aby zachować historię zatwierdzeń tak czystą, jak to możliwe, możesz chcieć zgnieść wszystkie swoje zatwierdzenia z gałęzi testowej do jednego zatwierdzenia w gałęzi głównej (zobacz także: Git: Zgnieść czy nie zgnieść? ). Następnie możesz również przepisać komunikat zatwierdzenia na coś bardzo ekspresyjnego. Coś, co jest łatwe do odczytania i zrozumienia, bez zagłębiania się w kod.

edytuj: Możesz być zainteresowany

Tak więc na GitHub kończę w następujący sposób dla gałęzi funkcji mybranch:

Otrzymuj najnowsze informacje o pochodzeniu

$ git checkout master
$ git pull origin master

Znajdź skrót bazowy scalania:

$ git merge-base mybranch master
c193ea5e11f5699ae1f58b5b7029d1097395196f

$ git checkout mybranch
$ git rebase -i c193ea5e11f5699ae1f58b5b7029d1097395196f

Teraz upewnij się, że tylko pierwsza jest pick, reszta to s:

pick 00f1e76 Add first draft of the Pflichtenheft
s d1c84b6 Update to two class problem
s 7486cd8 Explain steps better

Następnie wybierz bardzo dobry komunikat zatwierdzenia i prześlij na GitHub. Złóż wniosek ściągania.

Po scaleniu żądania ściągnięcia możesz je usunąć lokalnie:

$ git branch -d mybranch

i na GitHub

$ git push origin :mybranch

który powinien być tylko jednym zatwierdzeniem w gałęzi master ”, niekoniecznie; możesz chcieć zachować historię
Cocowalla

Pewnie. Ale potem nie marnujcie zobowiązań
Martin Thoma,

Myślę, że - pierwszy rodzic wydaje się najlepszym rozwiązaniem. davidchudzicki.com/posts/first-parent
bkribbs

7

Stary wątek, ale nie znalazłem sposobu na zrobienie tego. Może to być cenne dla kogoś, kto pracuje z rebase i chce połączyć wszystkie zatwierdzenia z gałęzi (funkcji) na master. Jeśli na drodze jest konflikt, możesz go rozwiązać dla każdego zatwierdzenia. Zachowujesz pełną kontrolę podczas procesu i możesz przerwać w dowolnym momencie.

Otrzymuj aktualne informacje o Master i Branch:

git checkout master
git pull --rebase origin master
git checkout <branch_name>
git pull --rebase origin <branch_name>

Scal gałąź na Master:

git checkout <branch_name>
git rebase master

Opcjonalne: Jeśli podczas Rebase napotkasz Konflikty:

Najpierw rozwiąż konflikt w pliku. Następnie:

git add .
git rebase --continue

Wciśnij swój rebased oddział:

git push origin <branch_name>

Teraz masz dwie opcje:

  • A) Utwórz PR (np. Na GitHub) i połącz go tam za pomocą interfejsu użytkownika
  • B) Wróć do wiersza poleceń i połącz gałąź w master
git checkout master
git merge --no-ff <branch_name>
git push origin master

Gotowy.


6

Jest to przepływ pracy, którego używam w pracy w zespole. Scenariusz jest taki, jak opisano. Po pierwsze, kiedy skończę pracę test, dokonuję zmian w bazie danych z master, aby pobrać wszystko, co zostało dodane do master w czasie, gdy pracowałem nad testgałęzią.

git pull -r upstream master

Spowoduje to wyciągnięcie zmian do wzorca, ponieważ rozwidliłeś testgałąź i zastosujesz je, a następnie zastosujesz wprowadzone zmiany, aby przetestować „nad” bieżącym stanem wzorca. Mogą występować konflikty, jeśli inne osoby wprowadziły zmiany do tych samych plików, które edytowałeś w teście. Jeśli tak, musisz je naprawić ręcznie i zatwierdzić. Gdy to zrobisz, będziesz mógł przejść do gałęzi master i połączyć testsię bez problemów.


3
git checkout master
git pull origin master
# Merge branch test into master
git merge test

Po scaleniu, jeśli plik zostanie zmieniony, to po scaleniu wystąpi błąd „Rozwiąż konflikt”

Więc najpierw musisz rozwiązać wszystkie swoje konflikty, a następnie ponownie zatwierdzić wszystkie zmiany, a następnie pchnąć

git push origin master

Lepiej to zrobić, kto dokonał zmian w gałęzi testowej, ponieważ wiedział, jakie zmiany dokonał.


3

Użyłbym metody rebase. Głównie dlatego, że doskonale odzwierciedla twój przypadek semantycznie, tj. co chcesz zrobić, to odświeżyć stan twojego obecnego oddziału i „udawać”, jakby był oparty na najnowszym.

Tak więc, nawet nie sprawdzając master, chciałbym:

git fetch origin
git rebase -i origin/master
# ...solve possible conflicts here

Oczywiście samo pobieranie z miejsca początkowego nie odświeża lokalnego stanu twojego master(ponieważ nie wykonuje scalania), ale jest to całkowicie w porządku dla naszego celu - chcemy uniknąć przełączania się ze względu na oszczędność czasu.


2

@ Odpowiedź KingCruncha powinna działać w wielu przypadkach. Jednym z problemów, które mogą się pojawić, jest to, że możesz być na innym komputerze, który musi pobrać najnowszą wersję z testu. Więc najpierw polecam test ciągnący. Wersja wygląda następująco:

git checkout test
git pull
git checkout master
git pull origin master
git merge test
git push origin master

0

Musisz pobrać gałąź do pobrania, ponieważ ciągnięcie oznacza scalenie się w master i potrzebujesz drzewa pracy, aby się połączyć.

git checkout master
git pull

Nie musisz najpierw sprawdzać; rebase robi właściwą rzecz z dwoma argumentami

git rebase master test  

git checkout master
git merge test

git push domyślnie wypycha wszystkie gałęzie, które istnieją tutaj i na pilocie

git push
git checkout test

0

Jak mówi tytuł „Najlepszy sposób”, myślę, że warto rozważyć strategię łączenia cierpliwości .

Od: https://git-scm.com/docs/merge-strategies

Dzięki tej opcji „scalanie-rekurencyjne” poświęca trochę więcej czasu, aby uniknąć rozbieżności, które czasami występują z powodu nieistotnych pasujących linii (np. Nawiasy klamrowe z różnych funkcji). Użyj tego, gdy gałęzie, które mają zostać scalone, rozeszły się gwałtownie. Zobacz także git-diff [1] --patience.

Stosowanie:

git fetch
git merge -s recursive -X patience origin/master

Alias ​​Git

Zawsze używam do tego aliasu, np. Uruchamiam raz:

 git config --global alias.pmerge 'merge -s recursive -X patience'

Teraz możesz zrobić:

git fetch
git pmerge origin/master


0

Odpowiem według gałęzi deweloperskich i fabularnych,

jeśli jesteś w gałęzi funkcji i chcesz ją zaktualizować za pomocą rozwijania użyj poniższych poleceń: git checkout rozwijaj git pull git Checkout feature / xyz git merge develop

Teraz Twoja funkcja została zaktualizowana o programowanie, dzięki czemu możesz wprowadzać zmiany.

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.