Wtajemniczeni programiści doskonalne rozumieją co kryje się pod pojęciem Git. Niemniej zawsze można o czymś zapomnieć lub
stracić pewność, czy podstawy które kiedyś poznaliśmy, zostały przez nas dobrze zrozumiane. Właśnie dlatego stworzyliśmy sekcję Pierwsze kroki.
Na początek proponujemy kilka słów wstępu dla początkujących, a następnie przejdziemy do najważniejszych pojęć związanych z Gitem.
Kurs Git dla początkujących
Kod większości projektów informatycznych tworzony jest przez wieloosobową grupę programistów.
To sprawia, że w tym samym czasie, na różnych komputerach dochodzi do zmian w plikach projektu.
Bardzo często równolegle zmieniany może być ten sam plik.
Mamy na przykład klasę
Item, w której jeden programista dodaje metodę
getName, a drugi programista usuwa metodę
getAlias.
Po dokonaniu zmian programiści wrzucają (innymi słowy, komitują) swoje wersje klas do jednego (wspólnego) miejsca, w którym
kod ten jest przechowywany. Miejsce to nazywamy
repozytorium.
Biorąc pod uwagę fakt, że wszystkie zmiany muszą być poprawnie zapisane, potrzebny jest nam system zarządzania takimi zmianami.
W tym celu stworzone zostały
systemy kontroli wersji. Nadzorują one zmiany wykonywane przez różne osoby, śledzą
kolejność tych zmian, a także zapamiętują ich historię.
Przez lata najpopularniejszym rozwiązaniem w tej materii był SVN, znany również pod nazwą Apache Subversion.
Jego charakterystyczną cechą było to, że posiadał on jedno centralne
repozytorium, znajdujące się na jednym serwerze.
Z czasem wymagania w stosunku do tego rodzaju rozwiązań zaczęły rosnąć, co zaoowocowało popularyzacją systemu Git.
Największa zaletą Gita w porównianiu do SVN-a jest to, że jest on rozproszonym
repozytorium kodu źródłowego.
W rzeczywistości mamy więc tutaj do czynienia z połączeniem zarówno
repozytorium zdalnego
jak i repozytoriów lokalnych, przechowywanych na komputerach programistów.
Innymi słowy, każdy programista przechowuje kopię zdalnego
repozytorium na swojej maszynie, co pozwala na skuteczną pracę offline
oraz na łatwe odtworzenie zdalnego
repozytorium w razie jego utraty (pomijamy kwestie backupów).
Na powyższym zdjęciu widzimy jak wygląda struktura Git-a stworzona w ramach projektu.
Mamy tutaj
katalog projektu, w którym Git stworzył podkatalog .git.
To w nim przechowywane są faktyczne pliki i katalogi tworzące
repozytorium lokalne.
Oprócz tego katalog ten zawiera również
przechowalnie plików (staging area).
Trafiają tam pliki, które zostały stworzone przez nas w ramach projektu i które zamierzamy dodać do lokalnego
repozytorium.
Staging area stanowi więc swego rodzaju poczekalnię dla plików, zanim zostaną one przez nas skomitowane do
repozytorium.
Na koniec możemy zauważyć, że pliki, które znajdują się w lokalnym
repozytorium, mogą zostać przez nas wypchnięte (push) do
repozytorium na serwerze.
Proces ten oczywiście może być wykonany w przeciwnym kierunku. Możemy pociągnąć (fetch lub pull) wszystkie zmiany w kodzie, które zostały wykonane przez innych programistów.
Zmieniony kod zostaje wprowadzony do naszego
repozytorium lub nawet do naszego katalogu z projektem (szczegóły przedstawiamy w dalszej części rozdziału).
Appa Notka.
Objerzyj ten materiał na filmie. Jeśli chcesz więcej filmów takich jak ten — subskrybuj i polub.
Takie działanie z Twojej strony pozwoli nam lepiej zrozumieć, czy ta seria filmów jest dla Ciebie wartościowa
i czy powinna być kontynuowana.
Git - Konsola vs interfejs graficzny
Z Git-a możemy korzystać zarówno z poziomu konsoli, jak również za pomocą programów z interfejsem graficznym. Programów tego typu jest wiele, ale my polecamy w szczególności narzędzie TortoiseGit (link na dole strony).
Używamy go od lat i nigdy nas nie zawiodło (Aczkolwiek warto rozważyć naukę GIT-a na konsoli tak dokłądnie rozumieć, jak on działa).
Z drugiej strony wielu programistów pracuje dzisiaj na Mac-ach lub komputerach z Linuxem, więc mając na uwadze lepszą współpracę w ramach teamu,
warto przynajmniej choć trochę znać polecenia w formie konsolowej. Git dostarcza naprawdę znaczną liczbę tych komend. Ich listę można przejrzeć uruchamiając jedną z podstawowych komend:
Klonowanie czyli pobieranie projektu
Na początku pracy z projektem tworzone jest
repozytorium kodu w Gicie. Wykonuje to zwykle jedna osoba w zespole. Pozostali programiści zaczynają pracę
nad projektem pobierając to
repozytorium na swoją lokalną maszynę. Możemy powiedzieć, że kod jest klonowany. W wyniku tej operacji w naszym systemie plików
tworzony jest katalog projektu oraz dodatkowy podkatalog o nazwie .git (podobnie jak na naszym zdjęciu w paragrafie Starter dla początkujących).
Jeśli chcemy sklonować projekt z
repozytorium na Githubie, znajdujący się pod adresem: https://github.com/javappa-coding/postspringboot,
podajemy pełną ścieżkę do pliku (
.git):
Tak jak wspomnieliśmy, w tak pobranym projekcie zawsze znajdziemy katalog .git, w którym przechowywane są pliki z obiektami Gita.
Pierwszy krok - Repozytorium lokalne
Praca z plikami projektu opiera się zawsze na podobnych mechanizmach. W dużym uproszczeniu można powiedzieć, że programiści wykonują
zadania na lokalnych komputerach oraz synchronizują swoje zmiany ze zmianami wykonywanymi przez innych programistów. Wszystkie możliwe scenariusze
takiej pracy są realizowane za pośrednictwem komend Gita, których wykonywanie tworzy tzw. przepływ pracy, popularnie zwany jako Git Workflow.
Scenariusz 1
Zobaczmy teraz jak wygląda najprostszy, typowy scenariusz realizowany w pracy z Gitem. Polega na stworzeniu pliku i dodaniu go
do lokalnego
repozytorium:
-
Programista tworzy plik ItemService.java oraz uruchamia komendę, która pokazuje co teraz Git wie o projekcie:
Po uruchomieniu komendy Git zwróci nam informacje o tym, że mamy jeden stworzony plik, który nie jest jeszcze przez niego śledzony.
Oczekiwanym działaniem będzie więc dodanie tego pliku do "poczekalni" plików Gita.
-
Programista dodaje ten plik do "poczekalni" (staging area):
Po wykonaniu komendy git status Git zwróci informację o tym, że plik jest obecnie przechowywany i że jest gotowy do wrzucenia (skomitowania) do repozytorium:
-
Programista wrzuca (komituje) zmiany do lokalnego repozytorium ma swoim komputerze:
Opcja -m jest bardzo ważna. Dodajemy ją zawsze, aby wraz z komitem została zapisana informacja o tym czego dotyczy ten komit.
Po wykonaniu komendy git status Git zwróci informację o tym, że nie ma obecnie żadnych zmian do skomitowania:
Plik znajduje się więc obecnie w lokalnym repozytorium w jego głównej gałęzi (branch) o nazwie master.
W momencie komitowania zawsze wykonywana jest migawka tej operacji (snapshot). Git odnotowuje ją na osi czasu (timeline),
dzięki czemu w przyszłości programista będzie mógł wrócić do wersji kodu pochodzącej dokładnie z tego czasu.
Scenariusz 2
Kolejny scenariusz polega na zmodyfikowaniu pliku i dodaniu kolejnego:
-
Programista modyfikuje plik ItemService.java oraz tworzy nowy plik ItemServiceImpl.java. Następnie uruchamia
komendę, która pokazuje co teraz Git wie o projekcie:
Po uruchomieniu komendy Git zwróci nam informacje o tym, że mamy jeden stworzony plik, który nie jest jeszcze przez niego śledzony, oraz że
mamy jeden plik zmieniony, ale zmiana ta nie została odnotowana przez Gita:
-
Programista dodaje oba zmienione pliki do "poczekalni" (staging area).
Po wykonaniu komendy git status Git zwróci informację o tym, że oba pliki są obecnie przechowywane i że są gotowe do wrzucenia (skomitowania) do repozytorium:
-
Programista wrzuca (komituje) zmiany do lokalnego repozytorium ma swoim komputerze.
Po wykonaniu komendy git status Git zwróci informację o tym, że nie ma obecnie żadnych zmian do skomitowania:
Podobnie jak w scenariuszu pierwszym pliki znajdują się obecnie w lokalnym repozytorium w jego głównej gałęzi (branch) o nazwie master.
W momencie komitowania wykonana została migawka operacji (snapshot). Git odnotował ją na osi czasu (timeline) - na samej górze (ponad poprzednimi zmianami),
dzięki czemu w przyszłości programista będzie mógł wrócić do tego miejsca w czasie.
W trakcie realizacji powyższych scenariuszy pliki zostały ostatecznie skomitowane do lokalnego
repozytorium, co zostało skrupulatnie odnotowane na osi czasu.
Innymi słowy, stworzona została historia wykonanych komitów.
Drugi krok - Przeglądanie historii
Prawdopodobnie jedną z najczęściej używanych funkcjonalności Gita jest przeglądanie historii komitów. Używamy tej funkcjonalności najczęściej po to aby zobaczyć
kiedy i jak zmieniały się pliki, które są dla nas w danym momencie ważne:
Po uruchomieniu komendy, Git zwróci nam informacje o wykonanych komitach prezentując ich autora, datę oraz wiadomość podaną przez nas (opcja -m) podczas wykonywania komitu.
Kolejność jest przedstawiana odwrotnie do wykonywanych zapisów, więc najpierw pojawiają się komity "najmłodsze", czyli te które są na szczycie osi czasu.
Dodatkowo każdy komit ma swój unikalny identyfikator
SHA-1 (ciąg literowo cyfrowy), którym w przyszłości możemy się posługiwać, gdy będziemy chcieli
się do takiego komita odwołać.
Trzeci krok - Repozytorium zdalne
Do tej pory pokazaliśmy jak można pracować na lokalnym
repozytorium. Teraz przyszedł czas na podzielenie się naszym kodem z innymi.
W tym celu wykorzystamy kilka komend, które pozwolą nam na komunikację ze zdalnym serwerem.
- Programista wrzuca na zdalne repozytorium wszystkie zmiany, które skomitował wcześniej do swojego lokalnego repozytorium.
- Inny programista pobiera wrzucone zmiany ze zdalnego repozytorium. Zmiany te ściągają się do jego lokalnego repozytorium oraz do
w lokalizacji, w której znajduje się jego projekt (working directory).
Jeśli zależy nam tylko na synchronizacji zmian między zdalnym i lokalnym repozytorium (bez modyfikowania working directory),
wówczas używamy komendy:
Natomiast jeśli później chcemy te zmiany wgrać do projektu z naszego lokalnego repozytorium, wówczas używamy komendy:
Wywołanie pull jest pewnego rodzaju skrótem, który odpala zarówno fetch jak i merge.
Repozytorium zdalne posiada swoją nazwę, która jest definiowana na etapie jego tworzenia. Nazwa ta może być dowolna, ale najczęściej
stosowana jest nazwa
origin. Tak samo jak na
repozytorium lokalnym, tak samo na
repozytorium zdalnym wszystkie zmiany są
przechowywane w jego konkretnej gałęzi (branch). Zwyczajowo nosi ona nazwę
master, jednak mogą oczywiście istnieć
branche o innych nazwach.
Podsumowanie - Git Workflow
Na koniec podsumujmy wszystkie wykonane operacje. Zgodnie z prawdą, że jeden obraz jest wart więcej niż tysiąc słów obejrzyjmy omówiony przepływ danych (workflow)
na poniższym obrazku:
Oczywiście użycie komendy
git merge nie musi być zawsze bezpośrednią konsekwencją wywołania komendy
git fetch. Bardzo często wykorzystujemy
merge
niezależnie, na przykład gdy mamy dwa branche lokalne i chcemy pobrać zmiany z jednego brancha do drugiego. Pytanie jakie należy sobie w tym momencie zadać to w jaki sposób można się przełączać między branchami.
W tym celu wywołujemy komendę:
To wszystko co chcieliśmy Wam przekazać w zakresie wiedzy początkowej. Więcej napiszemy w niedalekiej przyszłości, kiedy to planujemy omówić szerzej temat branchy oraz
przygotować opis kolejnych komend (np. komendy porównującej kod w working directory z kodem w lokalnym
repozytorium).
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java
Czy informacje, które otrzymałeś, były pomocne?
Jeśli tak, zapraszam Cię do podarowania mi kawy.
Linki:
https://git-scm.com
https://tortoisegit.org
https://www.atlassian.com/git