Praca lokalna w Git

Notatki z podstaw Git’a – praca lokalna

Git towarzyszy programistom już od dawna. Od kilku lat między innymi za sprawą dbt zaczął być w końcu łatwo-wdrażalny do analityki i analitycznego wykorzystania baz danych. Do mnie też Git dotarł razem z dbt i nie wyobrażam sobie już Business Intelligence bez tak cudownych narzędzi 😉

Poniżej opisuję podstawy Gita, które zdecydowanie przydadzą Ci się przy pracy z dbt. Pomijam tu inicjację projektu i pobieranie repozytorium ze zdalnego repozytorium, a skupiam się na codziennej pracy.

Czym właściwie jest Git

Po krótce – git to rozproszony system kontroli wersji.
System kontroli wersji służy do śledzenia zmian w kodzie utrzymując ich historię.
Git jest obecnie najlepszym rozwiązaniem spośród wszystkich systemów kontroli wersji dla większości zespołów pracujących nad rozwojem kodu. (Celowo nie piszę, że jest dla programistów, gdyż korzyści płynące z wykorzystania Gita są znacznie szersze).

Git przechowuje pliki jako zestaw migawek. Gdy w pliku zachodzą zmiany Git tworzy obraz wszystkich plików w repozytorium -> zmieniony plik zostaje zapisany w takiej migawce, a do wszystkich niezmienionych plików Git przechowuje referencję do poprzedniej, identycznej wersji, która już jest zapisana.

3 stany Gita

Zrozumienie koncepcji 3 stanów Gita to kluczowy aspekt do zrozumienia całego Gita.

Edytując plik w repozytorium Gita jest on przechowywany w Working Copy. Polecenie git status wskaże Ci wszystkie zmodyfikowane i utworzone pliki.

Po poleceniu git add plik.txt ten plik trafi do Staging Area.

Na koniec, po git commit Working Copy jest znów puste, a nowy plik plik.txt został dodany do lokalnego repozytorium git.

Praca lokalna

Ważna sprawa, która zauważyłem, że często zaprząta głowę osobom początkującym z Gitem -> wszelkie zmiany, jakich dokonujesz w kodzie nie wpłyną w żaden sposób na repozytorium zdalne i kod produkcyjny!

Więcej o Working Copy

Jak po prostu edytujesz plik i zapisujesz zmiany, jakie w nim wprowadziłeś, to właśnie w tej przestrzeni Gita się znajdujesz. Możesz tutaj testować różne zmiany i sprawdzać lokalnie jak zmiany wpływają na projekt, jednak póki co, te zmiany nie są zapisane w samym projekcie.

Żeby sprawdzić listę zmian, które lokalnie zapisałeś uruchom w konsoli poniższy kod. Zależnie od konsoli, jakiej używasz kolory mogą się różnić, jednak najczęściej wszystkie pliki z zapisanymi zmianami będą czerwone.

git status

Zauważ, że Git jest bardzo pomocny i podpowiada Ci od razu dużo rzeczy. Zgodnie z informacjami na screenie:

  • jestem na gałęzi master
  • mogę użyć polecenia git add <nazwa pliku>, by dodać go do listy plików do zacommitowania
  • nie mam w tej chwili żadnych plików oznaczonych jako gotowych do zacommitowania, ale są jakieś zmienione.

Jak wyczyścić working copy, żeby nie zapisywać ich zmian?

No dobra… ale co w sytuacji, jak napracowałeś się, pozmieniałeś mnóstwo plików i… chcesz przywrócić wszystkie pliki do stanu sprzed wszystkich zmian?

Mamy taką sytuację:

  • plik lista_zakupowa.html istniał już we wcześniejszym commicie, ale dodałem do listy nową rzecz.
  • plik_tekstowy.txt jest zupełnie nowy

Zauważ, że oba pliki są wylistowane oddzielnie. lista_zakupowa.html jest plikiem śledzonym przez Git’a, bo już istniała wcześniej (była już zacommitowana). Natomiast plik_tekstowy.txt jest plikiem zupełnie nowym.

komenda gitefekt
git checkout -- lista_zakupowa.htmlPrzywróci stan pliku z ostatniego commita. Podwójny myślnik jest po to, żeby git wiedział, że następuje po nim nazwa plików (jeśli nazwa pliku będzie taka sama, jak nazwa innej gałęzi, to komenda przeniesie Cię na tę gałąź).
git checkout -- *.htmlJak wyżej, ale przywróci stan z ostatniego commita wszystkim zmienionym plikom .html.
git reset --hardUsuwa wszystkie zmiany w śledzonych plikach i przywraca ich stan z ostatniego commita.
git clean -fUsuwa nowe pliki (te nieśledzone) z Working Copy.
git clean -nPokaże listę plików, które usunie komenda git clean -f.
git clean -iTryb interaktywny, gdzie Git przejdzie po kolei przez nowe pliki pytając się, czy je usunąć.
git clean -fdxUsunie wszystkie nieśledzone pliki i katalogi (włącznie z ignorowanymi przez Git).
komendy git do czyszczenia Working Copy

