Close

git merge

Scalanie w Git umożliwia ponowne połączenie podzielonej historii. Polecenie git merge pozwala zebrać niezależne linie prac programistycznych utworzone za pomocą polecenia git branch i zintegrować je w pojedynczą gałąź.

Należy zwrócić uwagę, że wszystkie przedstawione poniżej polecenia powodują scalenie z bieżącą gałęzią. Bieżąca gałąź zostanie zaktualizowana, aby odzwierciedlić operację scalenia, ale gałąź docelowa pozostanie całkowicie nienaruszona. Oznacza to, że polecenie git merge jest często stosowane w połączeniu z poleceniem git checkout, które pozwala wybrać bieżącą gałąź, oraz poleceniem git branch -d, które umożliwia usunięcie przestarzałej gałęzi docelowej.


Jak to działa


Polecenie git merge powoduje połączenie wielu sekwencji commitów w pojedynczą ujednoliconą historię. Najczęściej polecenie git merge wykorzystuje się do łączenia dwóch gałęzi. Przykłady przedstawione w dalszej części niniejszego dokumentu koncentrują się na tym wzorcu scalania gałęzi. W tych scenariuszach polecenie git merge wykorzystuje dwa wskaźniki commitów, zazwyczaj końcówki gałęzi, i wyszukuje ich wspólny commit bazowy. Gdy Git znajdzie wspólny commit bazowy, utworzy nowy „commit scalenia”, który obejmuje połączone zmiany z poszczególnych dodanych do kolejki sekwencji commitów scalenia.

Załóżmy, że mamy gałąź nowej funkcji wychodzącą z gałęzi main. Teraz chcemy scalić tę gałąź funkcji z gałęzią main.

Scalanie gałęzi feature z gałęzią main
Okno konsoli
materiały pokrewne

Zaawansowany dziennik Git

Logo Bitbucket
POZNAJ ROZWIĄZANIE

Poznaj środowisko Git z rozwiązaniem Bitbucket Cloud

Wywołanie tego polecenia spowoduje scalenie wskazanej gałęzi funkcji z bieżącą gałęzią, którą w założeniu jest gałąź main. Git określi algorytm scalania automatycznie (to zagadnienie omówiono poniżej).

Nowy węzeł commita scalenia

Commity scalenia różnią się od innych commitów tym, że mają dwa commity nadrzędne. Podczas tworzenia commita scalenia Git spróbuje w automatycznie magiczny sposób scalić dla Ciebie odrębne historie. Jeśli napotka fragment danych, który został zmieniony w obu historiach, nie będzie w stanie połączyć ich automatycznie. Taki scenariusz oznacza konflikt kontroli wersji i kontynuowanie procesu w Git będzie wymagać interwencji ze strony użytkownika.

Przygotowanie do scalenia


Aby scalenie przebiegło bez problemów, przed rozpoczęciem należy wykonać kilka kroków przygotowawczych.

Potwierdzanie gałęzi odbiorczej


Wykonaj polecenie git status, aby się upewnić, że wskaźnik HEAD wskazuje prawidłową gałąź odbiorczą operacji scalania. W razie potrzeby wykonaj polecenie git checkout , aby przełączyć się na gałąź odbiorczą. W naszym przypadku będzie to polecenie git checkout main.

Pobieranie najnowszych commitów zdalnych


Upewnij się, że gałąź odbiorcza i scalana zostały zaktualizowane o najnowsze zmiany zdalne. Wykonaj polecenie git fetch, aby pobrać najnowsze zdalne commity. Po zakończeniu pobierania upewnij się, że gałąź main zawiera najnowsze aktualizacje, wykonując polecenie git pull.

Scalanie


Po wykonaniu opisanych wcześniej kroków w ramach „przygotowania do scalenia” można zainicjować scalanie, wykonując polecenie git merge , w którym fragment oznacza nazwę gałęzi, która zostanie scalona z gałęzią odbiorczą.

Scalanie z przewijaniem


