Jak napsat zprávu o odevzdání systému Git

Obsah: Úvod | Sedm pravidel | Tipy

Úvod: Proč na dobrých zprávách o revizi záleží

Prohlédnete-li si protokol libovolného úložiště systému Git, pravděpodobně zjistíte, že jeho zprávy o revizi jsou více či méně chaotické. Podívejte se například na tyto skvosty z mých začátků odevzdávání na Spring:

$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement() method as it turns out this was one of the culprits in the recent build breakage. The classloader hacking causes subtle downstream effects, breaking unrelated tests. The test method is still useful, but should only be run on a manual basis to ensure CGLIB is not prematurely classloaded, and should not be run as part of the automated build.2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated ConfigurationPostProcessorTests until further investigation determines why it causes downstream tests to fail (such as the seemingly unrelated ClassPathXmlApplicationContextTests)147709f Tweaks to package-info.java files22b25e0 Consolidated Util and MutableAnnotationUtils classes into existing AsmUtils7f96f57 polishing

Jéje. Porovnejte je s těmito novějšími zprávami o revizích ze stejného repozitáře:

$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"5ba3db6 Fix failing CompositePropertySourceTests84564a0 Rework @PropertySource early parsing logice142fd1 Add tests for ImportSelector meta-data887815f Update docbook dependency and generate epubac8326d Polish mockito usage

Kterou byste četli raději?

První se liší délkou a formou, druhá je stručná a konzistentní.
První se děje ve výchozím nastavení, druhá se neděje ani omylem.

Přestože záznamy mnoha repozitářů vypadají jako ty první, existují výjimky. Skvělým příkladem je linuxové jádro a samotný systém Git. Podívejte se na Spring Boot nebo na jakýkoli repozitář spravovaný Timem Popem.

Přispěvatelé do těchto repozitářů vědí, že dobře zpracovaná zpráva o revizi v systému Git je nejlepší způsob, jak kolegům vývojářům (a vlastně i sobě v budoucnu) sdělit kontext změny. Rozdíl vám řekne, co se změnilo, ale pouze zpráva o revizi vám může správně sdělit proč. Dobře to vystihuje Peter Hutterer:

Znovu zjišťovat kontext kusu kódu je zbytečné. Nemůžeme se mu zcela vyhnout, takže naše úsilí by mělo směřovat k jeho co největšímu omezení. Zprávy o revizi mohou dělat přesně to a ve výsledku zpráva o revizi ukazuje, zda je vývojář dobrý spolupracovník.

Pokud jste se příliš nezamýšleli nad tím, co dělá skvělou zprávu o revizi systému Git, je možné, že jste nestrávili mnoho času používáním git log a souvisejících nástrojů. Vzniká zde začarovaný kruh: protože je historie revizí nestrukturovaná a nekonzistentní, člověk netráví mnoho času jejím používáním nebo péčí o ni. A protože se nepoužívá ani se o ni nestará, zůstává nestrukturovaná a nekonzistentní.

Ale dobře ošetřený záznam je krásná a užitečná věc. git blame, revert, rebase, log, shortlog a další dílčí příkazy ožívají. Přezkoumávání revizí a pull requestů ostatních se stává něčím, co stojí za to, a najednou to lze dělat nezávisle. Pochopení toho, proč se něco stalo před měsíci nebo lety, se stává nejen možným, ale i efektivním.

Dlouhodobý úspěch projektu závisí (mimo jiné) na jeho udržovatelnosti a správce má jen málo mocnějších nástrojů než protokol svého projektu. Vyplatí se věnovat čas tomu, abyste se naučili, jak o něj správně pečovat. To, co může zpočátku působit potíže, se brzy stane zvykem a nakonec zdrojem hrdosti a produktivity všech zúčastněných.

V tomto příspěvku se zabývám jen nejzákladnějším prvkem udržování zdravé historie revizí: jak psát jednotlivé zprávy o revizích. Existují další důležité postupy, jako je například mačkání revizí, kterými se zde nezabývám. Možná se tomu budu věnovat v některém z dalších příspěvků.

Většina programovacích jazyků má dobře zavedené konvence ohledně toho, co představuje idiomatický styl, tj. pojmenování, formátování atd. Existují samozřejmě různé varianty těchto konvencí, ale většina vývojářů se shoduje, že vybrat si jednu a držet se jí je mnohem lepší než chaos, který vzniká, když si každý dělá, co chce.