Więcej o Staging Area

Inaczej nazywane Index. Tu dodajesz wszystko, co chcesz zapisać w kolejnym commicie.

git add –all
lub
git add .

Powyższe komendy są najprostszymi sposobami na dodanie wszystkich zapisanych zmian w plikach do Staging Area. Ale…

Dobrą praktyką jest tworzenie commitów spójnych. Co oznacza spójny commit? Spójny commit to taki, który zawiera w sobie tylko zmiany, które są logiczną całością. Chodzi o to, żeby commit rozwiązywał pojedyncze zagadnienie/problem, a nie rozwijał od razu kilka lub więcej funkcjonalności.

git add -p

Komenda git add -p pomoże Ci nad tym zapanować. Korzystając z tej komendy Git zacznie przechodzić przez wszystkie „hunk’i” pytając się po kolei, czy dodać je do Staging Area.

Czym jest ten hunk w Git?

Hunk to nic innego, jak pojedyncza zmiana w kodzie, jaką zidentyfikował Git. W jednym pliku możesz mieć wiele hunk’ów, co oznacza, że możesz dodać do Staging Area nawet pojedynczą zmianę, a nie koniecznie cały plik od razu.

Poniżej najprostszy przykład pliku z 2 hunk’ami w liście zakupów. Dodałem do jednej listy Sok pomarańczowy, a do drugiej Słuchawki. Polecenie git diff pozwala podejrzeć w terminalu listę zapisanych zmian znajdujących się w Working Copy.

git diff

Wykorzystując git add -p zauważysz, że Git zapyta się, czy dodać każdą z tych zmian indywidualnie. Na dole, na niebiesko masz informację, że jest to 1 hunk z 2, jakie Git zidentyfikował. Ten chcę dodać, a drugi pominę.

Zauważ, że plik lista_zakupowa.html jest teraz zarówno w Staging Area jak i Working Copy.

Jeśli chcesz dodać wszystkie zmiany z tylko jednego pliku, lub wszystkie pliki z jednego katalogu możesz do git add dodać nazwę pliku lub katalogu.