Scalanie z przewijaniem może wystąpić, gdy między końcówką bieżącej gałęzi a gałęzią docelową istnieje ścieżka liniowa. Zamiast „faktycznego” scalenia gałęzi, Git po prostu integruje historie, przenosząc (lub inaczej „przewijając”) końcówkę bieżącej gałęzi do końcówki gałęzi docelowej. W ten sposób można skutecznie połączyć historie, ponieważ wszystkie commity osiągalne z poziomu gałęzi docelowej są teraz dostępne za pośrednictwem gałęzi bieżącej. Przykładowo scalenie z przewijaniem gałęzi jakiejś funkcji „some-feature” z gałęzią main będzie wyglądało mniej więcej następująco:

Węzeł funkcji wyprzedza węzeł główny, a po scaleniu z przewijaniem obydwie gałęzie znajdują się na poziomie tego samego węzła

Scalanie z przewijaniem nie jest jednak możliwe, jeśli gałęzie zostały rozdzielone. Jeśli nie ma ścieżki liniowej wiodącej do gałęzi docelowej, Git nie ma innego wyboru, jak połączyć gałęzie w wyniku scalania trójstronnego. W scalaniu trójstronnym łączy się ze sobą dwie historie za pomocą specjalnego commita. Przyjęta nazwa wynika z faktu, że Git generuje commit scalenia na podstawie trzech commitów: dwóch końcówek gałęzi i ich wspólnego elementu nadrzędnego.

Schemat po scalaniu trójstronnym

Pomimo możliwości użycia dowolnej z tych strategii scalania, wielu programistów woli używać scalenia fast-forward (które ułatwia operacja zmiany bazy) w przypadku niewielkich funkcji lub poprawek błędów, zachowując scalenia trójstronne na potrzeby integracji funkcji, nad którymi prace trwają dłużej. W tym drugim przypadku wynikowy commit scalenia pełni funkcję symbolicznego połączenia dwóch gałęzi.

Nasz pierwszy przykład ilustruje scalanie z przewijaniem. Poniższy kod tworzy nową gałąź, dodaje do niej dwa commity, a następnie integruje ją z linią główną za pomocą operacji scalania z przewijaniem.

# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature

Jest to przepływ pracy stosowany powszechnie w odniesieniu do krótkich gałęzi tematycznych, które są wykorzystywane raczej do prowadzenia odizolowanych prac programistycznych niż jako narzędzie organizacyjne dla dłużej rozwijanych funkcji.

Należy również pamiętać, że Git nie powinien zwracać błędów w odpowiedzi na polecenie git branch -d, ponieważ nowa funkcja „new-feature” jest teraz dostępna z poziomu głównej gałęzi.

Jeśli podczas scalania z przewijaniem jest wymagane utworzenie commita scalenia dla celów ewidencyjnych, można użyć polecenia git merge z opcją --no-ff.

git merge --no-ff <branch>

To polecenie powoduje scalenie konkretnej gałęzi z gałęzią bieżącą, ale zawsze generuje commit scalenia (nawet w przypadku scalania z przewijaniem). Jest to przydatny sposób dokumentowania wszystkich scaleń występujących w repozytorium.

Scalanie trójstronne


Kolejny przykład jest bardzo podobny, ale wymaga scalania trójstronnego, ponieważ gałąź main jest rozwijana, gdy prace nad funkcją są w toku. Jest to typowy scenariusz w przypadku dużych funkcji lub w sytuacji, gdy kilku programistów pracuje nad projektem jednocześnie.

Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature

Należy zwrócić uwagę, że Git nie jest w stanie wykonać scalania z przewijaniem, ponieważ nie da się przenieść gałęzi main w górę do gałęzi new-feature bez cofania (backtracking).

W przypadku większości przepływów pracy gałąź new-feature byłaby znacznie większą funkcją, której opracowanie trwałoby dłuższy czas, i dlatego w międzyczasie w gałęzi main pojawiłyby się commity. Gdyby gałąź funkcji faktycznie była tak mała, jak w powyższym przykładzie, prawdopodobnie lepszym rozwiązaniem byłoby połączenie jej z gałęzią main za pomocą operacji zmiany bazy, a następnie wykonanie scalania z przewijaniem. Pozwoliłoby to uniknąć zaśmiecania historii projektu niepotrzebnymi commitami scalenia.