Přístup týmu k protokolu revizí by neměl být jiný. Aby bylo možné vytvořit užitečnou historii revizí, měly by se týmy nejprve dohodnout na konvenci zpráv o revizi, která definuje alespoň následující tři věci:

Styl. Syntaxe značek, obtékání okrajů, gramatika, velká písmena, interpunkce. Vysvětlete tyto věci, odstraňte dohady a vše co nejvíce zjednodušte. Konečným výsledkem bude pozoruhodně konzistentní deník, který je nejen radost číst, ale který se skutečně pravidelně čte.

Obsah. Jaké informace by mělo obsahovat tělo zprávy o revizi (pokud vůbec nějaké)? Co by obsahovat nemělo?

Metadata. Jak by se mělo odkazovat na ID pro sledování vydání, čísla požadavků na stažení atd.

Naštěstí existují dobře zavedené konvence ohledně toho, co tvoří idiomatickou zprávu o revizi systému Git. Mnohé z nich se skutečně předpokládají ve způsobu fungování některých příkazů systému Git. Není třeba nic znovu vymýšlet. Stačí dodržovat sedm níže uvedených pravidel a jste na cestě k odevzdávání jako profesionál.

Sedm pravidel skvělé zprávy o revizi systému Git

Mějte na paměti: Tohle všechno už bylo řečeno.

  1. Oddělte předmět od těla prázdným řádkem
  2. Omezte předmět na 50 znaků
  3. V předmětu pište velká písmena
  4. Neuzavírejte předmět tečkou
  5. V předmětu používejte rozkazovací způsob
  6. Tělo zprávy omezte na 72 znaků
  7. V těle zprávy vysvětlete, co a proč vs. proč. jak

Například:

Summarize changes in around 50 characters or lessMore detailed explanatory text, if necessary. Wrap it to about 72characters or so. In some contexts, the first line is treated as thesubject of the commit and the rest of the text as the body. Theblank line separating the summary from the body is critical (unlessyou omit the body entirely); various tools like `log`, `shortlog`and `rebase` can get confused if you run the two together.Explain the problem that this commit is solving. Focus on why youare making this change as opposed to how (the code explains that).Are there side effects or other unintuitive consequences of thischange? Here's the place to explain them.Further paragraphs come after blank lines. - Bullet points are okay, too - Typically a hyphen or asterisk is used for the bullet, preceded by a single space, with blank lines in between, but conventions vary hereIf you use an issue tracker, put references to them at the bottom,like this:Resolves: #123See also: #456, #789

Oddělte předmět od těla prázdným řádkem

Z manuálové stránky git commit:

Ačkoli to není povinné, je dobré začít zprávu o revizi jedním krátkým (méně než 50 znaků) řádkem shrnujícím změnu, po kterém následuje prázdný řádek a pak podrobnější popis. Text až do prvního prázdného řádku ve zprávě o revizi se považuje za název revize a tento název se používá v celém systému Git. Například funkce Git-format-patch(1) změní revizi na e-mail a použije název na řádku Předmět a zbytek revize v těle.

Předně, ne každá revize vyžaduje předmět i tělo. Někdy stačí jediný řádek, zejména když je změna tak jednoduchá, že není třeba dalšího kontextu. Například:

Fix typo in introduction to user guide

Nic dalšího není třeba říkat; pokud čtenáře zajímá, v čem byl překlep, může se jednoduše podívat na samotnou změnu, tj. použít git show nebo git diff nebo git log -p.

Pokud něco takového odevzdáváte v příkazovém řádku, je snadné použít volbu -m k git commit:

$ git commit -m"Fix typo in introduction to user guide"

Jestliže si však změna zaslouží trochu vysvětlení a kontextu, je třeba napsat tělo. Například:

Derezz the master control programMCP turned out to be evil and had become intent on world domination.This commit throws Tron's disc into MCP (causing its deresolution)and turns it back into a chess game.

Zprávy o závazcích s tělem není tak snadné napsat pomocí volby -m. Lepší je napsat zprávu ve vhodném textovém editoru. Pokud ještě nemáte editor nastavený pro práci se systémem Git z příkazového řádku, přečtěte si tuto část knihy Pro Git.

Oddělení předmětu od těla se každopádně vyplatí při procházení protokolu. Zde je celý záznam protokolu:

$ git logcommit 42e769bdf4894310333942ffc5a15151222a87beAuthor: Kevin Flynn <[email protected]>Date: Fri Jan 01 00:00:00 1982 -0200 Derezz the master control program MCP turned out to be evil and had become intent on world domination. This commit throws Tron's disc into MCP (causing its deresolution) and turns it back into a chess game.

A nyní git log --oneline, který vypíše pouze předmět:

$ git log --oneline42e769 Derezz the master control program

Nebo git shortlog, který seskupuje revize podle uživatelů a pro stručnost opět zobrazuje pouze předmět:

$ git shortlogKevin Flynn (1): Derezz the master control programAlan Bradley (1): Introduce security program "Tron"Ed Dillinger (3): Rename chess program to "MCP" Modify chess program Upgrade chess programWalter Gibbs (1): Introduce protoype chess program

V systému Git existuje řada dalších kontextů, kde se rozlišení mezi předmětem a tělem projeví – ale žádný z nich nefunguje správně bez prázdného řádku mezi nimi.

Omezte řádek předmětu na 50 znaků

50 znaků není pevný limit, pouze pravidlo. Udržování řádků předmětu v této délce zajišťuje jejich čitelnost a nutí autora chvíli přemýšlet o tom, jak nejstručněji vysvětlit, o co jde.

Tip: Pokud se vám nedaří shrnout, možná se dopouštíte příliš mnoha změn najednou. Snažte se o atomické revize (téma na samostatný příspěvek).

Uživatelské rozhraní služby GitHub si je těchto konvencí plně vědomo. Upozorní vás, pokud překročíte limit 50 znaků:

A každý předmět delší než 72 znaků zkrátí elipsou:

Takže se snažte o 50 znaků, ale 72 považujte za tvrdý limit.

Pište předmět s velkým písmenem

To je tak jednoduché, jak to zní. Všechny řádky předmětu začínají velkým písmenem.

Například:

  • Zrychlete na 88 mil za hodinu

Na místo:

  • zrychlete na 88 mil za hodinu

Na konci řádku předmětu nepište tečku

V řádcích předmětu je zbytečná interpunkce. Kromě toho je místo drahocenné, když se je snažíte udržet na 50 znacích nebo méně.

Příklad:

  • Otevřete dveře do podpalubí

Místo:

  • Otevřete dveře do podpalubí.

V předmětu použijte rozkazovací způsob

Rozkazovací způsob znamená pouze „řečeno nebo napsáno, jako by se dával příkaz nebo pokyn“. Několik příkladů:

  • Ukliď si pokoj
  • Zavři dveře
  • Vynes odpadky

Každé ze sedmi pravidel, o kterých právě čtete, je psáno v imperativu („Zabalte tělo na 72 znaků“ atd.).

Imperativ může znít poněkud hrubě; proto ho často nepoužíváme. Ale pro předměty revizí systému Git je ideální. Jedním z důvodů je, že samotný systém Git používá imperativ vždy, když vytváří revizi vaším jménem.

Například výchozí zpráva vytvořená při použití git merge zní:

Merge branch 'myfeature'

A při použití git revert:

Revert "Add the thing with the stuff"This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.

Nebo při kliknutí na tlačítko „Merge“ (sloučit) na požadavku na stažení GitHub:

Merge pull request #123 from someuser/somebranch

Takže když píšete zprávy o revizi v imperativu, dodržujete vlastní vestavěné konvence systému Git. Například:

  • Refaktor subsystému X pro lepší čitelnost
  • Aktualizace dokumentace pro začátek
  • Odstranění zastaralých metod
  • Vydání verze 1.0.0

Psaní tímto způsobem může být zpočátku trochu nepohodlné. Jsme spíše zvyklí mluvit v oznamovacím způsobu, který je zaměřen na oznamování faktů. Proto zprávy o revizi často končí takto:

  • Oprava chyby s Y
  • Změna chování X

A někdy se zprávy o revizi píší jako popis jejich obsahu:

  • Další opravy rozbitých věcí
  • Sladké nové metody API

Abychom odstranili případné zmatky, zde je jednoduché pravidlo, jak to pokaždé udělat správně.

Správně vytvořený předmět revize systému Git by měl být vždy schopen doplnit následující větu:

  • Pokud se použije, tato revize bude váš předmět zde

Například:

  • Pokud bude použita, tato revize provede refaktorizaci subsystému X pro lepší čitelnost
  • Pokud bude použita, tato revize aktualizuje úvodní dokumentaci
  • Pokud bude použita, tato revize odstraní zastaralé metody
  • Pokud bude použita, tato revize vydá verzi 1.0.0
  • Pokud bude použita, tato revize sloučí pull request #123 od uživatele/branch

