Identyfikowanie rewizji, czyli jak odnieść się do komita istniejącego w naszej historii. Napiszę jakie są możliwe sposoby wraz z przykładami. Zapraszam 🙂
Pełny SHA-1
Pospolicie commit, profesjonalnie identyfikator rewizji czyli 40-znakowy skrót SHA-1. Polecenie:
git log --pretty=oneline
Spowoduje wyświetlenie wszystkich rewizji, każdy w jednej linii z informacją: sha1 a następnie wiadomość commita. Przykład:
C:\MojeProjekty\git (master -> origin) λ git log commit 61893e857c17378b845d66979951ddefa5431b04 (HEAD -> master) Author: Przemysław JuśkiewiczDate: Sat Apr 8 15:38:04 2018 +0100 c commit 30be34132ab4bb7f2c4a69dce94294f21009f752 Author: Przemysław Juśkiewicz Date: Sat Apr 8 15:37:56 2018 +0100 b commit 1af12d98d1f6146781e4b8e69743bd5bb9cb08c4 Author: Przemysław Juśkiewicz Date: Sat Apr 8 15:37:41 2018 +0100 a C:\MojeProjekty\git (master -> origin) λ git log --pretty=oneline 61893e857c17378b845d66979951ddefa5431b04 (HEAD -> master) add c 30be34132ab4bb7f2c4a69dce94294f21009f752 add b 1af12d98d1f6146781e4b8e69743bd5bb9cb08c4 add a
Każda rewizja jest identyfikowana unikalnym 40-znakowym skrótem SHA-1. Aby przywrócić obszar roboczy, ze stanu konkretnej rewizji, należy wydać polecenie:
git checkout sha-1 git checkout 30be34132ab4bb7f2c4a69dce94294f21009f752
W tym przypadku nasz obszar roboczy będzie posiadać stan plików z komitu 'a’ oraz 'b’.
Skrócony SHA-1
Zamiast podawać pełnego skrótu SHA-1 możemy podać jego skróconą wersję, która wynosi 4 znaki. Jest jeden warunek, dana rewizja musi być unikatowa. Jeżeli w historii będą dwie rewizje, które mają taki sam początkowy SHA-1, wtedy komenda nie zadziała. Gdy okaże się, że skrócony zapis nie działa, wtedy należy podać więcej niż 4 znaki. Przykład:
C:\MojeProjekty\git (master -> origin) λ git log --abbrev-commit --abbrev=4 --pretty=oneline 6189 (HEAD -> master) add c 30be add b 1af1 add a
Ilość znaków, jakie podamy podczas polecenia git checkout jest nie ważna, ważne, aby ilość znaków SHA-1 była unikatowa.
//wyświetli skrócną wersje SHA-1 git log --abbrev-commit --pretty=oneline 61893e8 (HEAD -> master) add c 30be341 add b 1af12d9 add a //parametr '--abbrev=' definiuje ile znaków ma być podane. git log --abbrev-commit --abbrev=4 --pretty=oneline
Znaczniki
Jeżeli rewizje oznaczymy znacznikiem
1af1 add a git tag -a v0.0.1 -m "Wersja 0.0.1"
wówczas poniższe polecenia działają tak samo:
git checkout -f 1af1 git checkout -f v0.0.1
HEAD
HEAD wskazuje ostatnią rewizję w bieżącej gałęzi.
C:\MojeProjekty\git (master -> origin) λ git log --pretty=oneline 61893e857c17378b845d66979951ddefa5431b04 (HEAD -> master) add c 30be34132ab4bb7f2c4a69dce94294f21009f752 add b 1af12d98d1f6146781e4b8e69743bd5bb9cb08c4 add a
Poniższe polecenia są równoznaczne
git checkout -f 6189 git checkout -f HEAD
Przywracanie rewizji domyślnej
Inaczej mówiąc, rewizja domyślna działa tak samo, jak rewizja z HEAD, różnica jest w zapisie. Poniższe polecenia działają tak samo:
git checkout -f 6189 git checkout -f HEAD git checkout -f
Repozytoria nieliniowe
Słowo wstępu, jeżeli nie wiesz, czym jest gałąź (ang. branch), nie przejmuj się :), te elementy zostaną omówione w kolejnych wpisach. Przykłady z nieliniową historią rewizji ma pokazać, że git nie ogranicza się tylko do historii liniowej.
Powyższe przykłady pokazują historie rewizji w jednej linii tzn z jednym rodzicem.
... O Third commit ... ^ | | O Second commit ^ | | O First commit
W git istnieją gałęzie (ang. branch), pozwalają one na utworzenie historii nieliniowych, będę pisać o tym w dalszej części serii.
Przykład historii wieloliniowej:
... O Merged commit ^ ----|---- ^ ^ | | | | | O Five commit three commit O ^ ^ | | O Four commit | | Two commit ----O---- ^ | | One commit O
Oba przykłady mają wspólny element, mowa o rodzicach (ang. parent revision, parent node).
Używając Gita możemy, identyfikować rodziców za pomocą specjalnych znaków:
X~n X^n //LEGEND X - commit n - natural numbers ~ - shows n ancestor generation ^ - shows n parent generation
Komity opisujemy tutaj znakiem X. Liczbą naturalną jest n, która wskazuję na konkretnego rodzica. Znak ~ wskazuję na przodka n-tej generacji, zaś ^ mówi o n-tym rodzicu.
Kolejność rodziców
Mając w historii wielu rodziców, warto wiedzieć jaka jest kolejność, który jest pierwszy, drugi i ostatni…
Zaprezentuję to na przykładzie:
O Merged commit ^ ----|---- ^ ^ | | | | one commit O O two commit
Polecenie git log pokaże następujące wiadomości:
Merged commit powstał przez połączenie one commit i two commit two commnt jest drugim rodzicem rewizji Merged commit one commit jest pierwszym rodzicem rewizji Merged Commit
Czyli pierwszym rodzicem rewizji Merged commit jest one commit, a drugim rodzicem jest two commit.
Mówiąc inaczej, pierwszym rodzicem w historii rewizji, zawsze jest ten najniżej. Gdy spojrzymy na wynik w konsoli, najniższym będzie pierwszy z lewej strony na samym dole. Przykład konsoli:
C:\MojeProjekty\git (master -> origin) λ git log --all --decorate --oneline --graph * 69c417e (HEAD -> master) Merge branch 'twoBranch' |\ | * 857ba5d (twoBranch) Add f (second branch names twoBranch) | * 4f927bf Add e * | a9f7e86 Add d |/ * 61893e8 (tag: v0.0.1) add c * 30be341 Add b * 1af12d9 Add a (first branch names master)
Przodek n-tej generacji
Teraz zidentyfikujemy rewizję za pomocą wcześniej wspomnianym przykładzie X~n. Odwołamy się do n-tego przodka w historii liniowej, czyli takim z jednym rodzicem.
... O X ^ | | O X~1 ^ | | O X~2
W miejsce znaku n podajemy liczbę kroków, o jaką należy cofnąć się w historii. Powyższy przykład mówi nam: X jest dzieckiem, X~1 ojcem, X~2 dziadkiem itp
W miejce X wstawiamy przykładowo znak SHA-1, pełny albo skrócony, można podać HEAD(czyli zaczynamy od dziecka) oraz znaczniki (ang.tags):
git log 61893e857c17378b845d66979951ddefa5431b04 (HEAD -> master) add d 30be34132ab4bb7f2c4a69dce94294f21009f752 add c 1af12d98d1f6146781e4b8e69743bd5bb9cb08c4 add b (tag: v0.0.1) 1aza7898d1f6146781e4b8e789654jkhb9cb08c4 add a //////////////////////////////////////////// 61893~2 - shows 'add b' 61893~3 - shows 'add a' HEAD~1 - shows 'add c' v0.0.1~2 - shows 'add b'
Jeżeli historia rewizji mam kilku rodziców, zapis X~n dotyczny zawsze pierwszego rodzica.
n-ty rodzic
Aby, odwołać się do konkretnego rodzica należy użyć schematu X^n. Tak X^1 wskazuje na pierwszego rodzica, X^2 drugiego itp
Używać komendy X^n możemy tak samo pracować, jak z X~n. Utworzyłem jeden plik a.txt w gałęzi master. Stworzyłem Gałąź A, B i C w każdej z gałęzi robiłem edycje na pliku a.txt. Gałąź główną master scaliłem z gałęziami A, B i C. Obecnie nasz ostatni commit ma plik a.txt, który był edytowany przez 3 różne źródła, teraz doskonale zobaczymy jaki rodzic, jakie zmiany wprowadził za pomocą komendy X^n.
Przykład: (ten przykład wykonuj na konsoli git bash)
touch a.txt vim a //(dokonuje edycji pliku, wpisując przykładowy tekst "Test 1") git add a.txt git commit -m "Add a.txt with text" git log commit be42d1e587684a983e1ebdc2e75122c751292d61 Author: Przemysław JuśkiewiczDate: Sat Apr 10 18:25:41 2018 +0100 //Tworze nowe gałęzie od commit: be42d1e587684a983e1ebdc2e75122c751292d61 git branch A git branch B git branch C //Przechodze do branch A git checkout A //Edytuje plik a.txt vim a.txt (wpisuje "Test 2" git add a.txt git commit -m "Add a.txt with text from branch A" //Te same kroki wykonuje dla branch B i C git checkout B vim a.txt (wpisuje "Test 3" git add a.txt git commit -m "Add a.txt with text from branch B" git checkout C vim a.txt (wpisuje "Test 4" git add a.txt git commit -m "Add a.txt with text from branch C" //Przechodze do gałęzi głównej master git checkout master //Dokonuje scalania branchy A,B i C do master git merge A git merge B git merge C //Podczas merge mogą wystąpić konflikty, nalezy je rozwiązać. //Czyli wchodzimy do pliku a.txt i usuwamy zbędne znaki po za namszymi "test1, test2 itp" //Wydaje polecenie jak poniżej $ git log --all --decorate --oneline --graph * 647636f (HEAD -> master) Merge from C |\ | * fb6960b (C) Change a from C * | 5edb409 Change a from master * | 5b62f45 Merge from B |\ \ | * | b81a745 (B) Add a with text from branch B | |/ * | dcc4281 (A) Add a with text from branch A |/ * 6a6ae4d Add a with text //Teraz będąc w commit:647636f sprawdźmy, ilu rodziców //miał plik a.txt oraz jakie były robione zmiany. //Rodzic pierwszy git show 647636f^1 commit 5edb40975e06c3eb205b22c5366f8cf99dd1c186 Author: Przemysław Juśkiewicz Date: Sat Apr 10 18:27:41 2018 +0100 Change a from master diff --git a/a b/a index 31326ac..a7d686e 100644 --- a/a +++ b/a @@ -1,3 +1,5 @@ Test 1 Test 2 Test 3 +Test 4 //Rodzic drugi git show 647636f^2 commit fb6960b19642853ac635efd4a2b37d0ce8de9990 (C) Author: Przemysław Juśkiewicz Date: Sat Apr 10 18:28:41 2018 +0100 Change a from C diff --git a/a b/a index ac5ab8f..60e9843 100644 --- a/a +++ b/a @@ -1 +1,6 @@ Test 1 + + + + +Test5
Sprawdzanie n-tego rodzica dla danego pliku. Powtarzam po raz kolejny :), Jeżeli nie rozumiesz powyższego przykładu, nie przejmuj się, w kolejnej serii będą wpisy dotyczące gałęzi oraz operacji na nich, wtedy ta podkategoria będzie czytelniejsza. Jedyne co z tego podtytułu należy wiedzieć to, że identyfikacje rewizji możemy robić na wiele sposobów. 🙂
Dziennik reflog
W git posiadamy dziennik reflog, w tym dzienniku zapisywane są identyfikatory bieżących rewizji. Gdy wykonujemy operacje na rewizji i 'zapisujemy’ nasze zmiany, wtedy do dziennika reflog trafiają kolejne wpisy.
Do sprawdzenia zawartości dziennika używamy polecenia: git reflog
Przykład:
touch a.txt git add a.txt git commit -m a touch b.txt git add b.txt git commit -m b touch c.txt git add c.txt git commit -m c git reflog addc5d0 (HEAD -> master) HEAD@{0}: commit: c 05b8f5e HEAD@{1}: commit: b 51d8a85 HEAD@{2}: commit: a
Dziennik reflog jest przydany, gdy chcemy wrócić do stanu kodu przed mergem gałęzi, albo gdy popełnimy jakiś faux-pas i będziemy chcieli wrócić do poprzedniego stanu. Przechodzenie do stanu z danego wpisu z reflog należy użyć polecenia git checkout HEAD@{n}, gdzie n jest liczbą naturalną i oznacza n-ty od góry wpis.
Aby sprawdzić dziennik dla innej gałęzi, należy wydać polecenie git reflog NazwaGalezi.
Przykład:
git branch * master pierwszyBranch drugiBranch git reflog pierwszyBranch //Tutaj pokażą się wpisy prowadzone dla tej gałęzi.
W dzienniku reflog możemy poruszać się nie tylko za pomocą konkretnej liczby, mam tutaj na myśli n z HEAD@{n}. Oprócz tego można użyć jednostki w czasie np: godziny, bądź daty.
Poniższy przykład pokaże nam dziennik reflog z gałęzi master pokazując rewizje ze stanu godzinę temu, czyli wszystkie operacje na rewizjach wykonane jedną godzine wstecz od aktualnej:
git reflog @{1.hour.ago} 647636f (HEAD -> master) refs/heads/master@{Tue Apr 11 16:28:17 2018 +0100}: commit (merge): Merge from C 5edb409 refs/heads/master@{Tue Apr 11 16:26:52 2018 +0100}: commit: Change a 5b62f45 refs/heads/master@{Tue Apr 11 16:26:26 2018 +0100}: commit (merge): Merge from B dcc4281 (A) refs/heads/master@{Tue Apr 11 16:25:53 2018 +0100}: merge A: Fast-forward 6a6ae4d refs/heads/master@{Tue Apr 11 16:24:48 2018 +0100}: commit (initial): Add a with text
Tutaj podobnie ale dostaniemy informację stanu gałęzi master z dnia 11 kwietnia roku 2018 o godzinie 16:30:00
git reflog @{2018-04-11.16:30:00} 647636f (HEAD -> master) refs/heads/master@{Tue Apr 11 16:28:17 2018 +0100}: commit (merge): Merge from C 5edb409 refs/heads/master@{Tue Apr 11 16:26:52 2018 +0100}: commit: Change a 5b62f45 refs/heads/master@{Tue Apr 11 16:26:26 2018 +0100}: commit (merge): Merge from B dcc4281 (A) refs/heads/master@{Tue Apr 11 16:25:53 2018 +0100}: merge A: Fast-forward 6a6ae4d refs/heads/master@{Tue Apr 11 16:24:48 2018 +0100}: commit (initial): Add a with text
Poprawne formaty:
@{yyyy-mm-dd.hh:mm:ss}
@{n.minute.ago}
@{n.hour.ago}
@{n.day.ago}
Aby wyczyścić dziennik reflog, użyjemy komendy:
git reflog expire –all –expire=now
Podsumowanie
Dotarliśmy do końca 🙂 w tym wpisie było dużo informacji na temat rewizji oraz informacji o tematyce, która zostanie poruszona w dalszych wpisach mam tu na myśli temat gałęzi i poruszania się po nich. Informację na temat dziennika reflog są bardzo pomocne, mi w pracy z Git’em ten dzienniczek bardzo pomógł, gdy jeszcze byłem początkującym 'git-owcem’ :D.
Jeżeli coś jest nie jasne, czegoś nie rozumiesz, albo zauważyłeś błąd, bądź po prostu chcesz wyrazić swoją opinię, zapraszam Cię do skomentowania, bądź bezpośredniego kontaktu e-mailowego do mnie 🙂
Pozdro 🙂