git add plik_tekstowy.txt
git add katalog/*

Podglądanie zmian w Staging Area

Polecenie git diff pokaże Ci tylko zmiany w Working Copy. Żeby zobaczyć zmiany, które oczekują na zacommitowanie w Staging Area możesz wykorzystać poniższe komendy:

git status -v
git diff --cached
git diff --staged

Jeśli będziesz mieć w Staging Area wiele plików, ale przypuśćmy, że chcesz zobaczyć zmiany tylko w jednym pliku, to wystarczy, że skorzystasz z takiego polecenia:

git diff --cached -- lista_zakupowa.html

Pamiętasz? Podwójny myślnik informuje Git, że po nich zaczyna się lista nazw plików.

czyszczenie Staging Area

Jeśli jednak chcesz jednak cofnąć któryś plik ze Staging Area wystarczy skorzystać z poniższych komend. Wersja z kropką cofnie wszystkie pliki ze Staging Area do Working Copy.

git restore --staged .
git restore --staged lista_zakupowa.html

Więcej o commit’ach

Commit to zapis stanu gry, to takie okruszki, które pozwolą Ci zobaczyć historię projektu, jak się zmianiał i co kierowało tymi zmianami. Commity pozwalają też cofnąć się w czasie, przywrócić cały projekt do stanu z konkretnego momentu, lub tylko małą jego część. Jednak, żeby łatwo się z tych funkcjonalności korzystało warto przestrzegać kilku dobrych praktyk.

ZasadaOpis
Jeden commit = jedna logiczna zmianaNiech commit nie zawiera rozwiązania buga i rozwinięcie kilku nowych funkcjonalności.
Rozwój konkretnej funkcjonalności też warto rozbić na wiele commitów – każdy krok w kierunku dowiezienia ostatecznego rozwiązania = commit.
Commituj częstoWiąże się to z powyższym punktem. Pojedyncze logiczne zmiany raczej zachodzą dość często, dlatego warto często je commitować.
Commit message musi być informatywnyCommit message powinien wyraźnie opisywać co zmianiasz w kodzie. Opisy „bug fix” czy „saving work” nie mówią zbyt wiele.
Dobrym commit message może być „fixed window function for week to date revenue”.
Commit message powinien mieścić się w 72 znakachWszystkie narzędzia używają tej konwencji. Jeśli commit message będzie miał więcej znaków, to się nie wyświetlą, lub przejdą do następnej linii, co utrudni ich odczyt.
Jeśli trzeba, do commit message dodaj dłuższe wytłumaczenie.W takiej sytuacji nie dodawaj parametru „-m” jak commitujesz. Otworzy Ci się okno wybranego edytora tekstu, w którym pierwszy wiersz to podstawowy commit message, później pusty wiersz, a od 3 wiersza opisujesz dokładniej zmiany, jeśli jest to konieczne.
Przykładowo dlaczego wprowadzasz te zmiany i z czym się wiążą.
Dodatkowych opisów również dotyczy limit 72 znaków na linię.

Edytowanie commita

Co jeśli commit już jest zrobiony, ale commit message jest kiepski? Albo okazuje się, że do ostatniego commita jeszcze trzeba dorzucić zmianę, bo w ferworze wykorzystywania komendy git add -p kliknęło się o jedno 'n’ za dużo?

git commit --amend -m <commit message>
git commit --amend --no-edit

Parametr --amend podczas commitowania pozwala Ci nadpisać historię. W miejscu poprzedniego commita wstawia nowy (przetestuj – zauważysz, że ostatni commit id się zmieni).

Parametr --no-edit pozwoli Ci zrobić edytować commit bez konieczności edycji commit message.

Cofanie i odwracanie commita

Może Cię czasem trącić sumienie, że po zacommitowaniu dużej ilości zmian jednak chcesz się cofnąć o krok i zrobić porządne commity. 😉

Do tego posłuży Ci się poniższa komenda. Nie wchodząc w szczegóły Git reset z id commita przywróci stan plików do stanu z wybranego commita, a wszystkie zmiany od tego commita trafią do Working Copy.

git reset <poprzedni commit>
git reset d585f04

Żeby dostać id commitów posłużą Ci się poniższe komendy:

git log --oneline -n4
gitk

Pierwsza komenda wylistuje 4 ostatnie commity (przełącznik -n4), 1 commit w 1 wierszu (przełącznik --oneline).

Gitk z kolei to graficzny interfejs, w którym łatwiej możesz przejrzeć historię projektu.

Warto wiedzieć, że tak można

git revert <id commita>

Git revert tworzy nowy commit, który będzie odwrotnością wybranego commita. Jeśli odwrócisz commit zbyt odległy może się okazać, że będziesz mieć do rozwiazania konflikt.

git checkout <id commita> -- <lista plików>
git checkout 684763f -- lista_zakupowa.html

Powyższe git checkout pozwala na wzięcie stanu konkretnego pliku z konkretnego commita i dodanie go do bieżącej gałęzi bezpośrednio do Staging Area. Wybrany commit nie musi być historycznym commitem bieżącej gałęzi – może być równie dobrze na jakiejś innej gałęzi.

Krótko o branchach/ gałęziach

Gałęzie w Git to logiczne kopie projektu pozwalające na niezależny rozwój różnych funkcjonalności w taki sposób, że developerzy sobie nie przeszkadzają. Każda gałąź składa się z commitów.

Główną gałęzią jest zazwyczaj main/master i od niej możesz tworzyć „feature branche”.

Słowniczek pojęć

Lista komend

KomendaOpis
git branchwylistuje wszystkie lokalne gałęzie
git branch <nazwa_gałęzi>stworzy nową gałąź
git branch -d <nazwa_gałęzi>usunie wybraną gałąź
git branch -D <nazwa_gałęzi>usunie gałąź nawet taką, która nie została nigdzie zmergeowana
git branch -m <nowa_nazwa_gałęzi>pozwala zmienić nazwę bieżącej gałęzi
git checkout <nazwa_gałęzi>przejdziesz do wybranej gałęzi
git checkout -b <nazwa_gałęzi>dzięki przełącznikowi „-b” git najpierw utworzy nową gałąź, a później automatycznie Cię na nią przeniesie
git checkout -podając sam minus po komendzie checkout git przeniesie Cię na poprzednią gałąź, a dokładniej-> na poprzedni HEAD

Merge, czyli łączenie gałęzi

Tworzenie gałęzi na nic by się zdało, gdybyśmy nie mogli ich później połączyć. Merge to przeniesienie commitów z jednej gałęzi na drugą.

Ważne: merge odbywa się DO bieżącej gałęzi.
Innymi słowy: w komendach merge mówisz Git’owi „dodaj do bieżącej gałęzi commity z tej gałęzi, której nazwę ci podaję”.

git merge <nazwa_brancha>

Co tu pominąłem w kontekście pracy z Git’em?

Ogólnie… mnóstwa rzeczy. W tym wpisie zawarłem jedynie podstawy Git. Znajomość i świadomość powyższych aspektów i tak powinna pozwolić Ci na płynną pracę samodzielną.

Planuję jeszcze jeden wpis o Git w kontekście pracy zdalnej i zespołowej, w którym pewnie pojawią się poniższe aspekty:

  • GitHub / GitLab
  • wysyłanie i pobieranie zmian
  • konflikty
  • przegląd historii projektu

Nie przegap kolejnych wpisów -> śledź mnie:


Opublikowano

w

przez

Komentarze

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *