czwartek, 21 maja 2015

[GIT] Podstawy i praca z repozytorium

TRUE
6335671948737500847
Git to obok Subversion drugi najpopularniejszy system wersjonowania kodu. Pozwala na bardzo przyjemną i przejrzystą organizację kodu zarówno dla pojedyńczego programisty, jak i w projektach wieloosobowych. Podstawy obsługi Gita są łatwe do ogarnięcia - wystarczy nauczyć się logiki działania takiego podejścia do wersjonowania projektu oraz zaznajomić się z kilkoma pojęciami, jakie spotykać będziemy podczas codziennej pracy z Gitem. W artykule tym postaram się w skrócie wyjaśnić na czym polega praca z repozytorium Gita i jak efektywnie wykorzystywać możliwości jakie daje on programiście. Artykuł pisany jest pod kątem pracy pod Windowsem, ale pod Linuxem składnia poleceń Gita jest identyczna, jedynie sposób instalacji jest inny.

Największą zaletą Gita jest to, iż zawsze pracujemy na lokalnej roboczy kopii naszego kodu, a nie na nim samym bezpośrednio. Jest to niesamowite rozwiązanie, bo po pierwsze pozwala na pracę "offline", po drugie sprawdza się to świetnie w pracy zespołowej, (o pracy w teamie i o tym jak to wygląda napiszę po krótce w innym tekście).

Jak więc działa Git? Zasada działania z początku może wydawać się zagmatwana, ale po zrozumieniu jej wyda się Wam banalnie wręcz prosta. W Gicie pracujemy z naszymi plikami w folderze roboczym. Pliki te mogą być śledzone przez Gita, lub nie. A co to znaczy "śledzone"? Znaczy to, że Git będzie je uwzględniał w swoim repozytorium i analizował wszelkie ich modyfikacje. Znaczy to też to, że pliki do repozytorium muszą być przez nas dodane.

Przyjrzyjmy się poniższemu diagramowi, który przedstawia możliwe statusy w jakich może znaleźć się każdy z plików naszego projektu:




Pierwszy status to zwykły plik, jeszcze nie śledzony przez Gita (untracked).
Aby sprawić, by był od śledzony przez Gita i uwzględniany w repozytorium, musimy go do niego dodać. Plik taki wyląduje w tzw. stage, lub indexie (obie nazwy są równoważne), czyli w czymś w rodzaju poczekalni. Plik teraz możemy dowolnie modyfikować, lub też dodać kolejne pliki do repozytorium. Póki co znajdują się one w naszej roboczej wersji, ale zmiany w nich nie są jeszcze zatwierdzone w repozytorium. Dopiero po wykonaniu polecenia commit zmiany jakich dokonaliśmy w plikach są zatwierdzane i nasze pliki dostają status unmodified, czyli niezmodyfikowany od ostatniego commita. Poleceniem commit tworzymy zatem nową tzw. rewizję. Pliki lądują tym samym w tzw. HEAD repozytorium. Kolejna modyfikacja plików zmieni ich status na modified i cała procedura rozpoczyna się od nowa. Prześledzimy to wszystko dokładnie w tym poradniku.

Instalacja i nowe repozytorium - git init

Gita po pierwsze musimy pobrać i zainstalować w systemie.
Dla Windowsa - wchodzimy na stronę https://msysgit.github.io/ i pobieramy najnowszą wersję.
Po instalacji, w systemie pojawią się nam dwa nowe narzędzia: Git Bash i Git GUI. Na razie nauczymy się pracy w bashu.
Na początek stworzymy folder z naszym projektem.
W poradniku tym, dla przykładu niech będzie to folder:
[code]C:/repo_test[/code]
Na razie będziemy pracować w konsoli, zatem uruchamiamy okno Git Basha.
Na początek dokonamy małej konfiguracji, tak aby każdy commit był odpowiednio podpisywany naszymi danymi:
[code]$ git config --global user.name "imię i nazwisko"
$ git config --global user.email "adres@email.pl"[/code]
Ustawimy sobie też kolorowanie ekranu:
[code]$ git config color.ui true [/code]
Po skonfigurowaniu Gita, wchodzimy do nowo utworzonego folderu:
[code]$ cd C:/repo_test[/code]
Zainicjujemy teraz w nim nowe repozytorium.
Robimy to komendą:
[code]$ git init[/code]
Otrzymamy komunikat:
[code]Initialized empty Git repository in C:/repo_test/.git[/code]


W nazwie naszego folderu pojawi się (master) - co oznacza, że znajdujemy się w głównej galęzi projektu, która w Gicie ma właśnie nazwę master.

