Zabawy z aliasami i gitem ciąg dalszy. Celem dzisiejszego ćwiczenia jest stworzenie kilku przydanych aliasów, które pozwalają posprzątać lokalne repozytorium z nieprzydatnych rzeczy.

Co to są aliasy?

Podobnie jak w bashu, aliasy w gicie służą do „skracania” długich poleceń. Najsłynniejszym zbiorem aliasów dla gita jest to repozytorium. Więcej wiedzieć nam nie trzeba.

Co i dlaczego chcemy sprzątać?

W skrócie chcemy usunąć wszystkie „martwe” gałęzie z lokalnego repozytorium. Przez pojęcie „martwej” rozumiem gałąź której nie ma w żadnym repozytorium zdalnym (remote). Chcę też stworzyć alias, który „posprząta” przy powrocie na główną gałąź. Motywacja do takiego sprzątania jest dość prosta. Chcę ograniczyć wielkość lokalnego repozytorium. W dodatku mój sposób pracy z gitem opiera się o pracę na jednej gałęzi, mergu i usunięciu jej ze zdalnego repo. Jeżeli z jakiegoś powodu potrzebuję wrócić do tej gałęzi, to tworzę ją od nowa. Dzięki temu unikam problemów związanych z synchronizacją pomiędzy gałęziami. Gałąź, na której pracuję, nie ma żadnych commitów, które dogrywają do niej jakąś zewnętrzna zawartość z innych gałęzi. Dopiero na koniec robię rebase z gałęzią, od której się odbiłem i rozwiązuję potencjalne konflikty.

Dodatkowo chcę trochę zmniejszyć ilość naciśnięć przycisków i mieć jakieś śmieszne polecenia.

git exterminatus

To już pierwszy cel mamy wypełniony. Nasz alias będzie nazywał się exterminatus. Chcemy teraz znaleźć wszystkie martwe gałęzie. Posłużą nam do tego polecenia git pull --prune i git branch --vv. Zanim jednak użyjemy tych poleceń, to krótkie przygotowanie. W jakimś repozytorium odbij gałąź z master. Następnie zrób jakieś zmiany, wyślij do repo zdalnego i tam zmerguj. Następnie w zdalnym repo usuń zmergowaną gałąź. Następnie wróć na gałąź master i zrób prosty git pull:

Listing 1. Stan wyjściowy

koziolek@koziolek-desktop3 ~/workspace/git-configuration-aliases (aliases) $ git co master 
Przełączono na gałąź „master”
Twoja gałąź jest na bieżąco z „origin/master”.
koziolek@koziolek-desktop3 ~/workspace/git-configuration-aliases (master) $ git pull 
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
Rozpakowywanie obiektów: 100% (1/1), 886 bajtów | 886.00 KiB/s, gotowe.
Z github.com:Koziolek/git-configuration
   09f005a..5f1e29b  master     -> origin/master
Aktualizowanie 09f005a..5f1e29b
Fast-forward
 bash/bash_rc   | 6 ++++++
 git/aliases    | 1 +
 git/git_config | 4 ++++
 3 files changed, 11 insertions(+)

Teraz wykonaj po kolei git branch --vv, git pull --prune i jeszcze raz git branch --vv

Listing 2. Stan po zmianach

koziolek@koziolek-desktop3 ~/workspace/git-configuration-aliases (master) $ git branch -vv
aliases        7e69d99 [origin/aliases] add new aliases
+ feature/-split 208f795 (/home/koziolek/workspace/git-configuration) [origin/feature/-split] local store
* master         5f1e29b [origin/master] Merge pull request #6 from Koziolek/aliases
  koziolek@koziolek-desktop3 ~/workspace/git-configuration-aliases (master) $ git pull --prune
  Z github.com:Koziolek/git-configuration
- [usunięto]        (brak)     -> origin/aliases
  Już aktualne.
  koziolek@koziolek-desktop3 ~/workspace/git-configuration-aliases (master) $ git branch -vv
  aliases        7e69d99 [origin/aliases: nie ma] add new aliases
+ feature/-split 208f795 (/home/koziolek/workspace/git-configuration) [origin/feature/-split] local store
* master         5f1e29b [origin/master] Merge pull request #6 from Koziolek/aliases

Jak widać ja pracuję z gałęzią aliases. Gałąź ta po operacjach na zdalnym repozytorium nadal istnieje lokalnie. Wykonanie git pull --prune usunęło tylko informacje o zdalnej gałęzi. Widać to po drugim wykonaniu git branch -vv, gdy przy nazwie zdalnej gałęzi pojawia się komunikat nie ma. Wykorzystamy to teraz do napisania naszego aliasu. Będzie to alias - funkcja, dzięki czemu będzie można wykonać kilka poleceń w sensowny sposób. Zdefiniuję ją od razu w pliku konfiguracyjnym gita:

Listing 3. Alias exterminatus

alias.exterminatus=! f() { git branch -vv | grep ': nie ma]' | awk '{print $1}' | xargs git branch -D;}; f

I teraz ciekawostka, to zadziała jedynie, gdy mamy ustawiony język polski w terminalu. Git używa translacji do wyświetlania komunikatów, więc musimy wymusić „jedyny słuszny” język:

Listing 4. Dodajemy konfigurację języka

alias.exterminatus=! f() { LANG=en_GB git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D;}; f

Uruchommy zatem naszą nową zabawkę i zobaczmy co się stanie

Listing 5. Czas na exterminatus

koziolek@koziolek-desktop3 ~/workspace/git-configuration/bash (master) $ git branch -vv
  aliases        7e69d99 [origin/aliases: nie ma] add new aliases
  feature/-split 208f795 [origin/feature/-split] local store
* master         5f1e29b [origin/master] Merge pull request #6 from Koziolek/aliases
koziolek@koziolek-desktop3 ~/workspace/git-configuration/bash (master) $ git exterminatus
Usunięto gałąź aliases (wskazywała 7e69d99).
koziolek@koziolek-desktop3 ~/workspace/git-configuration/bash (master) $ git branch -vv
  feature/-split 208f795 [origin/feature/-split] local store
* master         5f1e29b [origin/master] Merge pull request #6 from Koziolek/aliases

Działa i armaci. Podobny efekt możemy uzyskamy uruchamiając git remote prune dla każdego zdalnego repozytorium, czyli w pętli. Jednak polecenie to działa potwornie wolno (wykonuje zapytanie po sieci). W naszym przypadku pracujemy lokalnie i zakładamy niejawnie, że repozytorium już jest aktualne.

git home

Kolejny alias, który chcę wam pokazać, to powrót do „domu”. Gałęzi głównej. To proste polecenie wykorzysta rev-parse i trochę awk:

Listing 6. Go home git you are trunk

home = "! BRANCH_NAME=$(git rev-parse --abbrev-ref origin/HEAD | awk '{ split($0, arr, \"/\"); print arr[length(arr)]; }'); git checkout $BRANCH_NAME;"

I na koniec możemy połączyć te dwa aliasy w jeden:

Listing 7. Sprzątamy w domu

clean-home = "! git home && git exterminatus"

Wesołego kernela!