Git pro mě/Psaní zdrojového kódu v týmu
Ne vždy na zdrojovém kódu pracuji sám. Pravda je taková, že tým toho udělá víc. Když ví, jak spolupracovat. Tohle bude trochu delší poznámka a určitě potřebuji vědět, jak na Psaní zdrojového kódu skriptu i Psaní zdrojového kódu nové funkce.
V každém novém repozitáři je první commit
git commit -m'Add license, readme'
kde README píšu pro sebe. Chci vědět, CO je pointa, protože do zítra to zapomenu. Občas to, co si napíšu zní dost divně, takže přidám PROČ zrovna to. Navíc do README přidám JAK dělat věci, které dělám pořád (třeba jak projekt zkompilovat). A v neposlední řadě KAM a KOMU napsat dotaz či bug report (komunikační kanál).
Role v týmu
[editovat | editovat zdroj]Ať chci nebo ne, členové vývojového týmu mají tři různé kompetence:
- Vývojář upravuje zdrojový kód a změny posílá k review.
- Reviewer kontroluje a komentuje změny a vrací je k přepracování, čímž s vývojářem vytvoří nejlepší možnou sadu změn, která implementuje novou funkci.
- Maintainer má za úkol různé sady změn zkontrolovat a začlenit do projektu.
Začlenění sady změn je cíl všech členů týmu!
Teď ještě pár poznámek o tom, co by každý člen týmu měl o Gitu vědět, a jak by spolu měli komunikovat.
Git pro vývojáře
[editovat | editovat zdroj]Jako vývojář implementuji nějakou funkci a to v samostatné větvi. Při vytváření nové větve se na ni chci rovnou přepnout, takže spojím dva příkazy:
git checkout -b NOVA-FUNKCE
Jako vývojář mám zodpovědnost za sadu změn, nikoli za zdrojový kód. To je úkol maintainera. Abych vytvořil rozumnou historii, používám
git diff git add -p git diff --cached git commit -m'52 znaků dokončujících větu'
a tu větu už znám, zní "When applied, this patch will ...".
Jo, ještě... proč že to mám, jako vývojář, zodpovědnost za sadu změn? A proč že má být rozumná? Protože jako vývojář sadu změn pošlu k review! A protože vývojář většinou funguje zároveň jako reviewer pro další členy týmu, tak posílám sadu změn, kterou bych sám chtěl kontrolovat.
Git pro Reviewera
[editovat | editovat zdroj]Kód se píše jednou, ale čte se hodněkrát. Úkol reviewera je tenhle poměr změnit, aby to bylo alespoň trochu fér.
Jako reviewer se podívám na každý commit v sadě změn. Jako první si přečtu commit message (stručný komentář ke změně). Zajímá mě CO změna dělá a PROČ. JAK se dovím ze zdrojového kódu a když to vývojář napíše v commit message, spíš mě to mate.
Komentuji vše, k čemu mám co říci: design, funkci, zda je vůbec potřeba, testování, složitost, pojmenování, komentáře, styl, konzistenci, dokumentaci, kontext i co se mi líbí. Prostě každou řádku. To, že sada změn, kterou dostane maintainer, je dokonalá, je zodpovědnost reviewera.
Zpátky u vývojáře
[editovat | editovat zdroj]Patch set, jak se taky říká sadě změn, se po review vrátí zpátky vývojáři. Ten komentáře zapracuje a pošle novou verzi (sady změn).
Z pohledu Gitu chci, jako vývojář, změnit uloženou historii. K tomu mi slouží následující kroky:
- Pomocí git logg a git show IDENTIFIKATOR-ULOZENE-ZMENY zjistím, kterou z uložených změn v sadě chci upravit.
- Upravím soubory související se změnou IDENTIFIKATOR-ULOZENE-ZMENY.
- Pomocí git add -p připravím relevantní řádky souborů pro uložení do historie.
- A změny uložím, tentokrát pomocí
git commit -m'F IDENTIFIKATOR-ULOZENE-ZMENY'.
No a když mám všechny komentáře z review zpracované a uložené, přijde na řadu to přepisování historie. To provedu příkazem
git rebase -i master
který mi otevře textový editor. V něm přesunu řádky
pick IDENTIFIKATOR-OPRAVY F IDENTIFIKATOR-ULOZENE-ZMENY
těsně pod relevantní řádky
pick IDENTIFIKATOR-ULOZENE-ZMENY 52 znaků dokončujících větu
a změním "pick" na "f" nebo "fixup":
f IDENTIFIKATOR-OPRAVY F IDENTIFIKATOR-ULOZENE-ZMENY
Když mám konečně hotovo, soubor zavřu a je to. Pokud se při rebase na příkazové řádce objeví slovo "conflict", dám
git rebase --abort
a začnu na webu hledat, jak se v Gitu řeší merge konflikty.
Git pro Maintainera
[editovat | editovat zdroj]Úkol maintainera je začlenit dokonalou sadu změn. To ale neznamená, že jí musí stoprocentně chápat -- stačí, když důvěřuje vývojáři a reviewerovi.
Záleží na komunikaci v týmu, jestli maintaner použije git am, git merge, nebo klikne na tlačítko na webu.
Tady si musím poznamenat pár informací o merge konfliktech. Jako maintainerovi se mi může stát, že mám za úkol začlenit více sad změn. Problém nastane, když jednotlivé sady změn k začlenění mění stejné soubory. Může se totiž stát, že se soubory mění na stejném místě, což vede k tomu, že po aplikaci první sady změn vychází ta druhá ze zastaralého kódu, který už není k dispozici.
Jsou dvě řešení. Vrátím druhou sadu změn vývojáři a reviewerovi a řeknu, že nevychází z nejnovější verze, ať sadu změn aktualizují. To udělám v případě, kdy sadě změn vůbec nerozumím a to by se nemělo stát.
Druhé řešení je, že merge conflict vyřeším. Merge conflict znamená, že jsou dvě verze změn a Git neví, kterou z nich má použít. Můj úkol je z těch dvou verzí udělat jednu, funkční, chtěnou.
Komunikace v týmu
[editovat | editovat zdroj]Tak si říkám, jak daleko se můžu dostat, aniž bych věděl, že Git je decentralizovaný. To znamená, že každý člen týmu má vlastní kopii historie změn -- repozitáře. Mezi členy týmu se sdílí sady změn a předpokládá se, že změnu identifikovanou IDENTIFIKATOR-ULOZENE-ZMENY, ze které sada změn vychází, má člen týmu dostupnou ve svojí kopii repozitáře.
Komunikace týmu skrz Git, tedy spolupráce na zdrojovém kódu, je asynchronní. Takže si člověk může naplánovat, kdy pošle sadu změn k review, kdy provede review sady změn, nebo kdy sadu změn začlení. Git není chat.
Vývojář má sadu změn, kterou chce sdílet, většinou v samostatné větvi NOVA-FUNKCE. Je několik způsobů, jak mezi sebou členové týmu sady změn sdílí:
- git daemon
- git send-email
- pull/merge request
Git daemon
[editovat | editovat zdroj]Pokud chci sdílet vývojovou větev, respektive sadu změn, rychle přes lokální síť, tak v rodičovském adresáři repozitáře:
git daemon --export-all --base-path=. --enable=receive-pack
kde --enable=receive-pack povoluje ostatním na síti do repozitáře také zapisovat. Členové týmu si přidají vzdálený repozitář:
git remote add KOLEGA git://IP-ADRESA/muj-repo
aktualizují sí svojí kopii repozitáře a přepnou se na větev:
git fetch KOLEGA git checkout NOVA-FUNKCE
nebo se přepnou na větev, pokud ji již mají, a aktualizují ji:
git checkout NOVA-FUNKCE git pull
Git send-email
[editovat | editovat zdroj]Git je dělaný pro (asynchronní) komunikaci přes email. Email se sadou změn se většinou posílá do mailing listu a při správném nastavení je příkaz jen
git send-email master..NOVA-FUNKCE
Mailing list je emailová adresa, která přesměruje příchozí zprávy na předem definované adresy. Taková emailová asynchronní diskuzní skupina. Alias na emailové adresy členů týmu.
A teď se hodí přidat odkaz na etiketu emailové komunikace.
Pull/merge requests
[editovat | editovat zdroj]Forge, servery poskytující služby vývojářům, přinášejí centralizaci do jinak decentralizovaného Git světa. Nejdřív: mailing list je také centralizace -- skupinová zpráva se posílá na jeden server se seznamem emailových adres. Při nedostupnosti serveru nelze zprávu do skupiny odeslat a je potřeba poslat skupinovou zprávu na všechny relevantní emailové adresy. A teď: Forge je webová platforma pro spolupráci vývojářů. Typicky poskytuje online prohlížení zdrojových kódů repozitářů, správu mailing listů, CI/CD, nástroje pro code review, bug/ticket tracker, wiki, či chat.
Používání pull/merge requestů funguje tak, že si nejdřív ve webové aplikaci forknu požadovaný projekt, čímž vlastně vytvořím svojí kopii cizího repozitáře na (cizím) serveru. Potom přidám svůj forknutý repozitář jako origin remote:
git remote add origin git@muj.vysneny.forge:/tojsemja/muj-fork
Nebo jestli nemám ještě kód, tak jej naklonuji:
git clone git@muj.vysneny.forge:/tojsemja/muj-fork
Nahraji větev, ve které mám sadu změn, ze které chci vytvořit pull/merge request:
git checkout NOVA-FUNKCE git push -u origin NOVA-FUNKCE
A nakonec ve webové aplikaci kliknu na něco jako "vytvořit pull/merge request".
Když je kód po review, opravím jej, fixnu a nahraji znovu:
git push -f
Tentokrát není potřeba -u, to stačí jen jednou. Říká to, kterou vzdálenou větev má moje lokální větev sledovat. Pokud se ale změní historie sady změn (git rebase), je potřeba -f, který říká, že se má historie sady změn na serveru přepsat, nejen přidat nové změny.
Ještě jedna věc: potřebuji držet krok s kódem, který je v hlavní větvi forknutého projektu. Přidám si jej jako upstream:
git remote add upstream git@muj.vysneny.forge:/kolega/jeho-repo
svoji hlavní větev (master, který bude brzo main) nastavím, aby sledovala hlavní větev v upstream remote:
git fetch upstream git branch -u upstream master:master
a svoji lokální hlavní větev aktualizuji:
git checkout master git pull --rebase
Shrnutí
[editovat | editovat zdroj]Git je asynchronní komunikační kanál pro spolupráci na zdrojovém kódu.
Vývojář:
git checkout -b NOVA-FUNKCE git diff git add -p git diff --cached git commit -m'52 znaků dokončujících větu'
Znovu vývojář:
git commit -m'F IDENTIFIKATOR-ULOZENE-ZMENY'. git rebase -i master git rebase --abort
Maintainer:
git merge --no-ff NOVA-FUNKCE git am *.patch
Ad-hoc sdílení:
git daemon --export-all --base-path=. --enable=receive-pack git pull git@IP-ADRESA/muj-repo
Mailing list:
git send-email master..NOVA-FUNKCE
Pull/merge request:
git remote add origin git@muj.vysneny.forge:/tojsemja/muj-repo git clone git@muj.vysneny.forge:/tojsemja/muj-repo git checkout NOVA-FUNKCE git push -u origin NOVA-FUNKCE git push -f
A ještě:
git remote add upstream git@muj.vysneny.forge:/kolega/jeho-repo git fetch upstream git branch -u upstream master:master git checkout master git pull --rebase
◄ Git pro mě/Psaní zdrojového kódu nové funkce | Psaní zdrojového kódu v týmu |