Żaden programista nie wyobraża sobie dziś pracy bez systemów kontroli wersji. Wśród nich niekwestionowanymi liderami jest Subversion (znany szerzej, jako SVN) oraz znacznie zyskujący na popularności Git. Na temat historii i możliwości gita znalazłem dziesiątki stron i kilka książek, zatem pominę tę część i postaram się przedstawić praktyki, które mogą ułatwić pracę w zespole programistów.

Commitować wszystko, czy nie wszystko: oto jest pytanie

Co prawda git, z założenia, powinien służyć do wersjonowania plików tekstowych, to warto wersjonować wszelkie materiały związane z pracą nad projektem jak diagramy UML, czy opisy wymagań (nawet, gdy te znajdują się w plikach pdf lub docx). Taki zabieg zapewni dostęp do dokumentacji projektowej każdemu deweloperowi. Unika się za to wersjonowania plików binarnych, pochodzących z kompilacji. Wszelkie .exe, .bin, .pyc powinny być wypisane w pliku .gitignore, którego przykład zamieszczam poniżej.

Kolejnym dylematem jest jak często commitować. Zaleca się jak najczęściej. Dopisanie nowej funkcji: commit. Dodanie nowego pliku: commit. Jest też prosta opcja: git add -p, która pozwoli nam interaktywnie wybrać, co dodać do najbliższego commitu. Nie ma obawy, że takie commity “zajmą dużo pamięci”. Git, w przeciwieństwie do np. SVN-a, zapisuje tylko zmiany, czyli dodanie nowego pliku o wadze 1kB sprawi, że rozmiar repozytorium wzrośnie o 1kB (a nawet mniej, gdyż Git dysponuje całkiem wydajnym systemem kompresji danych). Inną kwestią jest dylemat: czy można commitować coś, co nie działa? Powszechną zasadą panującą wśród użytkowników systemów kontroli wersji jest commitowanie kodu, który da się skompilować. Git rozwiązuje sprawę inaczej: mamy jedną gałąź master, na którą zaleca się wrzucać kod kompilowalny i najlepiej przetestowany, gałąź wspólną, nad którą obecnie pracuje zespół – tutaj wedle ustaleń zespołu, ale też najczęściej kod, który da się skompilować oraz najlepszą część gita: własny branch, na którym możemy robić, co nam się żywnie podoba.

Struktura gałęzi w repozytorium

Skoro już doszliśmy do tematu branchy: dzięki bardzo elastycznemu systemowi “drzewa”, mamy możliwość dostosowania repozytorium do swoich wymagań. Nie ma tutaj z góry narzuconej metodologii, co najwyżej kilka przykładów, jak można porządkować pracę. Pierwszy, chyba najczęściej stosowany w powiązaniu z metodologią SCRUM-ową, to posiadania gałęzi master, zawsze sprawnej, i tworzenie nowego brancha dla każdego sprintu. Następnie z takiego brancha sprintowego odchodzą gałęzie powiązane z konkretnymi zadaniami na dany sprint. Tutaj zależnie od wielkości zespołu. Jeżeli jedna osoba zajmuje się daną funkcjonalnością to sama decyduje o stanie tej gałęzi. Jeżeli wiele, to gałąź znów może się rozchodzić na poszczególnych developerów. Na koniec branche są składane, do nadrzędnych, (ale tylko te, które są sprawne, tj. kompilowalne i najlepiej przetestowane) i dopiero następuje merge do mastera. Merge do mastera kończy dany sprint, a zabawa zaczyna się od nowa wraz z kolejnym sprintem.

Git w praktyce

Merge, rebase i cherry-pick, czyli scalanie zmian między branchami

By efektywnie pracować w zespole, warto nauczyć się także poprawnie merge’ować oraz taggować. Pierwsze – merge’owanie, czyli scalanie zmian dokonanych na dwóch różnych branchach, może być zrobione na kilka sposobów (jak wszystko): rebase oraz merge. Git rebase polega na przeniesieniu danego commita z jednego brancha, na drugi. Niestety: tracimy przez to część historii, bo powstaje złudzenie, że dany commit zawsze był w tej gałęzi. Lepszym podejściem jest użycie git merge, które powoduje scalenie dwóch gałęzi, co jest lepiej widoczne w historii i zapewnia lepszą kontrolę na rozwojem projektu. Jeżeli scalamy dwie gałęzie, np. sprintu w mastera to warto zaznaczyć, że takie zdarzenie miało miejsce. Samo użycie git merge może spowodować, że git sam scali zmiany (czyli nastąpi fast-forward). Dlatego lepiej w takim przypadku wykonać polecenie git merge --no-ff, czyli merge bez fast-forward, który wymusi na git’cie stworzenie oddzielnego commita, opisującego co, skąd zostało zmergowane. Pytanie: jaki sens ma rebase? Przydaje się do sprzątania w celu uniknięcia tworzenia commitów, takich jak poprawianie literówek. Wyobraźmy sobie, że na naszym prywatnym branchu mamy listę commitów na branchu subject_list:

Historia oryginalna, przed rebase
e3ffwty9 Added CSS
s0b64a2 Removed a typo in list name
j9b6la2 Added list to view
j9b6la2 Added list to view
tun832v Created controller for listing subjects

W tym przypadku commit s0b64a2 jest redundantny, używamy zatem polecenia git rebase -i subject_list, co wywoła interaktywny edytor (zapewne VIMa) z listą commitów (starsze na dole): oraz instrukcją, z której wynika, że słowo kluczowe “pick” oznacza by dołączyć dany commit. Szukamy w instrukcji polecenia “squash”, które ściska dany commit z poprzednim. Modyfikujemy zatem listę do postaci:

Przykład interaktywnego rebase
pick e3ffwty9 Added CSS
squash s0b64a2 Removed a typo in list name
pick j9b6la2 Added list to view
pick tun832v Created controller for listing subjects

I zapisujemy. Git przeniesie nas do nowego okna, które służy do edycji nowego commita. Wszystkie niepuste i niezakomentowane linie (czyli bez #) znajdą się w commit message nowego commita. Po edycji wg własnego widzimisię znów zapisujemy i teraz nasz historia wygląda tak:

Historia po rebase
op34ze9 Added CSS
pick ty7bywq Added list to view
tun832v Created controller for listing subjects

Przeglądając commit “ty7bywq Added list to view” znajdziemy zmiany, które wcześniej były rozbite na dwa oddzielne. Warto zauważyć, że rebase tworzy nowe commity, co widać po nowych hashach. Tylko jeden pozostał bez zmian, gdyż nie ruszaliśmy ani jego, ani jego przodków. Taki zabieg warto wykonywać przed pushem do zdalnego repozytorium, gdyż NIGDY, pod żadnym pozorem nie wolno modyfikować zdalnego repozytorium. Jest to zbrodnia porównywalna do nazywania zmiennych / funkcji w stylu zmiennaA, czy funkcja1 – po prostu się tego nie robi. Z rebase warto też korzystać przy okazji pullowania, dzięki czemu nie utworzymy zbędnego punktu w historii, gdy synchronizujemy naszą pracę ze zdalnym repozytorium. Git może w tym przypadku korzystać z rebase automatycznie, jeżeli wcześniej ustawimy flagę pull.rebase na true, np. za pomocą komendy: git config --global --bool pull.rebase true. Jeśli chodzi o łączenie branchy to nie można nie wspomnieć o poleceniu cherry pick, czyli jak nazwa wskazuje, wzięciu wisienki. Polecenie git cherry-pick hash wybiera zmiany dokonane we wskazanym commitcie i scala je z aktywną gałęzią. Wyobraźmy sobie sytuację, że pracujemy nad sprintem, a w tym czasie wykryto i naprawiono buga na masterze. Jeżeli Bug ma wpływ na nasz obecny sprint to warto wprowadzić hotfix u nas, ale najlepiej identyczny z już zrobionym. W tym celu pobieramy wisienkę z mastera, czyli: git cherry-pick hash_z_hotfixem i cieszymy się poprawionym kodem. Cherry pick kopiuje tylko commit, który mu wskażemy, na początek brancha nad którym pracujemy.

Git w praktyce

Na pierwszy rzut oka: cherry-pick jest tak “subtelny”, że niemal nie widać różnicy

Git w praktyce

Tagi – etykietowanie kamieni milowych w projekcie

Następnym zagadnieniem, które warto poruszyć to tagowanie, czyli szczególne oznaczenie konkretnego commita, np. realease’u. Git udostępnia dwa rodzaje tagowania: proste i z adnotacją. W prawdziwych projektach nie powinno się stosować prostego modelu, gdyż polega ono na nadaniu nazwy jakiemuś commitowi, zaś w praktyce: git tworzy coś na kształt brancha. Prawdziwy tag zawiera adnotację, w której znajdziemy, oprócz nazwy, opis etykiety, datę utworzenia, oraz dane autora. Dokonujemy tego korzystając z polecenia git tag -a, domyślnie oznaczymy tym ostatni commit, jeśli dodamy hash konkretnego commita, to jego oznaczymy. Etykiety to nie tylko dekoracja, pozwalają sprawniej poruszać się po repozytorium. Możemy je przeszukiwać, np. poleceniem git tag -l 'v1.0.*', które zwróci wszystkie tagi zaczynające się od v1.0, albo wypisać dane commita, który opisują git show nazwa_taga.

Proste zasady dobrych commit message’y

Git w praktyce

Być może powinienem był od tego zacząć: commity. Standardowy kształt to po prostu jednolinijkowy opis (max 50 znaków), po którym będziemy w stanie określić, co zostało zrobione (patrz rysunek). Trzymając się zasady commitować małe rzeczy, ale często, nie powinno być z tym problemu. Większe commity, np. feature do sprint brancha, a już na pewno WSZYSTKIE do mastera powinny być bardziej szczegółowo opisywane w formacie: jedna linijka głównego opisu, pusta linijka, i dopiero długi, skrupulatny opis, co wnosimy danym commitem. Taki format się przydaje, gdy chcemy wysłać maile z pomocą gita. Wtedy mamy wyraźny rozdział na temat i treść maila. Istnieje też drugi powód, by odróżniać temat od treści commita: wpisując git shortlog uzyskamy listę commiterów wraz z wylistowanymi tytułami ich commitów.

Przykładowy efekt polecenia git shortlog
$git shortlog
Daszczu (1):

Initial commit

Leszq (3):

Basic project architecture
Documentation
Merge remote-tracking branch ‘origin/master’

Misiu (6):

updated .gitignore
deleted .suo
new user attributes
user profile created
hook test Signed-off-by: Misiu

andrut (1):

Initial database

Hooki – automatyczna kontrola pracy z repozytorium

Jeżeli nawet ustalimy sobie w zespole jakieś reguły commit message’y, to może się zdarzyć, że ktoś się zapomni. Jak już pisałem: co na serwerze, na serwerze zostać musi. Tutaj przychodzą nam z pomocą tzw. hooki. Są to skrypty, umieszczone w katalogu .git/hooks, które wykonują się w zależności od akcji użytkownika. Gdy wejdziemy do ww. katalogu znajdziemy kilka przykładowych skryptów napisanych w bashu. Aby je aktywować wystarczy usunąć rozszerzenie “.sample”. Np. odblokowując prepare-commit-msg i odkomentowując ostatnie dwie linijki sprawimy, że każdy commit będzie miał dodane w treści dane autora.

Plik: git/hooks/prepare-commit-msg

Ten hook otrzymuje jeden parametr: ścieżkę do pliku commit message

 

#!/bin/sh

SOB=$(git var GIT_AUTHOR_IDENT |sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')

grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"

Inny przykładowy hook to update, który blokuje możliwość przyjmowania tagów bez adnotacji – bardzo przydatne. Niestety ten, aby być użytecznym, musi się znajdować na serwerze zdalnym, gdyż nie blokuje tworzenia prostych tagów, ale uniemożliwia przyjęcie ich od kogoś innego. W Internecie znajdzie się naprawdę dużo przykładowych hooków. Warto też wiedzieć, że mogą być pisane w dowolnym języku skryptowym, jak python czy perl. Wystarczy, że będą miały dostępny interpreter (#!/bin/python, #!/bin/perl, #!/bin/bash).

Aliasy, czyli droga na skróty

Niektóre polecenia wykorzystujemy po kilkadziesiąt razy dziennie, zwłaszcza, gdy mają dodatkowe parametry, warto je sobie zapisać. Git udostępnia funkcjonalnośc zwaną aliasami, każdy może zdefiniować sobie własne, wpisując w konsoli: nazwa_aliasu = polecenia, które byś wpisał po git Co potem wywołujemy poleceniem git nazwa_aliasu. Ja postaram się przedstawić kilka, z których korzystam najczęściej:

Alias Efekt
lg =log –graph –format=’%C(yellow bold)%h%Creset %C(bold blue white)%d%Creset %C(white bold)%s%Creset%n %C(magenta bold)%cr%Creset %C(green bold)%an%Creset’ Mój ulubiony alias – w przestępny i kolorowy sposób prezentuję drzewo aktywnego brancha, a po dodaniu parametru –all (git lg --all) całego repozytorium.
lasttag = describe –tags –abbrev=0 Wypisuje ostatni tag na obecnym branchu
brclean = “!f() { git branch –merged ${1-master} | grep -v ” ${1-master}$” | xargs -r git branch -d; }; f” Czyszczenie repozytorium z branchy, które zostały zmerge’owane do mastera – przydatne, sprzątanie przy dłużej żyjących projektach
lf = log –pretty=’%C(yellow bold)%h%Creset %C(bold blue white)%d%Creset %n %s %C(green bold)[%cn]’ –numstat Wypisuje jakie pliki zostały zmienione w poszeczególnych commitach (numrki oznaczają linie dodane / linie usunięte)
Coś dla osób, które pracowały z SVN-em:
st = status Jeżeli już ktoś zagląda do tej sekcji, to pewnie wie, co robią te skróty ;-)
ci = commit
co = checkout
df = diff
up = pull

Skrytka: git stash

Jest Jeszcze jedna, użyteczna opcja w git’cie: git stash, ale wydaje mi się, że często zapomniana. Standardowy przykład zastosowania: jesteśmy w trakcie pracy na nową funkcjonalnością i nagle przychodzi przełożony: zrób mi coś na teraz. Teraz powstaje problem: co zrobić z rozgrzebanym kodem? Niestety większość użytkowników po prostu commituje zmiany, bierze inny branch i na nim robi zadanie od szefa. Lepszym podejściem będzie “odłożenie na półkę” dokonanych zmian, a następnie ich zaaplikowanie na nowo. Polecenie git stash zapamięta wszelkie, niezacommitowane zmiany i przywróci stan kopii roboczej do ostatniego commita. Jest to prawie to co, jakbyśmy zacommitowali, ale nieco mniej roboty (jedno polecenie vs 2). Natomiast warto znać dodatkowe przełączniki: git stash -u, które doda wszystkie nie wersjonowane pliki (untracked) oraz git stash -a, które zapamięta wszystko (all), co jest w danej chwili w kopii roboczej. Nie ważne którą opcję wybierzemy: po wykonaniu zadania dodatkowego, przywracamy stan pracy poleceniem git stash pop i kontynuujemy ją.

Jak jeszcze ułatwić sobie życie?

Na koniec chciałbym przedstawić kilka dodatkowych funkcji, które przydają się w dużych projektach. Po pierwsze: kogo obwinić (ang. blame), że wpisał linijkę kodu, która psuje program? Służy do tego polecenie git blame ścieżka_do_pliku, która wypisze kto jest autorem każdej linijki w pliku.

Przykład wyniku dla polecenia: git blame major_changes.latex
28d64132 (Tomasz 2015-07-15 11:07:27) \item changing main.py – DONE
f6eccc78 (Tomasz 2015-07-08 10:56:20) \item stats generation -DONE
3101436b (Vesemir 2015-06-24 11:16:24) \item typo in theme – DONE
92dbc83e (Vesemir 2015-06-17 11:27:17) \item performance tests uncompleted
a46077f6 (Vesemir 2015-05-13 11:19:19) \item another step in server configuration – DONE
28d64132 (Tomasz 2015-07-15 11:07:27) \item network issues solved
f66ccc78 (Tomasz 2015-07-08 10:56:20) \item replaced colors
28d44132 (Tomasz 2015-07-15 11:07:27) \item \textcolor{medium-gray}{build improvements – TODO}
a46077f6 (Vesemir 2015-05-13 11:19:19) \item \textcolor{medium-gray}{changes in hotspot – TODO}
1ae58e56 (burny 2015-03-04 09:41:19) \item \textcolor{medium-gray}{script for setup – TODO}
9464ce99 (andrut 2014-10-15 08:07:33) \end{enumerate}

Kolejną wartą uwagi funkcją jest możliwość przeszukiwania brancha. Na przykład poniższe polecenie: git log -S main.py --author zgredek --before="2015-08-15 00:00" --after="2015-08-01" wypisze wszystkie commity, utworzone między 1 a 15 sierpnia 2015 roku, autorstwa zgredka, w których zmienia się ilość wystąpień słowa “main.py”, czyli zostaje dodana linijka np. import main.py, albo usunięta. Naturalnie parametry autora, czasu utworzenia są nieobowiązkowe. Za jedną z największych zalet SVN-a uważam możliwość pobrania tylko konkretnego pliku / folderu. Niedawno dowiedziałem się, że jest to też możliwe za pomocą gita! Wystarczy użyć polecenia git checkout commit_hash sciezka/do/pliku. Dodatkowo, podobnie jak w SVN-ie można wybrać gdzie ma się znaleźć dany plik. Wystarczy skorzystać z parametru --work-tree, np.: git --work-tree=/ścieżka/gdzie/checkoutujemy/ checkout HEAD src/main.py

Podsumowanie

Ukazując w niniejszym artykule zaledwie kilka z potencjalnych możliwości gita posłużono się opisami właściwości i przykładami użycia, zachęcając drogich czytelników do samodzielnej zabawy i do poszukiwania kolejnych przydatnych zastosowań. Projekt git powstał w 2005 roku i w porównaniu ze starszymi systemami kontroli wersji można dojść do wniosku, że podbija serca programistów, zauważając wciąż rosnącą popularność. Poniższy wykres może to tylko potwierdzić.

Git w praktyce

Skoro od czasu powstania git zdążył zdobyć tak wielką popularność, to z pewnością jego możliwości zdążyły zachwycić użytkowników. Git, jako projekt należący do wolnego oprogramowania, jest wciąż rozwijany przez programistów na całym świecie, więc ten wachlarz możliwości będzie rósł. Może, więc warto, chociaż tylko spróbować i sprawdzić, dlaczego tak bardzo git stał się królem wśród systemów kontroli wersji?

  • Paweł

    Ostatnio pojawiają się ciekawe artykuły, nowa szata graficzna cieszy oko, ale nie byłbym sobą, gdybym się nie przyczepił ;)

    Powiedzcie mi proszę, po co w ogóle dawać napisy małą czcionką, w kolorze obrazka w tle, skoro są nieczytelne lub trudne do odczytania (szare na szarym, szare na czerwonym)? Owszem wygląda to ładnie, ale mnie osobiście drażni, jeśli widzę jakiś tekst, ale trzeba się wpatrywać albo zaznaczać myszą aby go odczytać. Poza tym nie mam uwag :)

    • Jakub Konieczny

      Zapewne relikt starego stylu.

    • o_O

      Wystarczyłoby dodać cień i trochę jaśniejszy odcień szarości.
      Regułka dla Stylisha na szybko:
      .entry-crumbs *, .meta-info * {
      text-shadow: 0 0 3pt black !important;
      color: #ccc !important;
      }

    • Poprawione ciut.

  • asd

    Uczę się właśnie gita, muszę przyznać że tylko jakiś zryty umysł mógł coś takiego wymyślić. Mimo wszystko dzięki za artykuł, od siebie polecam początkującym pobawić się tym: http://pcottle.github.io/learnGitBranching/

    • Jakub Konieczny

      GIT jest dziełem tego samego zrytego umysłu który stworzył Linuksa ;) To był hejt na firmę, która wcześniej hostowała Kernela.

    • o_O

      To nie był hejt, tylko chore wymogi tej firmy od BitKeepera, aby użytkownicy (devowie kernela) podpisali lojalki, że w żadnym swoim produkcie nie wykorzystają logiki działania ich systemu kontroli wersji.
      Więc Linus uznał, że czas stworzyć otwarty system, który będzie odpowiadał potrzebom projektu kernela.
      Teraz pewnie ta firemka od BitKeepera plusie sobie w brodę, o ile jeszcze istnieje…

    • Roman syn Ryżu

      Użyj jakiegoś graficznego interfejsu. Choćby Github for Desktop. Będzie dużo łatwiej.

    • o_O

      Tak, i zamiast logiki działania gita nauczy się klikać w kolorowe ikonki, które magicznie robią “to co potrzeba”.

      Osobiście nie zatrudniłbym kogoś takiego nawet na stanowisko juniora, bo używanie GUI bez znajomości logiki pod spodem oznacza wiele tragicznych problemów takiego człowieka: nie interesuje go dogłębne poznanie problemu, zadowala się połowicznymi rozwiązaniami, które będzie sklejał na ślinę, itd.

      Tak samo jeśli ktoś umie tylko kliknąć “Run” w IDE, a nie ma pojęcia o procesie kompilacji i sam nie umiałby napisać prostego Makefile czy użyć gcc z linii poleceń (odsyłam do http://osworld.pl/kompilacja-w-gcc-krok-po-kroku), to jest na dobrej drodze do bezrobocia albo pracy jako code-monkey w jakimś java-kołchozie gdzie jakość kodu jest na ostatnim miejscu.

      Wiedzę można uzupełnić, ale podejście do pracy trudno zmienić.

    • Roman syn Ryżu

      Nie zgodzę się. Moim zdaniem trzeba korzystać z narzędzi na które pozwala nam doświadczenie. Narzędzia zmienia się, gdy poprzednie przestaną wystarczać. Wtedy nabiera się mniej złych nawyków.

    • o_O

      Ja też się nie zgodzę.

      Narzędzi można używać wtedy, gdy już się umie to robić, inaczej można zrobić sobie i innym krzywdę.
      Jak poznasz na czym polega rzecz, którą robisz, to potem “dla wygody” możesz użyć sobie IDE. Choć ja w graficznych nakładkach wygody nie widzę. Wolę automatyzować czynności skryptami, które potem lecą do repo razem z kodem, co zresztą jest zgodne z duchem continuous integration.

      IDE to narzędzia dla amatorów i code-monkey, i to tylko tych, którzy tego poziomu nigdy opuścić nie zamierzają.
      Dopuszczanie takich osób do kodu jest niebezpieczne. Efekty widać wszędzie dookoła – jakość na zerowym poziomie i wymagania sprzętowe z kosmosu (nie dosłownie, bo żeby polecieć w kosmos wystarczył znaczniej słabszy sprzęt niż dzisiaj do odpalenia najprostszej gierki czy nawet programu księgowego).

    • Gienek

      “IDE to narzędzia dla amatorów i code-monkey […]”
      To zależy. Moim zdaniem chodzi o dobrze wykonaną robotę a nie jakiś wzięte z kapelusza “ideały” i “powinności”. Jeśli X potrafi wykonać tą samą robotę w IDE w krótszym czasie, niż osoba Y w konsoli, to wolę zatrudnić X niż “profesyjonaliste” Y. To są tylko narzędzia i bycie efektywnym się liczy a nie bycie “fajnym”, bo umiem klepać kod w vimie. Moim zdaniem narzędzia to sprawa drugorzędna. Nie mam nic do narzędzi konsolowych czy GUI, ale szefa interesuje szybko, dobrze i niezawodnie wykonana praca, anie dyrdymały czy ktoś to zrobi w konsoli czy GUI czy może sam coś napiszę choćby w asemblerze. Szczerze nie rozumiem skąd przekonanie, że konsola jest lepsza od GUI. Masz może jakieś badania lub statystyki na poparcie tej hipotezy? Chętnie dowiem się czegoś nowego.

      Można używać konsoli i być code-monkey. Używanie konsoli nie sprawi, że staniesz się świetnym developerem.

      Natomiast zgodzę się z tobą, że używanie narzędzi (nieważne czy konsola czy GUI) nie zwalnia ze znajomości jak coś działa “pod maską”, bo taka wiedza często jest bardzo przydatna.

    • o_O

      Nic nie zrozumiałeś. Przeczytaj mój komentarz jeszcze raz.

      A X niech lepiej zrozumie co robi, bo klikanie w ikonki bez pojęcia co się robi nigdy się dobrze nie kończy.

      W prawdziwych, dużych projektach wszystko i tak jest automatyzowane, ot choćby takim graddle, gulp czy bamboo. I tam wszędzie musisz powpisywać polecenia albo skrypty. A nie jak małpka klikać ikonki.

    • AbC

      Heh, rozumiem, programista… Czyli każdy kto korzysta z framework’ów to od razu
      bot i go nie zatrudnisz bo nie umie programować, nie wie co się tam
      dzieje w kodzie przecież. Przedstawiasz takiego kolesia co cały czas
      ubabrany w konsoli klepie i klepie, a chłopak inny mądry nauczy się i
      zacznie korzystać z GUI bo szybciej i wygodniej. Ale musi wyskoczyć taki
      konsolowy łepek jak Ty i będzie tego zwalniał tego zatrudniał. Daj
      spokój, bo może programować umiesz, ale generalizowanie nie postawia Cie
      w dobrym świetle w kwestii człowieka myślącego i doświadczonego
      życiowo.

    • o_O

      Framework ma swoje API. Nie muszę wiedzieć co jest poniżej, ma działać.

      Git nie ma już prostszego “API” niż to w konsoli. Jeśli upraszczasz je za pomocą GUI i magicznych ikonek, to znaczy, że ukrywasz pewne fakty przed noobami. A to jest niebezpieczne i świadczy, że ktoś niekompetentny chce zrobić coś w moim projekcie.

      Nie mam nic przeciwko GUI jako uzupełnienie konsoli dla profesjonalistów. (sam często gitk używam, żeby podejrzeć sobie commity). Ale najpierw musisz znać polecenia i rozumieć co robisz, a GUI używać dla wygody (o ile uznasz GUI za wygodne). Ty sugerujesz, że GUI jest po to, żeby ktoś kto nie wie jak używać gita mógł z nim pracować – to niebezpieczne i karygodne podejście.

    • o_O

      Zryty umysł to musieli mieć ludzie od csv, które było popsute by design, oraz subversion, które strzelało sobie w stopę będąc “csv-em zrobionym lepiej”.

      Git to piękny system, wszystko jest tam proste (“wszystko jest wskaźnikiem na commit”), a możliwość używania jego mocy offline dopełnia destrukcji konkurencyjnych bubli.

      Zanim wyrazisz opinię poświęć trochę więcej czasu i wreszcie naucz się tego narzędzia.

    • o_O

      csv -> cvs
      tak dawno tego polecenia nie używałem, że te 3 litery układają mi się tylko w jeden akronim ;)

    • o_O

      http://pcottle.github.io/learnGitBranching/
      Nie działa na Firefoxie.
      I wygląda jakby nadmiernie komplikowało proste rzeczy. Mnie odrzuciło od samego początku.

  • Ten ktoś

    Fajny tekst jednak ja jakoś wolę rebase zamiast merge. Po pierwsze widać historię commitów (a nie np. Merged from…). Może to być istotne jeżeli usuwamy dany branch po operacji scalania. Ale może źle myślę?

    • o_O

      Zdecydowanie.
      Merge commity to przy typowej deweloperce czyste zło i są często zabronione w zespołach projektowych. I bardzo słusznie. Masz nałożyć swoją zmianę na koniec gałęzi, a nie doklejać na ślinę swój stary commit do aktualnego stanu gałęzi robiąc “poprawki”.
      Dlatego np. w gerricie masz tylko prosty automatyczny rebase. Nie rebasuje się? Popraw commit.
      A w przypadku pojedynczych commitów jest jeszcze niezastąpiony cherry-pick.
      Merge commit ma uzasadnienie tylko przy (back)portowaniu zmian, gdzie chcesz zachować oryginalny commit i dodatkowo pokazać co zostało zrobione dla nałożenia go na inną gałąź/wersję.

  • o_O

    Z dobrych praktyk: pracując na końcu jakiejś gałęzi upstremowej zawsze rób jej kopię w postaci własnej gałęzi i dopiero na niej twórz swoje commity. Nawet w lokalnym repo wszystkie gałęzie istniejące zdalnie powinny zawsze być czyste, aby w dowolnej chwili móc się na nie przełączyć mając pewność co do ich stanu. A już zbrodnią jest praca lokalnie na masterze, a potem szukanie ostatniego commita oryginalnego mastera i żonglowanie własnymi zmianami.

    • R

      A wskaźniki do zdalnego repozytorium nie wystarczą?

      $ git reset –hard origin/master

      Może lepiej jeszcze z dwie – trzy kopie lokalnej gałęzi w lokalnym repozytorium stawiać, bo a nuż…

    • o_O

      Nie wystarczą.
      Reset to opcja (nad)używana w 99% przez idiotów.

      Jak masz swój commit na górze mastera, a masz cherrypickować inny i nałożyć go na czystego mastera żeby zrobić mu weryfikację i code review? To co zrobisz? Zapiszesz sobie swój commit id na kartce?
      Z tymi dwoma czy trzeba kopiami to trafiłeś jak kulą w płot, bo chyba nie wiesz jak działa git.

    • R

      Przepraszam. Już wykupiłem bilet na pielgrzymkę do Częstochowy w ramach zadośćuczynienia.

      Jak masz swoją rewizję na górze gałęzi master, to zrobiłeś elementarny błąd, bo nie pracuje się na masterze, do mastera się merdżuje. Ale jeśli już ten drobny fakt pominąć i przyjąć, że masz już ten swój “commit” na górze “mastera”, to znaczy, że możesz już swój boski “code review” robić na takim właśnie masterze. Poza tym “code review” lepiej chyba przeprowadzać po prostu na gałęzi autora, ewentualnie odgałęziając się od tejże aby wprowadzić swoje poprawki.

      Bo co z tym “code review” zrobisz po boskim “cherry-pick”? Każesz koledze wykonać kolejnego cherry-picka? Kilka takich manewrów i też możesz wpłacać na pielgrzymkę, kolego.

  • R

    Fajny artykuł, widać że dużo pracy włożone. Mam jednak bardzo mocne zastrzeżenia co do zaciągania (w tym nieumiejętnego) terminów z angielskiego na polski. Na bogów (starych i nowych) — nie stosujcie nigdy w życiu takich potworów jak “git’cie” !!! Czy normalnie brzmi zdanie “Ale masz fajny napis na swoim t-shirt’cie!” ?? Piszesz normalnie : “Dobre praktyki w Gicie, czyli…”, na litość…
    Poza tym kilka literówek (przestępny i kolorowy sposób), oraz cała masa kalek z angielskiego. Wiem, że to trudne, ale w języku polskim naprawdę mamy odpowiedniki wszystkich “commitów” (rewizja), “branchy” (gałąź) i “tagów” (etykieta, znacznik). Nawet “hook” można ładnie używać jako “hak” – w końcu skoro robią to angielskojęzyczni (u nich “hook” to właśnie “hak”), to dlaczego po polsku miałoby to być niemożliwe?

    • Tomek

      Cześć,z tym jak pisać o Gicie jest nieco
      problematyczne.
      Jeżeli “git” to nazwa własna to OK, masz rację, wtedy odmieniamy jak
      inne rzeczowniki, czyli np. Gita, Gitem, ale! Ale powinno być “Git’cie”,
      gdyż w tym przypadku ostatnia głoska tematu jest niema i powinna być
      zaznaczona. T-shirt jest słowem przyjętym w języku polskim i podlega już
      naszej “rodzimej” odmianie.

      Dodam tylko, że kwestia
      odmiany jest dyskusyjna i tylko wyjaśniam czym ja się kierowałem. O
      odmianę Gita najlepiej spytać kogoś po polonistyce.

      Jeżeli
      zaś chodzi o polskie odpowiedniki nazw. Pracując naprawdę rzadko używa
      się polskich określeń, sam z tym walczę w pracy (np. używają słów
      “gałąź” lub “etykieta”), ale tłumacząc komuś zasady działania Gita
      naprawdę łatwiej jest używać angielskich określeń, zwłaszcza, że są
      zgodne z tym, co “wpisujemy w konsolę” i praktycznie powszechnie
      akceptowalne.

      Na koniec: słowo “commit” nie ma odpowiednika
      w języku polskim. Commitowaniem możemy nazwać czynność commitowania
      (wtedy “rewizja” nie pasuje), bądź pojedynczy pakiet zmian, których
      oznaczeniem jest rewizja (czyli ten ciąg znaków), wtedy można mówić o
      rewizji.

    • o_O

      +1 dla niezmieniania liter w “git” przy odmianie. Bez znaczenia z jakich to wymyślnych powodów i mądrych zasad. Po prostu git jest tak krótkim słowem, że zaciera się jego znaczenie przy zamianie “t” na “c”.

      “otaguj tego brancha, a potem wcommituj swojego patcha” :)

      Oczywiście, że tak jest prościej. Też nie lubię “gałęzi”, choć do tego idzie przywyknąć. Ale reszta to już tłumaczenie na siłę.

    • R

      Za krótki, to Ty masz rozum.
      Czytajcie więcej książek chłopaki, to nie boli a może nawet dzięki temu jakąś dziewczynę uda wam się zagaić kiedyś…
      A słowo “Git’cie” to mój zdecydowany faworyt – proponuję nagrodę od PWN! (bombonierkę).

    • R

      Jeszcze mnie oświeciło. Jak już nie wiesz jak odmieniać, to pozostaw nieodmienione. Dużo lepiej czytałoby się “Dobre praktyki w Git, czyli zbiór…”

  • WalDo

    Mam pytanie dotyczące aliasów. Autor pisze “wpisujemy w konsoli”. A jak wejść do tej konsoli?

    Czy może chodzi o standardowe aliasy basha?

    • Tomek

      [alias]
      lg = log –graph –format=’%C(yellow bold)%h%Creset %C(bold blue white)%d%Creset %C(white bold)%s%Creset%n %C(magenta bold)%cr%Creset %C(green bold)%an%Creset’

      lasttag = describe .tags .abbrev=0

      Tak powinien wyglądać .gitconfig (w Twoim home)

      natomiast używasz:

      /geronimo_project $ git lg

      /geronimo_project $ git lasttag

    • WalDo

      OK. Dzięki.
      Zabrakło informacji, że trzeba taką sekcję dodać w .gitconfig. Zrozumiałem, że to bezpośrednio w “git shell” się wpisuje

    • Tomek

      You are welcome ;-)