Zawartość: Wprowadzenie | Siedem zasad | Porady
- Wprowadzenie: Dlaczego dobre komunikaty commit mają znaczenie
- Siedem zasad doskonałej wiadomości Git commit
- Oddziel temat od ciała pustym wierszem
- Zmniejsz długość tematu do 50 znaków
- Kapitał w linii tematu
- Nie kończ linii tematycznej kropką
- Używaj trybu rozkazującego w temacie
- Zawijaj ciało na 72 znaki
- Użyj ciała, aby wyjaśnić co i dlaczego vs. Jak
- Wskazówki
- Naucz się kochać wiersz poleceń. Zostaw IDE za sobą.
- Czytaj Pro Git
Wprowadzenie: Dlaczego dobre komunikaty commit mają znaczenie
Jeśli przejrzysz dziennik dowolnego losowego repozytorium Git, prawdopodobnie zauważysz, że jego komunikaty commit są w mniejszym lub większym stopniu bałaganem. Na przykład, spójrz na te perełki z moich wczesnych dni popełniania Springa:
$ 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
Yikes. Porównaj to z tymi nowszymi commitami z tego samego repozytorium:
$ 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
Które wolałbyś przeczytać?
Pierwsze różnią się długością i formą; drugie są zwięzłe i spójne.
Pierwsze jest tym, co dzieje się domyślnie; drugie nigdy nie dzieje się przez przypadek.
Pomimo że logi wielu repozytoriów wyglądają jak te pierwsze, są wyjątki. Jądro Linuksa i sam Git są świetnymi przykładami. Spójrz na Spring Boot, lub jakiekolwiek repozytorium zarządzane przez Tima Pope’a.
Współautorzy tych repozytoriów wiedzą, że dobrze sformułowana wiadomość Git commit jest najlepszym sposobem na przekazanie kontekstu zmiany innym programistom (i rzeczywiście ich przyszłym ja). Dyferencjał powie Ci co się zmieniło, ale tylko komunikat commit może właściwie powiedzieć dlaczego. Peter Hutterer dobrze to podkreśla:
Powtórne ustalanie kontekstu kawałka kodu jest marnotrawstwem. Nie możemy tego całkowicie uniknąć, więc nasze wysiłki powinny iść w kierunku zmniejszenia tego jak to tylko możliwe. Komunikaty commit mogą robić dokładnie to, a w rezultacie komunikat commit pokazuje, czy programista jest dobrym współpracownikiem.
Jeśli nie zastanawiałeś się zbytnio nad tym, co czyni komunikat commit Git świetnym, może to oznaczać, że nie spędziłeś zbyt wiele czasu używając git log
i powiązanych narzędzi. Mamy tu do czynienia z błędnym kołem: ponieważ historia commitów jest nieuporządkowana i niespójna, nie poświęcamy zbyt wiele czasu na jej używanie lub dbanie o nią. A ponieważ nie jest używana lub nie dba się o nią, pozostaje nieuporządkowana i niespójna.
Ale dobrze zadbany dziennik jest piękną i użyteczną rzeczą. git blame
, revert
, rebase
, log
, shortlog
i inne podkomendy ożywają. Przeglądanie cudzych commitów i pull requestów staje się czymś, co warto robić, i nagle może być robione niezależnie. Zrozumienie, dlaczego coś wydarzyło się miesiące lub lata temu, staje się nie tylko możliwe, ale i skuteczne.
Długoterminowy sukces projektu zależy (między innymi) od jego łatwości w utrzymaniu, a opiekun ma niewiele narzędzi potężniejszych niż dziennik projektu. Warto poświęcić trochę czasu, aby nauczyć się, jak dbać o niego prawidłowo. To, co na początku może być kłopotliwe, wkrótce stanie się nawykiem, a w końcu źródłem dumy i produktywności dla wszystkich zaangażowanych.
W tym poście zajmę się tylko najbardziej podstawowym elementem utrzymywania zdrowej historii commitów: jak napisać indywidualną wiadomość commit. Istnieją inne ważne praktyki, takie jak commit squashing, których tutaj nie poruszam. Być może zrobię to w kolejnym poście.
Większość języków programowania ma dobrze ugruntowane konwencje co do tego, co stanowi styl idiomatyczny, tj. nazewnictwo, formatowanie i tak dalej. Istnieją oczywiście wariacje na temat tych konwencji, ale większość programistów zgadza się, że wybranie jednej i trzymanie się jej jest o wiele lepsze niż chaos, który powstaje, gdy każdy robi coś swojego.
Podejście zespołu do jego dziennika commitów nie powinno być inne. W celu stworzenia użytecznej historii zmian, zespoły powinny najpierw uzgodnić konwencję komunikatu commit, która definiuje przynajmniej trzy następujące rzeczy:
Styl. Składnia znaczników, marginesy zawijania, gramatyka, kapitalizacja, interpunkcja. Wyjaśnij te rzeczy, usuń zgadywanie i uczyń to wszystko tak prostym, jak to tylko możliwe. Rezultatem końcowym będzie niezwykle spójny dziennik, który nie tylko przyjemnie się czyta, ale który rzeczywiście jest regularnie czytany.
Treść. Jakiego rodzaju informacje powinna zawierać treść komunikatu commit (jeśli w ogóle)? Czego nie powinna zawierać?
Metadane. W jaki sposób należy się odwoływać do identyfikatorów śledzenia wydania, numerów żądań wyciągnięcia itp. Na szczęście istnieją dobrze ustalone konwencje dotyczące tego, co czyni komunikat commit idiomatycznym w Gicie. W rzeczywistości, wiele z nich jest zakładanych w sposobie działania niektórych poleceń Git. Nie ma nic, co musiałbyś wymyślać od nowa. Po prostu przestrzegaj siedmiu poniższych zasad i jesteś na dobrej drodze, aby popełniać błędy jak profesjonalista.
Siedem zasad doskonałej wiadomości Git commit
Pamiętaj: To wszystko zostało już wcześniej powiedziane.
- Oddziel temat od treści pustą linią
- Zmniejsz długość tematu do 50 znaków
- Kapitał w temacie
- Nie kończ tematu kropką
- Używaj trybu rozkazującego w temacie
- Zawijaj treść do 72 znaków
- Używaj treści do wyjaśnienia co i dlaczego vs. jak
Na przykład:
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
Oddziel temat od ciała pustym wierszem
Z podręcznika git commit
:
Chociaż nie jest to wymagane, dobrym pomysłem jest rozpoczęcie wiadomości commit od pojedynczego krótkiego (mniej niż 50 znaków) wiersza podsumowującego zmianę, po którym następuje pusty wiersz, a następnie bardziej szczegółowy opis. Tekst aż do pierwszej pustej linii w komunikacie commit jest traktowany jako tytuł commit’u, i ten tytuł jest używany w całym Git’cie. Na przykład, Git-format-patch(1) zamienia commit w email, i używa tytułu w linii Subject oraz reszty tekstu w treści.
Po pierwsze, nie każdy commit wymaga zarówno tematu jak i treści. Czasami pojedyncza linia jest w porządku, zwłaszcza gdy zmiana jest tak prosta, że nie jest potrzebny żaden dodatkowy kontekst. Na przykład:
Fix typo in introduction to user guide
Nic więcej nie trzeba mówić; jeśli czytelnik zastanawia się, co było literówką, może po prostu spojrzeć na samą zmianę, tj. użyć git show
lub git diff
lub git log -p
.
Jeśli popełniasz coś takiego w wierszu poleceń, łatwo jest użyć opcji -m
do git commit
:
$ git commit -m"Fix typo in introduction to user guide"
Jednakże, gdy commit zasługuje na odrobinę wyjaśnienia i kontekstu, musisz napisać ciało. Na przykład:
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.
Komunikaty commit z ciałem nie są tak łatwe do napisania z opcją -m
. Lepiej jest napisać wiadomość w odpowiednim edytorze tekstowym. Jeśli nie masz jeszcze edytora skonfigurowanego do używania z Gitem w wierszu poleceń, przeczytaj tę sekcję Pro Git.
W każdym razie, oddzielenie tematu od ciała opłaca się podczas przeglądania dziennika. Oto pełny wpis dziennika:
$ 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 teraz git log --oneline
, który wypisuje tylko temat:
$ git log --oneline42e769 Derezz the master control program
Albo, git shortlog
, który grupuje commity według użytkownika, ponownie pokazując tylko temat dla zwięzłości:
$ 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
Istnieje wiele innych kontekstów w Gicie, w których rozróżnienie między tematem a ciałem jest ważne – ale żaden z nich nie działa poprawnie bez pustej linii między nimi.
Zmniejsz długość tematu do 50 znaków
50 znaków nie jest sztywnym limitem, a jedynie zasadą. Utrzymywanie linii tematu w tej długości zapewnia, że są one czytelne i zmusza autora do zastanowienia się przez chwilę nad najbardziej zwięzłym sposobem wyjaśnienia tego, co się dzieje.
Porada: Jeśli masz trudności z podsumowaniem, być może popełniasz zbyt wiele zmian na raz. Dąż do atomowych commitów (temat na osobny post).
UI GitHuba jest w pełni świadome tych konwencji. Ostrzeże Cię, jeśli przekroczysz limit 50 znaków:
I skróci każdą linię tematu dłuższą niż 72 znaki za pomocą wielokropka:
Więc postaraj się o 50 znaków, ale uznaj 72 za twardy limit.
Kapitał w linii tematu
To jest tak proste, jak brzmi. Zaczynaj wszystkie linie tematyczne wielką literą.
Na przykład:
- Przyspiesz do 88 mil na godzinę
Zamiast:
- przyspiesz do 88 mil na godzinę
Nie kończ linii tematycznej kropką
Wciągająca interpunkcja jest zbędna w liniach tematycznych. Poza tym, miejsce jest cenne, gdy starasz się ograniczyć je do 50 znaków lub mniej.
Przykład:
- Otwórz drzwi do zatoki kapsuły
Zamiast:
- Otwórz drzwi do zatoki kapsuły.
Używaj trybu rozkazującego w temacie
Tryb rozkazujący oznacza po prostu „mówiony lub pisany tak, jakby wydawał polecenie lub instrukcję”. Kilka przykładów:
- Sprzątnij swój pokój
- Zamknij drzwi
- Wynieś śmieci
Każda z siedmiu zasad, o których teraz czytasz, jest napisana w imperatywie („Zawiń ciało na 72 znaki” itd.).).
Imperatyw może brzmieć trochę niegrzecznie; dlatego nieczęsto go używamy. Ale jest idealny dla linii tematycznych commitów Git. Jednym z powodów jest to, że Git sam używa imperatywu za każdym razem, gdy tworzy commit w twoim imieniu.
Na przykład, domyślna wiadomość utworzona przy użyciu git merge
brzmi:
Merge branch 'myfeature'
A kiedy używamy git revert
:
Revert "Add the thing with the stuff"This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.
Albo kiedy klikamy przycisk „Merge” na żądaniu ściągnięcia z GitHuba:
Merge pull request #123 from someuser/somebranch
Więc kiedy piszemy swoje wiadomości commit w imperatywie, postępujemy zgodnie z własnymi wbudowanymi konwencjami Gita. Na przykład:
- Refactor subsystem X for readability
- Update getting started documentation
- Remove deprecated methods
- Release version 1.0.0
Pisanie w ten sposób może być na początku trochę niezręczne. Jesteśmy bardziej przyzwyczajeni do mówienia w trybie oznajmującym, który polega na podawaniu faktów. To dlatego komunikaty commit często kończą się tak:
- Usuniecie błędu z Y
- Zmiana zachowania X
A czasami komunikaty commit są pisane jako opis ich zawartości:
- Więcej poprawek dla zepsutych rzeczy
- Słodkie nowe metody API
Aby usunąć wszelkie zamieszanie, oto prosta zasada, aby za każdym razem mieć rację.
Poprawnie utworzony temat commitu Git powinien zawsze być w stanie dokończyć następujące zdanie:
- Jeśli zostanie zastosowany, ten commit będzie Twój temat tutaj
Na przykład:
- If applied, this commit will refactor subsystem X for readability
- If applied, this commit will update getting started documentation
- If applied, this commit will remove deprecated methods
- If applied, this commit will release version 1.0.0
- Jeśli zostanie zastosowany, ten commit połączy pull request #123 od użytkownika/branży
Zauważ, jak to nie działa dla innych form nieimperatywnych:
- Jeśli zastosowane, ten commit naprawi błąd z Y
- Jeśli zastosowane, ten commit zmieni zachowanie X
- Jeśli zastosowane, ten commit będzie więcej poprawek dla zepsutych rzeczy
- Jeśli zastosowane, ten commit będzie słodkie nowe metody API
Pamiętaj: Użycie imperatywu jest ważne tylko w linii tematu. Możesz rozluźnić to ograniczenie, gdy piszesz ciało.
Zawijaj ciało na 72 znaki
Git nigdy nie zawija tekstu automatycznie. Kiedy piszesz treść wiadomości commit, musisz uważać na jej prawy margines i zawijać tekst ręcznie.
Zaleca się, aby robić to przy 72 znakach, tak aby Git miał dużo miejsca na wcięcia tekstu, ale nadal utrzymywał wszystko poniżej 80 znaków.
Dobry edytor tekstu może tu pomóc. Łatwo jest skonfigurować Vima, na przykład, aby zawijał tekst na 72 znaki, gdy piszesz commit Gita. Tradycyjnie jednak, IDE były okropne w dostarczaniu inteligentnego wsparcia dla zawijania tekstu w komunikatach commit (chociaż w ostatnich wersjach, IntelliJ IDEA w końcu się poprawiła w tej kwestii).
Użyj ciała, aby wyjaśnić co i dlaczego vs. Jak
Ten commit z Bitcoin Core jest świetnym przykładem wyjaśnienia, co się zmieniło i dlaczego:
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.
Przyjrzyjrzyj się pełnemu diff i pomyśl tylko, ile czasu autor oszczędza kolegom i przyszłym commitom, poświęcając czas na zapewnienie tego kontekstu tu i teraz. Gdyby tego nie zrobił, prawdopodobnie zostałoby to utracone na zawsze.
W większości przypadków można pominąć szczegóły dotyczące tego, jak dokonano zmiany. Kod jest generalnie samowytłumaczalny pod tym względem (a jeśli kod jest tak skomplikowany, że wymaga wyjaśnienia prozą, to właśnie po to są komentarze źródłowe). Po prostu skup się na wyjaśnieniu powodów, dla których dokonałeś zmiany – sposób, w jaki rzeczy działały przed zmianą (i co było w tym złego), sposób, w jaki działają teraz, i dlaczego zdecydowałeś się rozwiązać to w ten sposób.
Przyszły opiekun, który ci podziękuje, może być tobą samym!
Wskazówki
Naucz się kochać wiersz poleceń. Zostaw IDE za sobą.
Z tylu powodów, dla ilu istnieją podkomendy Gita, mądrze jest objąć linię poleceń. Git jest szalenie potężny; IDE też są, ale każde na inny sposób. Używam IDE każdego dnia (IntelliJ IDEA) i używałem innych w szerokim zakresie (Eclipse), ale nigdy nie widziałem integracji IDE dla Gita, która mogłaby zacząć dorównywać łatwości i mocy wiersza poleceń (gdy już ją poznasz).
Niektóre funkcje IDE związane z Gitem są nieocenione, jak wywołanie git rm
, gdy usuwasz plik, i robienie właściwych rzeczy z git
, gdy zmieniasz nazwę. Wszystko rozpada się, gdy zaczynasz próbować commitować, scalać, rebase, lub robić wyrafinowaną analizę historii przez IDE.
Gdy przychodzi do władania pełną mocą Gita, jest to wiersz poleceń na całej drodze.
Pamiętaj, że niezależnie od tego, czy używasz Basha, Zsh czy Powershella, istnieją skrypty uzupełniania tabulatorów, które zabierają wiele bólu z pamiętania podkomend i przełączników.
Czytaj Pro Git
Książka Pro Git jest dostępna online za darmo i jest fantastyczna. Skorzystaj z niej!
header image credit: xkcd
.