Repozytorium mamy już zainicjowane, spójrzmy co się w nim utworzyło.
W folderze C:/repo_test utworzył się ukryty podfolder o nazwie .git zawierający kolejne podfoldery i pliki. Folder .git przechowuje wszystkie informacje o naszym repozytorium, więc pamiętajmy, aby pozostał on dokładnie na swoim miejscu.

Nasze repozytorium jest na razie puste.
Utwórzmy w nim następujące testowe pliki:

  • plik test1.txt
  • plik test2.php
  • folder /testowy
  • plik /testowy/test3.php

Tak jak poniżej:



Dodawanie plików do repozytorium - git add

Mamy już kilka plików, ale mimo, iż znajdują się w folderze, to nie znajdują się one jeszcze w repozytorium i nie są przez Gita śledzone. Do repozytorium musimy je dodać ręcznie, za pomocą polecenia add. Można to zrobić na 2 sposoby:

1) podając pojedyńczą nazwę pliku:
[code]$ git add nazwa_pliku[/code]

2) lub dodając za jednym zamachem wszystkie pliki w folderze:
[code]$ git add .[/code]

Wykorzystajmy drugą opcję:
[code]$ git add .[/code]

Wpisujemy polecenie, wciskamy [ENTER] i nasze pliki zostają dodane do naszego repozytorium i od tej chwili są już śledzone przez Gita.


Aby usunąć dodany plik z repozytorium wykonujemy operację odwrotną, za pomocą polecenia rm:
[code]$ git rm nazwa_pliku[/code]

Commitowanie zmian - git commit 

Czym jest tzw. commit? Jest to w skrócie zatwierdzenie zmian dokonanych w plikach i wysłanie ich do repozytorium jako ich kolejny update. Robiąc commita tworzymy nową rewizję w naszym repozytorium. Po każdym takim commicie istnieje możliwość przywrócenia stanu plików z poprzednich commitów, możemy więc się cofnąć do poprzednich wersji. Pliki nie dodane do commita znajdują się w tzw. Indexie (są oczekujące na zatwierdzenie zmian), pliki zacommitowane lądują w tzw. HEAD repozytorium.

Jak już wspomniałem - główną gałęzią jest gałąź master. Zróbmy więc naszego pierwszego commita. Pamiętać należy, iż do każdego commita dodać należy jakąś krótką wiadomość (komentarz) informującą np. o zmianach w plikach jakie poczyniliśmy.

Commita robimy za pomocą polecenia:
[code]$ git commit -m "TREŚĆ WIADOMOŚCI"[/code]
Wywołanie commita bez parametru -m spowoduje otworzenie domyślnego edytora tekstowego w celu wpisania komentarza, dlatego aby tego uniknac komentarze podawajmy zawsze po parametrze -m, o ile oczywiście nie są to obszerne opisy.

Wpiszmy więc:
[code]$ git commit -m "pierwszy commit"[/code]
Pojawi się nam informacja o wszystkich plikach jakie zostały zacommitowane:


Dokonajmy teraz małej modyfikacji, żeby zrozumieć na czym polega przełączanie się pomiędzy wersjami. Przed chwilą dodaliśmy commita z wersjami plików takimi jakie były do chwili zacommitowania. Pliki póki co były puste, dokonajmy teraz małej zmiany, otwórzmy np. plik test1.txt znajdujący się w naszym testowym repozytorium i wpiszmy w nim jakiś ciąg znaków, cokolwiek, np. tutaj zmiana treści pliku i zapiszmy go.
Dokonaliśmy właśnie zmiany stanu pliku, zróbmy więc kolejnego commita, wpisując:
[code]$ git commit -am "zmieniono test1.txt"[/code]
lub
[code]$ git commit -a -m "zmieniono test1.txt"[/code]
(obie formy są równoważne)

Zauważmy, iż jako iż modyfikowaliśmy plik, dodajemy commita z parametrem: -aktóry to automatycznie dodaje zmienione pliki do danego commita, bez potrzeby kolejnego wywoływania git add. Musimy jednak pamiętać, iż dodane zostaną jedyne zmodyfikowane, już dodane wcześniej do repozytorium pliki - to polecenie nie doda nam nowo utworzonych plików - te musimy dodać oddzielnie, za pomocą git add.

Pojawi się informacja o zmodyfikowanych plikach, w tym przypadku test1.txt:



Informacje o aktualnym commicie/rewizji - git status

Wpiszmy teraz polecenie:
[code]$ git status[/code]
Wyświetli ono informacje o aktualnym commicie.
Jak widzimy, nie było żadnych zmian od naszego commita. W przypadku jeśli teraz zmodyfikujemy jakiś plik to poleceniem git status zobaczymy stosowną informację o potrzebie wykonania commita dla zmodyfikowanego pliku:



Utwórzmy teraz nowy plik, o nazwie np. test999.txt i zapiszmy w naszym repozytorium:



A następnie dodajmy go do repozytorium i zacommitujmy całość:
[code]$ git add "test999.txt"
$ git commit -m "dodano plik test999.txt"[/code]


W tym momencie mamy już w sumie 3 commity:

  1. pierwszy commit
  2. zmieniono "test1.txt"
  3. dodano plik "test999.txt"

Historia commitów/rewizji - git log

Wyświetlmy historię naszych commitów, zrobimy to za pomocą polecenia:
[code]$ git log[/code]



Jak zapewne widzimy, każdy z commitów identyfikowny jest przez Gita jako unikalny hash. Warto o tym pamiętać, gdyż wszelkie odwołania do danych commitów robić można jedynie za pomocą właśnie owych hashy.

Gałęzie repozytorium - git branch i git checkout 

Na początek - czym jest branch? Jest to dane odgałęzienie naszego projektu, nad którym możemy pracować niezależnie, a następnie z powrotem dołączyć do głównej gałęzi master. Jest to również rozwiązanie pozwalające na pracę kilku osobom nad jednym projektem - gdzie każdy z programistów pracuje na oddzielnej gałęzi. Wyobraźmy sobie, że mamy pomysł na nowy kod, nową funkcjonalność, ale nie chcemy mieszać w naszej głównej gałęzi. Utworzymy więc nową gałąź i to na niej będziemy pracować, a gdy zakończymy naszą pracę - dołączymy naszą gałąź do gałęzi głównej i scalimy ją z projektem.

Nowego brancha (gałąź) tworzymy za pomocą polecenia:
[code]$ git branch NAZWA_BRANCHA[/code]
Stwórzmy zatem gałąź o nazwie nowy_feature:
[code]$ git branch "nowy_feature"[/code]


Utworzyliśmy nową gałąź, ale póki co znajdujemy się w gałęzi głównej.
Aby przełączyć się na nowo utworzoną gałąź, użyjemy polecenia:
[code]$ git checkout NAZWA_BRANCHA[/code]
Możemy też utworzyć gałąż i od razu się na nią przełączyć za pomocą:
[code]$ git checkout -b NAZWA_BRANCHA[/code]
Wpiszmy zatem:
[code]$ git checkout "nowy_feature"[/code]


Jak widzimy - od tej chwili pracujemy w gałęzi nowy_feature.
Sprawdźmy jak to działa. Utwórzmy teraz nowy plik o nazwie nowy_kod.php:



Dodajmy go do repozytorium i zacommitujmy:
[code]$ git add "nowy_kod.php"
$ git commit -m "jedziemy z nowym kodem"[/code]


Commit poleciał do gałęzi nowy_feature.
Spójrzmy teraz co się stanie, gdy przełączymy się z powrotem na gałąź master:
[code]$ git checkout master[/code]
Plik nowy_kod.php zniknął!



Zniknął ponieważ istnieje on tylko w gałęzi nowy_feature, podobnie jak wszystkie zmiany w innych plikach jakie robiliśmy w tamtej gałęzi. Pracując więc na jednej gałęzi, nie zmieniamy absolutnie stanu plików innej gałęzi. Nasze repozytorium może mieć nieskończona liczbę rozgałęzień i żadne z nich nie wpływa za pozostałe gałęzie.

Można też automatycznie rozpocząć nową gałąź od zadanego commita, np.:
[code]$ git checkout -b NAZWA_NOWEGO_BRANCHA c3c6bad046[/code]
gdzie  c3c6bad046 to tutaj pierwsze 10 znaków hasha pierwszego commita (rewizji), jedynie na przykład.

Scalanie gałęzi - git merge

Załóżmy teraz, że skończyliśmy pisać już naszą nową funkcjonalność i chcemy gałąź nowy_feature dołączyć do naszj gałęzi głównej, czyli do master. Zrobimy to poleceniem git merge. Będąc w gałęzi master, wpisujemy:
[code]$ git merge "nowy_feature"[/code]


Gałąź nowy_feature została dołączona do gałęzi master.
Plik nowy_kod.php istnieje już od teraz w gałęzi głównej:

Po złączeniu gałęzi, możemy już usunąć naszą roboczą gałąź nowy_feature, robimy to poleceniem:
[code]$ git branch -d "nowy_feature"[/code]



Porównywanie zmian - git diff

Utwórzmy teraz kolejną gałąź o nazwie other_branch i wejdźmy w nią.
[code]$ git branch "other_branch"
$ git checkout "other_branch"[/code]