Rozwiązywanie konfliktu


Jeśli w dwóch gałęziach, które próbujesz scalić, zmieniono tę samą część tego samego pliku, Git nie będzie w stanie określić, której wersji powinien użyć. W takim przypadku zatrzyma operację tuż przed commitem scalenia, umożliwiając ręczne rozwiązanie konfliktów.

Fantastyczną cechą procesu scalania w Git jest stosowanie znanego przepływu pracy opartego na schemacie edycja / umieszczenie w przechowalni / zatwierdzenie do rozwiązywania konfliktów scalania. W razie napotkania konfliktu scalania wykonanie polecenia git status pozwoli wyświetlić pliki wymagające rozwiązania. Przykładowo, jeśli w obydwu gałęziach zmodyfikowano tę samą sekcję hello.py,wyświetlony komunikat powinien być zbliżony do następującego:

On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py

Sposób przedstawiania konfliktów


Jeśli Git napotka konflikt w trakcie scalania, przejdzie do edycji zawartości problematycznych plików, stosując wskaźniki wizualne do oznaczenia sprzecznej zawartości po obu stronach. Znaczniki wizualne są następujące: <<<<<<<, ======= i >>>>>>>. W trakcie scalania dobrze jest wyszukać te wskaźniki w projekcie, aby sprawdzić, gdzie występują konflikty wymagające rozwiązania.

here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;

Zasadniczo zawartość poprzedzająca znacznik ======= pochodzi z gałęzi odbiorczej, a zawartość następująca po tym znaczniku — z gałęzi scalanej.

Po zidentyfikowaniu powodujących konflikt sekcji można do nich przejść i naprawić scalenie według własnego uznania. Gdy wszystko będzie gotowe do zakończenia scalania, wystarczy uruchomić polecenie git add na plikach, w których wystąpił konflikt, aby poinformować Git, że problem został rozwiązany. Następnie należy uruchomić standardowe polecenie git commit, aby wygenerować commit scalenia. To dokładnie ta sama procedura, którą wykonuje się w trakcie zatwierdzania zwykłych migawek, co oznacza, że zwykli programiści mogą z łatwością zarządzać własnymi scaleniami.

Należy pamiętać, że konflikty scalania będą występowały wyłącznie w przypadku scalania trójstronnego. Sprzeczne zmiany nie pojawiają się w przypadku scalania z przewijaniem.

Podsumowanie


Ten dokument zawiera omówienie polecenia git merge. Scalanie jest podstawowym procesem stosowanym podczas pracy w Git. Opisano mechanikę wewnętrzną leżącą u podstaw scalenia oraz różnice między scalaniem fast-forward i prawdziwym scalaniem trójstronnym. Najważniejsze wnioski:

1. Scalanie w Git polega na łączeniu sekwencji commitów w pojedynczą, ujednoliconą historię commitów.

2. W Git istnieją dwa główne sposoby scalania: fast-forward i trójstronne.

3. Git scala commity automatycznie, chyba że w obydwu sekwencjach commitów występują sprzeczne zmiany.

W tym dokumencie uwzględniono, bezpośrednio lub przez odwołanie, także inne polecenia Git, takie jak: git branch, git pull i git fetch. Więcej informacji na ich temat można znaleźć na poświęconych im osobnych stronach.


Udostępnij ten artykuł
Następny temat

Zalecane lektury

Dodaj te zasoby do zakładek, aby dowiedzieć się więcej na temat rodzajów zespołów DevOps lub otrzymywać aktualności na temat metodyki DevOps w Atlassian.

Ludzie współpracujący przy ścianie pełnej narzędzi

Blog Bitbucket

Ilustracja DevOps

Ścieżka szkoleniowa DevOps

Demonstracje funkcji z ekspertami Atlassian

Zobacz, jak Bitbucket Cloud współpracuje z Atlassian Open DevOps

Zapisz się do newslettera DevOps

Thank you for signing up