OpenTTD GitHub
Wkład w OpenTTD - wytyczne
OpenTTD Doxygen
Styl kodowania
Kompilowanie OpenTTD
Debugowanie
Dodanie ustawienia
Dodanie funkcji squirrel
Zrozumienie obsługi SaveGame
Wyznaczenie wersji gry zapisanej
Wykonanie wydania OpenTTD
Podręcznik stylu
Format plików lang
Użycie ciągów OpenTTD
Lista ciągów specjalnych
Użycie systemu okna
Kody kolorów istniejących w OpenTTD
Dodawanie pola tekstowego
Zrozumienie widget focus system
Przewodnik stylu GUI
OpenTTD TCP protokół
OpenTTD UDP protokół
Debugowanie desynchronizacji
Rozwój Portu Administratora Serwera
Okno konsoli
Komendy konsoli
Zmienne konsoli
Używanie skryptu konsoli
Dodanie funkcji/komend do konsoli
Dodanie zmiennych do konsoli
Historia rozwoju Konsoli
Grafika i podobne (NewGRFy)
Środowisko AI (NoAI)
Framework GS (NoGO)
Tablica map (siatka pozioma)
Pojazdy
Wyszukiwanie trasy
Przyspieszenie pociągu
Dlaczego ustawiony styl kodowania jest ważny
Ten projekt jest projektem typu open source. Aby open source działał zgodnie z przeznaczeniem, wiele osób powinno być w stanie zrozumieć kod. Oznacza to, że istnieje dobrze udokumentowany i jednolity przepływ kodu.
Nie musi to wcale oznaczać, że współtwórca nie powinien pisać zoptymalizowanego, ale tajemniczego kodu - zawsze należy dbać o wydajność. Jednak inni programiści muszą zrozumieć kod, co oznacza skomplikowane części kodu muszą mieć dobrą dokumentację.
Dlaczego wymagamy, aby WSZYSTKO było udokumentowane
To, co dla niektórych jest proste, dla innych może wydawać się bardzo skomplikowane. Dokumentacja pomaga tym innym. Każdy powinien być w stanie poprawić kod. Ale głównym powodem jest to, że jeśli twórcy łatek chcą, aby ich łatki zostały dodane do wspólnej bazy kodu, kod musi zostać sprawdzony przez jednego lub więcej programistów. Dokumentacja znacznie ułatwia przeglądanie.
Contents |
Styl kodowania dla OpenTTD
Funkcje
- Użyj nazw funkcji CamelCase bez podkreślenia.
- Otwieranie nawiasu klamrowego { dla funkcji zaczyna się w następnym wierszu.
- Użyj Foo() zamiast Foo(void).
void ThisIsAFunction() { }
Zmienne
- Nazwy zmiennych są pisane małymi literami i używają "_" jako separatora.
- Zmienne globalne są poprzedzone znakiem podkreślenia. ("_") Użyj nazw opisowych, ponieważ wiodące podkreślenia są często używane w zmiennych systemowych / kompilatorowych.
- do własnych członków klas należy zawsze odwoływać się za pomocą "this->"
- Wskaźniki i odniesienia powinny mieć symbol odniesienia obok nazwy (zgodność z bieżącym kodem).
- Zmienne zadeklarowane jeden pod drugim powinny mieć swój typ, nazwę lub operator odniesienia oraz operator przypisania wyrównany spacjami.
- Istnieje wiele nazw dla wielu zmiennych. Są to (ale nie wyłącznie): Vehicle *u, *v, *w; Stacja *st; Miasto *t; Window *w; Silnik *e.
- W przypadku wielu instancji użyj liczb "*t1, *t2" lub postfiksów "*st_from, *st_to" .
- Deklaruj zmienne przy pierwszym użyciu.
- Zadeklaruj iteratory w swojej pętli.
- W "stałych wskaźnikach" ("const pointers") występuje spacja między '*' a 'const'
int number = 10; Vehicle *u_first_wagon = v->next; int value = v->value; uint32 _global_variable = 3750; static const char * const _global_array[] = { "first string", "second string", "another string", "last string followed by comma", }; protected: char protected_array[10]; for (int i = 0;;);
- Podaj zmienne nazwy celowe, to zwiększa czytelność kodu
bool is_maglev_train = true; if (!is_maglev_train) DoSomething();
- Niektóre osoby lubią wprowadzać kopie zmiennych w celu zwiększenia czytelności, co może marnować pamięć. Jednak w niektórych przypadkach, szczególnie w fragmentach kodu, które są często nazywane, sensowne jest buforowanie niektórych obliczonych zmiennych.
/* Unoptimized code: * foo is not touched inside the loop! */ for (uint8 i = 0; i < 100000; i++) { /* Do something */ if (value_to_check == (foo * 4) % 5 + 6) DoSomething(); /* Do something else */ } /* Better: * The used value of foo is calculated outside the loop. */ const uint32 bar = (foo * 4) % 5 + 6; for (uint8 i = 0; i < 100000; i++) { /* Do something */ if (value_to_check == bar) DoSomething(); /* Do something else */ }
Wyliczenia / stałe statyczne
- Wyliczenia przechowują liczby całkowite, które należą do siebie logicznie (typy szyn, identyfikatory ciągów itp.).
- Nazwy wyliczeń używają również CamelCase.
- Wszystkie wyliczniki to wielkie litery ze słowami "_" .
- Wyliczenia nie są używane do przechowywania pojedynczych liczb.
- Wyliczenia mają kolejne numery LUB (OR)
- Wyliczenia mają następujące po sobie potęgi dwóch. Potęgi dwóch (bitów) są zapisywane szesnastkowo lub za pomocą operatora zmiany biegów.
- Wyliczenia mogą mieć specjalne wyliczniki: "_BEGIN", "_END" i "INVALID_" ). Patrz przykład.
- Nieprawidłowy zawsze ma wartość 0xFF, 0xFFFF, 0xFFFFFFFF.
- Inne wartości specjalne są kolejno mniejsze niż nieprawidłowe.
- Zmienne zawierające wyliczniki powinny mieć typ wyliczenia.
enum DiagDirection { DIAGDIR_BEGIN = 0, DIAGDIR_NE = 0, DIAGDIR_SE = 1, DIAGDIR_SW = 2, DIAGDIR_NW = 3, DIAGDIR_END, INVALID_DIAGDIR = 0xFF, BROKEN_DIAGDIR = 0xFE, }; enum { DEPOT_SERVICE = (1 << 0), DEPOT_MASS_SEND = (1 << 1), DEPOT_DONT_CANCEL = (1 << 2), DEPOT_LOCATE_HANGAR = (1 << 3), }; DiagDirection enterdir = DIAGDIR_NE;
- Liczby przechowujące pojedyncze lub nieskorelowane dane są stałymi statycznymi. Mogą korzystać z konwencji nazewnictwa wyliczeń.
Przykład:
static const int MAXIMUM_STATIONS = 42;
- Wyliczenia są przydatne w kodzie GUI: Gdy widżety są wyliczane, dostęp do nich jest łatwiejszy podczas wielu operacji. Dodatkowo zmiany spowodowane zmodyfikowanymi sekwencjami widgetów wymagają mniej adaptacji kodu. Jeśli widget jest używany w ten sposób, jego nazwa wyliczeniowa powinna być obecna w komentarzu za odpowiednią definicją widgetu.
/** Enum referring to the widgets of the build rail depot window */ enum BuildRailDepotWidgets { BRDW_CLOSEBOX = 0, BRDW_CAPTION, BRDW_BACKGROUND, BRDW_DEPOT_NE, BRDW_DEPOT_SE, BRDW_DEPOT_SW, BRDW_DEPOT_NW, }; /* ... */ /** Widget definition of the build rail depot window */ static const Widget _build_depot_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_..}, // BRDW_CLOSEBOX { WWT_CAPTION, RESIZE_NONE, 7, 11, 139, 0, 13, STR_..., STR_...}, // BRDW_CAPTION { WWT_PANEL, RESIZE_NONE, 7, 0, 139, 14, 121, 0x0, STR_NULL}, // BRDW_BACKGROUND { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 17, 66, 0x0, STR_..}, // BRDW_DEPOT_NE { WWT_PANEL, RESIZE_NONE, 14, 71, 136, 69, 118, 0x0, STR_..}, // BRDW_DEPOT_SE { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 69, 118, 0x0, STR_..}, // BRDW_DEPOT_SW { WWT_PANEL, RESIZE_NONE, 14, 3, 68, 17, 66, 0x0, STR_..}, // BRDW_DEPOT_NW { WIDGETS_END}, };
- Komentarze do wartości wyliczeniowych powinny zaczynać się od "///<" , aby włączyć dokumentację doxygen
enum SomeEnumeration { SE_BEGIN = 0, ///< Begin of the enumeration, used for iterations SE_FOO = 0, ///< Used for xy SE_BAR, ///< Another value of the enumeration SE_SUB, ///< Special case for z SE_END, ///< End of the enumeration, used for iterations };
Kontrola przepływu
- Przed nawiasami wstaw spację w instrukcjach if, switch, for i while .
- Używaj nawiasów klamrowych i umieszczaj zawarte instrukcje w ich własnych wierszach (np. Nie umieszczaj ich bezpośrednio po if ).
- Otwieranie nawiasów klamrowych { pozostaje na pierwszej linii, zamykanie nawiasów klamrowych } dostaje linię do siebie (z wyjątkiem } poprzedzającego else , który powinien znajdować się w tym samym wierszu, co else ).
- Gdy zawarta jest tylko jedna instrukcja, nawiasy można pominąć. W takim przypadku umieść pojedynczą instrukcję w tym samym wierszu, co poprzednie słowo kluczowe (if, while etc.). Należy pamiętać, że jest to dozwolone tylko w przypadku instrukcji bez klauzuli else .
- Wszystkie upadki muszą być udokumentowane za pomocą komentarza „UPADEK PRZEZ” ( FALL THROUGH ).
- Makra NOT_REACHED() można używać w domyślnych konstrukcjach, które nigdy nie powinny zostać osiągnięte.
- Bezwarunkowe pętle są zapisywane za pomocą dla (;;) {
if (a == b) { Foo(); } else { Bar(); } if (very_large_checks && spread_over_two_lines) { Foo(); } if (a == b) Foo(); switch (a) { case 0: DoSomethingShort(); break; case 1: DoSomething(); /* FALL THROUGH */ case 2: DoMore(); b = a; break; case 3: { int r = 2; DoEvenMore(a); /* FALL THROUGH */ } case 4: { int q = 345; DoIt(); break; } default: NOT_REACHED(); } for (int i = 0; i < 10; i++) { Foo(); Bar(); }
Klasy
- Nazwy klas również używają CamelCase.
- Klasy powinny mieć sekcje "publiczne", "chronione" i "prywatne" ( "public", "protected", i "private" ) .
- W tej sekcji kolejność jest następująca: typy, stałe elementy statyczne, elementy statyczne, elementy, konstruktory / destruktory, metody statyczne, metody.
- Odchylenia od powyższej kolejności są dozwolone, gdy dyktuje to kod (np. Wymagana jest stała statyczna dla typedef)
- Metody i elementy powinny być pogrupowane logicznie.
- Wszystkie te reguły sortowania czasami są ze sobą sprzeczne. W takim przypadku należy kierować się zdrowym rozsądkiem, co zwiększa czytelność kodu.
- Implementacja metody powinna wskazywać, czy jest ona wirtualna czy podobna za pomocą komentarza.
- Bardzo krótkie metody mogą mieć definicję jednowierszową (jeśli są zdefiniowane w zakresie klasy).
class ThisIsAClass { public: typedef Titem_ *ItemPtr; private: static const int MAX_SIZE = 500; int size; ItemPtr *items; public: explicit ThisIsAClass(); ~ThisIsAClass(); int GetSize() { return this->size; } virtual void Method(); }; /*virtual*/ void Class::Method() { this->size *= 2; }
Szablony
Szablony są bardzo potężnym narzędziem C++, ale mogą łatwo pomylić początkujących. A zatem:
- Szablony należy dokumentować w bardzo jasny i pełny sposób. Nigdy nie zakładaj niczego w dokumentacji.
- słowo kluczowe szablonu i układ szablonu mają osobną linię. nazwy typowe to "T" lub poprzedzone "T", liczby całkowite otrzymują pojedynczą wielką literę lub opisową nazwę poprzedzoną przez "T".
template <typename T, typename Tsomething, int N, byte Tnumber_of_something> int Func();
- Jeśli piszesz jedną lub więcej klas szablonów w dedykowanym pliku nagłówkowym, użyj file.hpp dla jego nazwy zamiast file.h. Dzięki temu inni dowiedzą się, że jest to biblioteka szablonów (obejmuje także implementację), a nie tylko nagłówek z deklaracjami.
Inne ważne zasady
- Umieść spację przed i po operatorach binarnych: "a + b", "a == b", "a & b", "a <<= b" etc. Wyjątek stanowią ".", "->" i "[]" (bez spacji) i "," (tylko spacja po nim).
- Umieść nawias w miejscu, które poprawia czytelność: "*(b++)" instead of "*b++", and "if ((a & b) && c == 2)" zamiast "if (a & b && c == 2)" .
- Nie umieszczaj deklaracji zewnętrznych w plikach implementacyjnych (tj. cpp).
- Używaj const tam, gdzie to możliwe.
- Nie wpisuj wyliczeń i struktur.
- Nie traktuj nie-flag jak flag: użyj "if (char_pointer != NULL && *char_pointer != '\0')", nie "if (char_pointer && *char_pointer)" .
- Użyj "free(p)" zamiast "if (p != NULL) free(p)" . "free(NULL)" nikomu nie zaszkodzi.
- Brak spacji końcowych. Serwer svn nie zezwala na tabulatory ani spacje na końcu linii.
- Używaj tabulatorów tylko do wcięcia od początku linii.
- Długość linii jest nieograniczona. W praktyce przydatne może być podzielenie długiej linii. Podczas dzielenia dodaj dwie zakładki przed drugą częścią.
- '#' Instrukcji preprocesora przechodzi do pierwszej kolumny wiersza. Wcięcie odbywa się po znaku '#' (ponowne użycie tabulatorów).
- Użyj /* */ do komentarzy jednowierszowych.
-
Użyj // na końcu wiersza poleceń, aby zaznaczyć komentarze.
- Jednak użyj /* */ po # instrukcji preprocesora, ponieważ // powoduje ostrzeżenia w niektórych kompilatorach i/lub może mieć niepożądane skutki uboczne.
- C++ jest definiowany przy użyciu zestawu znaków ASCII. Nie używaj innych zestawów znaków, nawet w komentarzach.
- OpenTTD zawiera niektóre źródła Objective-C (*.mm, używane przez OSX), które mają specjalną składnię wywołania metody obiektowej: "[ obj doStuff:foo ]" . Proszę użyć spacji po wewnętrznej stronie nawiasów, aby odróżnić składnię tablicy C .
Dokumentacja
Używamy Doxygen do automatycznego generowania dokumentacji z kodu źródłowego. Skanuje pliki źródłowe w poszukiwaniu rozpoznawalnych komentarzy.
- Uczyń swoje komentarze rozpoznawalnymi.
Komentarze Doxygen zaczynają się od następującego stylu:
/** ///<
Użyj /** dla wieloliniowych bloków komentarzy. Użyj ///< dla komentarzy jednowierszowych dla zmiennych. Użyj //!< do komentarzy jednowierszowych w plikach .hpp NoAI. W przypadku bloków komentarzy w funkcji zawsze używaj /* */ lub //. Użyj // tylko jeśli komentarz znajduje się w tym samym wierszu co instrukcja, w przeciwnym razie użyj /* */.
Pliki
- Umieść komendę @file w komentarzu w stylu JavaDoc na początku pliku, a następnie opis.
/** * @file * This is the brief description. * This is the detailed description here and on the following lines. */
Jeśli w pliku brakuje file comment block wtedy Doxygen NIE udokumentuje ŻADNYCH elementów w tym pliku!
Funkcje
-
Dokumentacja powinna być jak najbliższa rzeczywistemu kodowi, aby zmaksymalizować szansę na synchronizację.
- Komentarze do funkcji znajdują się w pliku .cpp.
- Komentarze do wstawianych plików znajdują się w pliku .h/.hpp.
- Małe wstawki mogą mieć krótki 3 lub 4-liniowy komentarz w stylu JavaDoc.
- Dokumentuj całkowicie większe funkcje.
- Dokumentuj również oczywiste parametry i zwracane wartości!
/** * A brief explanation of what the function does and/or what purpose it serves. * Then follows a more detailed explanation of the function that can span multiple lines. * * @param foo Explanation of the foo parameter * @param bar Explanation of the bar parameter * @return The sum of foo and bar (@return can be omitted if the return type is void) * * @see SomeOtherFunc() * @see SOME_ENUM * * @bug Some bug description * @bug Another bug description which continues in the next line * and ends with the following blank line * * @todo Some to-do entry */ static int FooBar(int foo, int bar) { return foo + bar; }
Klasy
- Dokument struktury przypomina funkcje:
/** * A short description of the struct. * More detailed description of the its usage. * * @see [link to anything of interest] */ struct foo { }
Polecenia strukturalne JavaDoc
Ta tabela pokazuje polecenia, których powinieneś używać z OpenTTD. Pełna lista to tutaj.
Komenda | Akcja | Przykład |
---|---|---|
@attention | Rozpoczyna akapit, w którym można wprowadzić wiadomość wymagającą uwagi. Akapit zostanie wcięty. | @attention Whales crossing! |
@brief | Rozpoczyna akapit, który służy jako krótki opis. W przypadku klas i plików krótki opis zostanie wykorzystany na listach i na początku strony z dokumentacją. W przypadku członków klasy i plików krótki opis zostanie umieszczony w deklaracji członka i poprzedzony szczegółowym opisem. Krótki opis może obejmować kilka wierszy (choć zaleca się, aby był krótki!). | @brief This is the brief description. |
@bug | Rozpoczyna akapit, w którym można zgłosić jeden lub więcej błędów. Akapit zostanie wcięty. Wiele sąsiadujących poleceń @bug zostanie połączonych w jeden akapit. Opis każdego błędu rozpocznie się w nowej linii. Alternatywnie jedno polecenie @bug może wspomnieć o kilku błędach. | @bug Memory leak in here? |
@note | Rozpoczyna akapit, w którym można wprowadzić notatkę. Akapit zostanie wcięty. | @note Might be slow |
@todo | Rozpoczyna akapit, w którym opisano pozycję 'DO ZROBIENIA'. Opis doda również pozycję do osobnej listy TODO. Oba wystąpienia opisu zostaną powiązane. Każdy element na liście DO ZROBIENIA będzie poprzedzony nagłówkiem wskazującym pochodzenie elementu. | @todo Better error checking |
@warning | Rozpoczyna akapit, w którym można wprowadzić jeden lub więcej komunikatów ostrzegawczych. Akapit zostanie wcięty. | @warning Not thread safe! |
Function related commands | ||
@return | Rozpoczyna opis wartości zwracanej dla funkcji. | @return a character pointer |
@param |
Uruchamia opis parametru dla parametru funkcji o nazwie <parameter-name>. Następnie następuje opis parametru. Istnienie tego parametru jest sprawdzane i wyświetla się ostrzeżenie, jeśli brakuje dokumentacji tego (lub dowolnego innego) parametru lub nie ma go w deklaracji funkcji lub definicji. Komenda @param ma opcjonalny atrybut określający kierunek atrybutu. Możliwe wartości to "in" i "out". |
@param n The number of bytes to copy @param[out] dest The memory area to copy to. @param[in] src The memory area to copy from. |
@see | Rozpoczyna akapit, w którym można podać jedno lub więcej odsyłaczy do klas, funkcji, metod, zmiennych, plików lub adresu URL. Dwie nazwy połączone przez :: lub # są rozumiane jako odnoszące się do klasy i jednego z jej członków. Można wybrać jedną z kilku przeciążonych metod lub konstruktorów, umieszczając w nawiasach listę typów argumentów po nazwie metody. Tutaj można znaleźć szczegółowe informacje na temat tej funkcji. | @see OtherFunc() |
@b | Displays the following word using a bold font. Equivalent to <b>word</b>. To put multiple words in bold use <b>multiple words</b>. | ...@b this and @b that... |
@c / @p | Wyświetla parametr <word> przy użyciu czcionki do pisania. Za pomocą tego polecenia można odwoływać się do parametrów funkcji składowej w bieżącym tekście. Aby mieć wiele słów czcionką do pisania, użyj fontu <tt>multiple words</tt>. | ... the @p x and @p y coordinates are used to... |
@arg / @li | To polecenie ma jeden argument, który trwa do pierwszej pustej linii lub do napotkania kolejnego @arg / @li. Polecenia można użyć do wygenerowania prostej, nie zagnieżdżonej listy argumentów. Każdy argument powinien zaczynać się od komendy @arg / @li . |
@arg @c AlignLeft left alignment. @arg @c AlignCenter center alignment. @arg @c AlignRight right alignment |
@n | Wymusza nową linię. Równoważny i inspirowany funkcją printf. | @n |
Więcej na temat Doxygen i JavaDoc
Doxygen zna dwa różne rodzaje komentarzy:
- Brief descriptions: ('Krótki opis') jedno-linijny ('one-liners') , które z grubsza opisują tę funkcję (przykład)
- Detailed descriptions: ('Szczegółowe opisy') jak sama nazwa wskazuje, zawierają one szczegółową funkcję/cel opisywanego bytu (przykład)
Możesz pominąć jedno lub umieścić je w różnych miejscach, ale dla tego samego bytu dozwolony jest tylko jeden krótki i jeden szczegółowy opis.
Doxygen zna trzy tryby dokumentowania bytu:
- Przed 'entity'
- Po 'entity'
- W innym pliku
Ten ostatni jest nieco trudniejszy w utrzymaniu, ponieważ prototyp encji, którą opisuje, jest przechowywany w kilku miejscach (np. Plik .h i plik z opisami). Oprócz tego, że kod jest łatwiejszy do odczytania, ułatwia także pominięcie ważnego kroku aktualizacji opisu bytu, jeśli został zmieniony - i wszyscy wiemy, dlaczego tak się nie stało ;)
Z tych powodów użyjemy tylko dwóch pierwszych schematów dokumentacji.
Doxygen obsługuje style komentarzy Qt i JavaDoc:
- Qt przykład stylu: int i; //!< Licznik dla głównej pętli
- JavaDoc style example: int i; /**< Licznik dla głównej pętli */
Obsługuje także więcej stylów komentarzy, ale te dwa są znormalizowane. W przypadku OTTD będziemy używać stylu JavaDoc. Jednym z powodów jest to, że ma funkcję, której nie oferuje styl Qt: bloki komentarzy w stylu JavaDoc automatycznie rozpoczną krótki opis, który kończy się na pierwszej kropce, po której następuje spacja lub nowy wiersz. Wszystko później będzie również częścią szczegółowego opisu.
Ogólna struktura komentarza w stylu JavaDoc to
/** * This is the brief description. And this sentence contains some further explanations that will appear in the detailed description only. */
i wynikowe opisy tego bloku byłyby:
- Brief description: To jest krótki opis.
- Detailed description: To jest krótki opis. To zdanie zawiera dalsze wyjaśnienia, które pojawią się tylko w szczegółowym opisie.
Rozróżnienia między krótkim i szczegółowym opisem dokonuje kropka, po której następuje spacja/nowa~linia, więc jeśli chcesz użyć tego w krótkim opisie, musisz uciec spacji/nowej~linii:
/** * This is a brief description (e.g.\ using only a few words). Details go here. */
Jeśli robisz komentarz w jednym wierszu, użyj:
int i; ///< This is the description.
Również w bloku komentarza można dołączyć tak zwane polecenia strukturalne, które mówią Doxygenowi, co następuje. Zasadniczo ich obszar działania zaczyna się po słowie polecenia, a kończy po napotkaniu pustej linii lub innego polecenia. Również wiele wystąpień tego samego polecenia strukturalnego w bloku komentarza lub encji odsyłającej będzie zwykle dołączanych do danych wyjściowych dokumentacji.
Wiadomość Zatwierdzenia
Aby osiągnąć spójną całość i ułatwić pisanie dziennika zmian, oto kilka wskazówek dotyczących komunikatów zatwierdzania (commit). Na serwerze git znajduje się skrypt kontrolny (dostępny również dla klientów, patrz poniżej), aby upewnić się, że wszyscy przestrzegamy tych zasad.
Pierwszy wiersz wiadomości musi być zgodny:
<keyword>( #<issue>| <commit>(, (<keyword> #<issue>|<commit>))*)?: ([<section])? <Details>
Słowa kluczowe to:
- Dodaj, funkcja: Dodawanie nowych rzeczy. Różnica między "Feature" a "Add" jest nieco subiektywna. "Funkcja" dla rzeczy z punktu widzenia użytkownika, "Dodaj" dla innych.
- Zmiana: zmiana zachowania z punktu widzenia użytkownika.
- Usuń: Usunięcie czegoś z punktu widzenia użytkownika.
- Zmiana kodu, czyszczenie: zmiany bez zamierzonej zmiany zachowania z punktu widzenia użytkownika. Różnica między "Zmianą kodu" a "Porządkiem" jest dość subiektywna.
- Napraw, przywróć: Naprawianie rzeczy.
- Dokument, aktualizacja: zmiany w dokumentacji, przyrosty wersji, zatwierdzenia przez tłumacza.
- Przygotuj: Przygotowanie do większych zmian. Rzadko używane.
Jeśli zatwierdzisz poprawkę dla issue, dodaj odpowiedni numer wydania w postaci #NNNN. Zrób to również, jeśli zaimplementujesz funkcję z pasującym wpisem.
W przypadku poprawek błędów, jeśli wiesz, jaką poprawkę wprowadzono (np. Regresję), należy również wspomnieć o tej poprawce tuż po prefiksie. Znalezienie powodującej problemy rewizji jest bardzo zachęcane backporting/branching/releases - o wiele łatwiej.
Aby dodatkowo ustrukturyzować dziennik zmian, możesz dodać sekcje. Przykładami są:
- "Network" dla zmian specyficznych dla sieci
- "NewGRF" dla dodatków NewGRF
- "YAPP", "NPF" , w przypadku zmian tych funkcji
- "OSX", "Debian", "win32" , w przypadku zmian specyficznych dla systemu operacyjnego
Dalsze wyjaśnienia, ogólne 'bitching' itp. Nie wchodzą w pierwszą linię. Użyj nowej linii dla nich.
Kompletne przykłady:
- Reperacja: [YAPF] Nieskończona pętla w pathfinderze.
- Reperacja #5926: [YAPF] Nieskończona pętla w pathfinderze.
- Reperacja 80dffae130: Ostrzeżenie o niepodpisanym unarnym minusie.
- Reperacja #6673, 99bb3a95b4: Przechowuj ustawienia odmiany mapy w grze samej.
- Przywrócenie d9065fbfbe, Reperacja #5922: ClientSizeChanged jest wywoływany tylko przez WndProcGdi, który ma już muteks.
- Reperacja #1264, Fix #2037, Fix #2038, Fix #2110 : Przepisanie autoreplace jądra.
Inne wskazówki
Usuń końcowe białe znaki
Aby dowiedzieć się, czy/gdzie masz końcowe białe znaki, możesz użyć następującego polecenia (unix/bash):
grep -n -R --include "*.[ch]" '[ ]$' * | grep --invert-match ".diff" | grep --invert-match ".patch"
Automatyczne usuwanie białych znaków jest również możliwe za pomocą następującego skryptu powłoki (pamiętaj, że sprawdza tylko .c, .cpp, .h, .hpp and .mm pliki):
#!/bin/sh IFS=' ' for i in Makefile `find . -name \*.c -o -name \*.cpp -o -name \*.h -o -name \*.hpp -o -name \*.mm` do ( echo '%s/[ ]\{1,\}$/' echo w echo q ) | ed $i 2> /dev/null > /dev/null done
Zainstaluj 'haczyki' zatwierdzania git po stronie klienta
'Haki' (hooks) po stronie klienta wykonują różne kontrole, gdy zatwierdzasz zmiany lokalnie.
- Sprawdzanie białych znaków i wcięć.
- Sprawdzenie Commit style.
Zdobądź 'haki':
git clone https://github.com/OpenTTD/OpenTTD-git-hooks.git openttd_hooks
Zainstaluj te 'zaczepy', zakładając, że "openttd" jest folderem drzewa pracy:
cd openttd/.git/hooks ln -s -t . ../../../openttd_hooks/hooks/*