Zmodyfikujmy teraz plik test.txt dodając mu linijkę:
[code]zmienione w gałęzi other branch[/code]
Zapiszmy plik i zacommitujmy zmianę:
[code]$ git commit -am "zmiana w gałęzi"
[/code]
Plik test.txt jest teraz zmieniony w gałęzi other_branch.
Zobaczymy teraz jak wyświetlić różnice/zmiany w plikach pomiędzy gałęziami.
Aby zobaczyć jak gałąź master różni się teraz od gałęzi other_branch wpiszmy:
[code]$ git diff "master" "other_branch"[/code]
Zostaną nam wyświetlone różnice w plikach:



Tagowanie commitów/rewizji - git tag

Każdego commita możemy otagować, np. nazwą wersji.
Jak tego dokonać? Potrzebujemy pierwszych 10 znaków hasha commita, którego chcemy otagować, np. w naszym przypadku pierwsze znaki hasha pierwszy commit to:
[code]c3c6bad046[/code]
Dodajemy tag, np. o nazwie 1.0.0 :
[code]$ git tag 1.0.0 c3c6bad046[/code]

Cofanie zmian w repozytorium - git reset

Zmiany możemy wycofać zarówno w pojedyńczym pliku, jak i w całym commicie.
Cofanie zmian w pliku przedstawia poniższy diagram:





[code]$ git reset HEAD nazwa_pliku[/code]...spowoduje usunięcie pliku ze stage/indexu, nie cofając jednak zmian w nim dokonanych;

[code]$ git checkout nazwa_pliku[/code]...spowoduje cofnięcie wszystkich modyfikacji pliku, przywracając mu stan z przed modyfikacji, a więc plik powraca do stanu z ostatniego commita;

[code]$ git rm --cached nazwa_pliku[/code]...spowoduje usunięcie pliku z repozytorium, nadaje mu więc status untracked.

Cofanie zmian w całym commicie, czyli dla wszystkich plików pokazuje natomiast ten diagram:

[code]$ git reset --hard[/code]...spowoduje przywrócenie stanu całej rewizji do poprzedniego commita.

Aby przywrócić repozytorium do nie ostatniego, lecz do zadanego commita (rewizji) potrzebujemy pierwsze 10 znaków hasha rewizji, do której chcemy przywrócić stan, po czym wykonujemy polecenie, np.:
[code]$ git reset --hard c3c6bad046[/code]...przywróci to stan do stanu z rewizji identyfikującej się hashem c3c6bad046...

[code]$ git reset HEAD *[/code]...spowoduje cofnięcie zatwierdzonych w danej rewizji modyfikacji (cofa commit -a);

[code]$ git checkout *[/code]...spowoduje cofnięcie wszystkich modyfikacji w obecnej rewizji.

[code]$ git revert c3c6bad046 [/code]...stworzy nowego commita, jednocześnie cofając w nim wszystkie zmiany dokonane w rewizji c3c6bad046... Bezpieczna metoda, gdyż nie usuwa niczego z historii.

[code]$ git reset --hard HEAD~[/code]...usunie ostatniego commita wraz z historią.

Istnieje jeszcze komenda clean, która pozwala na automatyczne usunięcie wszystkich nieśledzonych przez Gita plików z folderu roboczego.

[code]$ git clean -n[/code]...wyświetli wszystkie nieśledzone pliki, nie usuwając ich jeszcze.

[code]$ git clean -f[/code]...usunie z folderu roboczego wszystkie nieśledzone pliki, za wyjątkiem tych określonych w .gitignore

Poprawki w repozytorium - git commit --amend

Jeśli stworzyliśmy nową rewizję poleceniem commit i o czymś zapomnieliśmy, możemy poprawić ostatnią rewizję, dodając zapomniane pliki:
[code]$ git add pliki_o_ktorych_zapomnielismy
$ git commit --amend[/code]

Graficzny interfejs - gitk

Po wpisaniu:
[code]$ gitk[/code]
uruchomimy graficzne GUI umożliwiające łatwe przeglądanie poszczególnych commitów i gałęzi:



Lista poleceń/pomoc - git help

Pełną listę opcji znajdziecie wpisując w konsoli:
[code]$ git --help[/code]

Bardzo ładna i skrócona prezentacja jak używać GIT-a znajduje się tutaj:
http://rogerdudler.github.io/git-guide/index.pl.html

1 komentarz:

Masz sugestię? Znalazłeś błąd? Napisz komentarz! :)

webmaester.pl - profesjonalne projektowanie WWW i webaplikacji
webmaester.pl - profesjonalne projektowanie WWW i webaplikacji