Všimněte si, že to nefunguje pro ostatní neimperativní formy:

  • Pokud bude použita, tato revize opraví chybu s Y
  • Pokud bude použita, tato revize změní chování X
  • Pokud bude použita, tato revize opraví více rozbitých věcí
  • Pokud bude použita, tato revize osladí nové metody API

Pamatujte: Použití imperativu je důležité pouze v předmětu. Při psaní těla můžete toto omezení zmírnit.

Zabalte tělo na 72 znaků

Git nikdy nezabaluje text automaticky. Když píšete tělo zprávy o revizi, musíte dbát na jeho pravý okraj a text obtékat ručně.

Doporučuje se to dělat na 72 znaků, aby měl systém Git dostatek prostoru pro odsazení textu a zároveň aby vše celkově nepřesáhlo 80 znaků.

Pomůže vám v tom dobrý textový editor. Je snadné nakonfigurovat například Vim tak, aby při psaní revize systému Git obtékal text na 72 znaků. Tradičně jsou však IDE příšerná v poskytování inteligentní podpory pro obtékání textu ve zprávách o revizi (i když v posledních verzích IntelliJ IDEA se to konečně zlepšilo).

V těle vysvětlete, co a proč oproti zprávám o revizi. jak

Tato revize z Bitcoin Core je skvělým příkladem vysvětlení toho, co a proč se změnilo:

commit eb0b56b19017ab5c16c745e6da39c53126924ed6Author: Pieter Wuille <[email protected]>Date: Fri Aug 1 22:57:55 2014 +0200 Simplify serialize.h's exception handling Remove the 'state' and 'exceptmask' from serialize.h's stream implementations, as well as related methods. As exceptmask always included 'failbit', and setstate was always called with bits = failbit, all it did was immediately raise an exception. Get rid of those variables, and replace the setstate with direct exception throwing (which also removes some dead code). As a result, good() is never reached after a failure (there are only 2 calls, one of which is in tests), and can just be replaced by !eof(). fail(), clear(n) and exceptions() are just never called. Delete them.

Podívejte se na celý diff a jen se zamyslete, kolik času autor ušetří kolegům a budoucím revizorům tím, že věnuje čas poskytnutí tohoto kontextu tady a teď. Kdyby to neudělal, pravděpodobně by to bylo navždy ztraceno.

Ve většině případů můžete vynechat podrobnosti o tom, jak byla změna provedena. Kód je v tomto ohledu obecně samovysvětlující (a pokud je kód tak složitý, že je třeba jej vysvětlit v próze, od toho jsou komentáře ke zdrojovému kódu). Soustřeďte se jen na to, aby byly jasné důvody, proč jste změnu vůbec provedli – jak věci fungovaly před změnou (a co na tom bylo špatně), jak fungují nyní a proč jste se rozhodli to vyřešit tak, jak jste to vyřešili.

Budoucím správcem, který vám poděkuje, můžete být vy sami!

Tipy

Naučte se milovat příkazový řádek. IDE nechte za sebou.

Z tolika důvodů, kolik je podřízených příkazů systému Git, je moudré přijmout příkazový řádek. Git je šíleně mocný, IDE také, ale každé jiným způsobem. Používám IDE každý den (IntelliJ IDEA) a hojně jsem používal i jiná (Eclipse), ale nikdy jsem neviděl integraci IDE pro Git, která by se mohla začít vyrovnat jednoduchosti a síle příkazového řádku (jakmile ho znáte).

Některé funkce související s IDE pro Git jsou neocenitelné, například volání git rm při mazání souboru a provádění správných věcí pomocí git při přejmenování souboru. Vše se rozpadá, když se prostřednictvím IDE začnete pokoušet o odevzdání, sloučení, přeskupení nebo sofistikovanou analýzu historie.

Pokud jde o ovládání plné síly systému Git, je to příkazový řádek.

Nezapomeňte, že ať už používáte Bash, Zsh nebo Powershell, existují skripty pro doplňování karet, které vás zbaví většiny starostí se zapamatováním si dílčích příkazů a přepínačů.

Přečtěte si knihu Pro Git

Kniha Pro Git je k dispozici zdarma online a je fantastická. Využijte toho!

obrázek v záhlaví: xkcd

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.