簡體中文 ▾ 主題 ▾ 最新版本 ▾ CodingGuidelines 最後更新於 2.52.0

此資訊專用於 Git 專案

請注意,如果您打算為 Git 專案本身做貢獻,此資訊才與您相關。它絕不是普通 Git 使用者的必讀內容。

與其他專案一樣,我們也有一些程式碼規範。對於 Git 而言,一些粗略的規則是:

  • 最重要的是,我們從不說“它在 POSIX 中;如果您的系統不符合,我們將愉快地忽略您的需求。”我們生活在現實世界中。

  • 然而,我們經常說:“讓我們遠離那種構造,它甚至不在 POSIX 中。”

  • 儘管有以上兩條規則,我們有時也會說:“雖然這不在 POSIX 中,但它(非常方便 | 使程式碼更具可讀性 | 具有其他優點),並且我們關心的所有平臺幾乎都支援它,所以讓我們使用它。”

    Again, we live in the real world, and it is sometimes a
    judgement call, the decision based more on real world
    constraints people face than what the paper standard says.
  • 在處理實際更改時,修復樣式違規作為準備性的清理步驟是好的,但除此之外,要避免為了符合樣式而進行無用的程式碼攪動。

    "Once it _is_ in the tree, it's not really worth the patch noise to
    go and fix it up."
    Cf. https://lore.kernel.org/all/20100126160632.3bdbe172.akpm@linux-foundation.org/
  • 解釋您更改的日誌訊息與更改本身一樣重要。清晰編寫的程式碼和程式碼內註釋解釋了程式碼如何工作以及從周圍上下文中假設了什麼。日誌訊息解釋了更改想要達到的目標以及為什麼更改是必要的(更多資訊請參閱隨附的 SubmittingPatches 文件)。

使您的程式碼可讀且明智,不要試圖表現得很聰明。

至於更具體的指南,只需模仿現有程式碼(無論您為哪個專案做出貢獻,這都是一個好指南)。始終首選匹配*本地*約定。新增到 Git 套件的新程式碼應匹配現有程式碼的整體風格。對現有程式碼的修改應匹配周圍程式碼已經使用的風格(即使它不匹配現有程式碼的整體風格)。

但如果您必須有一個規則列表,這裡有一些特定於語言的規則。請注意,Documentation/ToolsForGit.adoc 文件包含了一系列技巧,可幫助您使用一些外部工具來遵循這些指南。

特別是對於 shell 指令碼(不詳盡):

  • 我們使用製表符進行縮排。

  • case 分支與 case 和 esac 行具有相同的縮排深度,如下所示:

    case "$variable" in
    pattern1)
    	do this
    	;;
    pattern2)
    	do that
    	;;
    esac
  • 重定向運算子應在它們之前留有空格,但在它們之後不留空格。換句話說,寫 *echo test >"$file"* 而不是 *echo test> $file* 或 *echo test > $file*。請注意,即使 POSIX 不要求在變數中雙引號重定向目標(如上所示),我們的程式碼也會這樣做,因為某些 bash 版本會在沒有引號時發出警告。

    (incorrect)
    cat hello > world < universe
    echo hello >$world
    (correct)
    cat hello >world <universe
    echo hello >"$world"
  • 我們更喜歡 $( …​ ) 用於命令替換;與 `` 不同,它能正確巢狀。它本應是 Bourne 從一開始就使用的拼寫方式,但可惜不是。

  • 如果您想找出使用者 $PATH 中是否可用某個命令,應使用 *type <command>*,而不是 *which <command>*。*which* 的輸出不可機器解析,且其退出碼在不同平臺上不可靠。

  • 我們使用符合 POSIX 的引數替換,並避免 bashism;即:

  • 我們使用 ${parameter-word} 及其 [-=?+] 兄弟,以及它們的帶冒號的“未設定或為空”形式。

  • 我們使用 ${parameter#word} 及其 [#%] 兄弟,以及它們的雙重“最長匹配”形式。

  • 無“子字串擴充套件” ${parameter:offset:length}。

  • 無 shell 陣列。

  • 無模式替換 ${parameter/pattern/string}。

  • 我們使用算術擴充套件 $…​。

  • 我們不使用程序替換 <(list) 或 >(list)。

  • 不要將控制結構寫在同一行並用分號分隔。“then”應在新的一行上用於 if 語句,而“do”應在新的一行上用於“while”和“for”。

    (incorrect)
    if test -f hello; then
    	do this
    fi
    (correct)
    if test -f hello
    then
    	do this
    fi
  • 如果一個由 && 或 || 或 | 連線的命令序列跨越多行,將每個命令放在單獨的行上,並將 && 和 || 和 | 運算子放在每行的末尾,而不是開頭。這意味著您不需要使用 \ 來連線行,因為上述運算子意味著序列尚未完成。

    (incorrect)
    grep blob verify_pack_result \
    | awk -f print_1.awk \
    | sort >actual &&
    ...
    (correct)
    grep blob verify_pack_result |
    awk -f print_1.awk |
    sort >actual &&
    ...
  • 我們更喜歡 "test" 而不是 "[ …​ ]"。

  • 我們不在 shell 函式前寫多餘的“function”關鍵字。

  • 我們更喜歡函式名和括號之間有一個空格,而括號內部沒有空格。開頭的“{”也應在同一行。

    (incorrect)
    my_function(){
    	...
    (correct)
    my_function () {
    	...
  • 關於 grep 的使用,為了可移植性,請堅持使用 BRE 的子集(即,不使用 \{m,n\}, [::], [==], 或 [..])。

  • 我們不使用 \{m,n\};

  • 我們不使用 ? 或 +(它們在 BRE 中分別是 \{0,1\} 和 \{1,\}),但這不言而喻,因為這些是 ERE 元素而不是 BRE(請注意,\? 和 \+ 甚至不是 BRE 的一部分 — 使它們可以從 BRE 中訪問是 GNU 擴充套件)。

  • 使用 Git 的 gettext 包裝器在 git-sh-i18n 中使使用者介面可翻譯。請參閱 po/README 中的“標記字串以供翻譯”。

  • 我們不使用 "-a" 和 "-o" 來編寫我們的 "test" 命令,而是使用 "&&" 或 "||" 來連線多個 "test" 命令,因為 "-a/-o" 的使用經常出錯。例如:

    test -n "$x" -a "$a" = "$b"
    is buggy and breaks when $x is "=", but
    test -n "$x" && test "$a" = "$b"
    does not have such a problem.
  • 雖然 "local" 不是 POSIX 的一部分,但我們在測試套件中大量使用它。我們不在指令碼化的 Porcelains 中使用它,並希望沒有人開始使用 "local" 在所有我們關心的 shell 支援它之前(特別是,來自 AT&T Research 的 ksh 尚不支援它)。

  • 某些版本的 shell 不理解 "export variable=value",因此我們將其寫為 "variable=value" 然後在兩個單獨的行上寫 "export variable"。

  • 某些版本的 dash 在變數賦值前加上 "local"、"export" 和 "readonly" 時存在錯誤的變數賦值,即要賦值的值會經過欄位拆分在 $IFS 上,除非被引用。

    (incorrect)
    local variable=$value
    local variable=$(command args)
    (correct)
    local variable="$value"
    local variable="$(command args)"
  • 常見的構造

    VAR=VAL command args
    to temporarily set and export environment variable VAR only while
    "command args" is running is handy, but this triggers an
    unspecified behaviour according to POSIX when used for a command
    that is not an external command (like shell functions).  Indeed,
    dash 0.5.10.2-6 on Ubuntu 20.04, /bin/sh on FreeBSD 13, and AT&T
    ksh all make a temporary assignment without exporting the variable,
    in such a case.  As it does not work portably across shells, do not
    use this syntax for shell functions.  A common workaround is to do
    an explicit export in a subshell, like so:
    (incorrect)
    VAR=VAL func args
    (correct)
    (
    	VAR=VAL &&
    	export VAR &&
    	func args
    )
    but be careful that the effect "func" makes to the variables in the
    current shell will be lost across the subshell boundary.
  • 在 printf 格式字串中使用八進位制轉義序列(例如 "\302\242"),而不是十六進位制(例如 "\xc2\xa2"),因為十六進位制轉義序列不可移植。

對於 C 程式:

  • 我們使用製表符進行縮排,並將製表符解釋為最多 8 個空格。

  • 巢狀的 C 預處理器指令在 # 之後按每個巢狀級別縮排一個空格。

    #if FOO
    # include <foo.h>
    # if BAR
    #  include <bar.h>
    # endif
    #endif
  • 我們儘量將每行限制在 80 個字元以內。

  • 作為 Git 開發者,我們假設您擁有一個相當現代的編譯器,並建議您啟用 DEVELOPER makefile 選項,以確保您的補丁清除所有我們關心的編譯器警告,例如透過“echo DEVELOPER=1 >>config.mak”。

  • 在使用 DEVELOPER=1 模式時,您可能會看到來自編譯器的警告,例如“error: unused parameter foo [-Werror=unused-parameter]”,這表明一個函式忽略了它的引數。如果未使用的引數無法刪除(例如,因為該函式被用作回撥並且必須匹配某個介面),您可以使用 UNUSED(或 MAYBE_UNUSED)關鍵字來註解單個引數,例如“int foo UNUSED”。

  • 我們儘量支援多種 C 編譯器來編譯 Git,包括舊的編譯器。截至 Git v2.35.0,Git 需要 C99(我們檢查“STDC_VERSION”)。您不應使用更新的 C 標準中的功能,即使您的編譯器支援它們。

    New C99 features have been phased in gradually, if something's new
    in C99 but not used yet don't assume that it's safe to use, some
    compilers we target have only partial support for it. These are
    considered safe to use:
    1. 自 2007 年左右(透過 2b6854c863a)以來,我們一直使用在載入時不可計算的初始化元素。例如:

      const char *args[] = { "constant", variable, NULL };
    2. 自 2012 年初(透過 e1327023ea)以來,我們一直使用一個 enum 定義,其最後一個元素後面有一個逗號。這與以尾部逗號結尾的陣列初始化器一樣,可用於在新增新識別符號時減少補丁噪音。

    3. 自 2017 年中期(透過 cbc0f81d)以來,我們一直使用結構體的指定初始化器(例如“struct t v = { .val = a };”)。

    4. 自 2017 年中期(透過 512f41cf)以來,我們一直使用陣列的指定初始化器(例如“int array[10] = { [5] = 2 }”)。

    5. 自 2021 年初(透過 765dc168882)以來,我們一直使用可變引數宏,主要用於類似 printf 的跟蹤和除錯宏。

    6. 自 2021 年末(透過 44ba10d6)以來,我們在 for 迴圈中聲明瞭變數“for (int i = 0; i < 10; i++)”。

    7. 自 2023 年末(透過 8277dbe987)以來,我們一直在使用來自 <stdbool.h> 的 bool 型別。

      C99 features we have test balloons for:
    8. 自 2024 年末(透過 v2.48.0-rc0~20)以來,我們有用於複合字面量語法的測試氣球,例如 (struct foo){ .member = value }; 我們希望我們關心的平臺在使用它們時不會遇到問題,並將在 2026 年中期正式採納其更廣泛的使用。在此之前,請勿新增更多使用此語法的示例。

      New C99 features that we cannot use yet:
    9. %z 和 %zu 作為 size_t 的 printf() 引數(%z 用於 POSIX 特定的 ssize_t)。您應該改用 printf("%"PRIuMAX, (uintmax_t)v)。如今,我們依賴的 MSVC 版本支援 %z,但 MinGW 使用的 C 庫不支援。

    10. 結構體初始化中的簡寫方式,如 ".a.b = *c",已知會導致舊版 IBM XLC 出現問題,請改用 ".a = { .b = *c }"。請參閱 33665d98(reftable: 使賦值對 AIX xlc v12.01 可移植,2022-03-28)。

  • 變數必須在塊開始處,第一個語句之前宣告(即 -Wdeclaration-after-statement)。鼓勵在宣告結束和塊內的第一個語句之間留一個空行。

  • 不要顯式將全域性變數初始化為 0 或 NULL;相反,讓 BSS 來處理零初始化。

  • NULL 指標應寫為 NULL,而不是 0。

  • 宣告指標時,星號與變數名對齊,即 "char *string",而不是 "char** string" 或 "char * string"。這使得理解 "char *string, c;" 這樣的程式碼更容易。

  • 在運算子和關鍵字周圍使用空格,但在括號內和函數週圍不使用。所以:

          while (condition)
    func(bar + 1);
    and not:
          while( condition )
    func (bar+1);
  • 二進位制運算子(, 除外)和三元條件運算子 "?:" 在運算子兩側各有一個空格,將其與其運算元分開。例如 "A + 1",而不是 "A+1"。

  • 一元運算子(. 和 → 除外)在其運算元之間不留空格。例如 "(char *)ptr",而不是 "(char *) ptr"。

  • 不要將整數值與常量 0 或 *`\0`*,或指標值與常量 NULL 進行顯式比較。例如,要驗證計數的陣列 <ptr, cnt> 已初始化但沒有元素,請這樣寫:

    if (!ptr || cnt)
    	BUG("empty array expected");
    and not:
    if (ptr == NULL || cnt != 0);
    	BUG("empty array expected");
  • 我們避免不必要地使用花括號。即:

    if (bla) {
    	x = 1;
    }
    is frowned upon. But there are a few exceptions:
  • 當語句跨越多行時(例如,一個帶有嵌入式條件的 while 迴圈,或一個註釋)。例如:

    while (foo) {
    	if (x)
    		one();
    	else
    		two();
    }
    if (foo) {
    	/*
    	 * This one requires some explanation,
    	 * so we're better off with braces to make
    	 * it obvious that the indentation is correct.
    	 */
    	doit();
    }
  • 當條件語句有多個分支,其中一些分支需要花括號時,即使是單行程式碼塊也用花括號括起來以保持一致性。例如:

    if (foo) {
    	doit();
    } else {
    	one();
    	two();
    	three();
    }
  • 我們儘量避免在 "if" 語句的條件中使用賦值。

  • 儘量使您的程式碼易於理解。您可以添加註釋,但註釋的內容往往會隨著其描述的程式碼的改變而過時。通常將一個函式拆分成兩個會使程式碼的意圖更加清晰。

  • 多行註釋將其分隔符放在與文字分開的行上。例如:

    /*
     * A very long
     * multi-line comment.
     */
    Note however that a comment that explains a translatable string to
    translators uses a convention of starting with a magic token
    "TRANSLATORS: ", e.g.
    /*
     * TRANSLATORS: here is a comment that explains the string to
     * be translated, that follows immediately after it.
     */
    _("Here is a translatable string explained by the above.");
  • 雙重否定通常比根本沒有否定更難理解。

  • 關於比較,尤其是在迴圈內,有兩種觀點。一些人喜歡將不穩定的值放在左邊,穩定的值放在右邊,例如,如果您有一個從上到下計數變數 i 的迴圈,

    while (i > lower_bound) {
    	do something;
    	i--;
    }
    Other people prefer to have the textual order of values match the
    actual order of values in their comparison, so that they can
    mentally draw a number line from left to right and place these
    values in order, i.e.
    while (lower_bound < i) {
    	do something;
    	i--;
    }
    Both are valid, and we use both.  However, the more "stable" the
    stable side becomes, the more we tend to prefer the former
    (comparison with a constant, "i > 0", is an extreme example).
    Just do not mix styles in the same part of the code and mimic
    existing styles in the neighbourhood.
  • 關於將長邏輯行拆分成多行,有兩種觀點。一些人將第二行及後續行向右推得足夠遠,並使用製表符對齊它們。

          if (the_beginning_of_a_very_long_expression_that_has_to ||
    span_more_than_a_single_line_of ||
    the_source_text) {
                  ...
    while other people prefer to align the second and the subsequent
    lines with the column immediately inside the opening parenthesis,
    with tabs and spaces, following our "tabstop is always a multiple
    of 8" convention:
       if (the_beginning_of_a_very_long_expression_that_has_to ||
    span_more_than_a_single_line_of ||
    the_source_text) {
               ...
    Both are valid, and we use both.  Again, just do not mix styles in
    the same part of the code and mimic existing styles in the
    neighbourhood.
  • 拆分長邏輯行時,有些人會在二進位制運算子之前換行,這樣當你將頭部逆時針旋轉 90 度時,結果看起來就像一個解析樹。

       if (the_beginning_of_a_very_long_expression_that_has_to
    || span_more_than_a_single_line_of_the_source_text) {
    while other people prefer to leave the operator at the end of the
    line:
       if (the_beginning_of_a_very_long_expression_that_has_to ||
    span_more_than_a_single_line_of_the_source_text) {
    Both are valid, but we tend to use the latter more, unless the
    expression gets fairly complex, in which case the former tends to
    be easier to read.  Again, just do not mix styles in the same part
    of the code and mimic existing styles in the neighbourhood.
  • 拆分長邏輯行時,在其他條件相同的情況下,更傾向於在解析樹中級別較高的運算子之後拆分。也就是說,這樣做更可取:

    if (a_very_long_variable * that_is_used_in +
        a_very_long_expression) {
    	...
    than
    if (a_very_long_variable *
        that_is_used_in + a_very_long_expression) {
    	...
  • 一些聰明的技巧,比如對算術構造使用 !! 運算子,可能會讓別人非常困惑。除非有令人信服的理由,否則避免使用它們。

  • 使用 API。不,真的。我們有 strbuf(可變長度字串)、幾個帶有 ALLOC_GROW() 宏的陣列、一個用於排序字串列表的 string_list,一個名為 "struct decorate" 的雜湊對映(對映 struct 物件),等等。

  • 當您提出一個 API 時,請在將 API 暴露給呼叫者的標頭檔案中記錄其函式和結構。使用 "strbuf.h" 中的內容作為適當的語氣和詳細程度的模型。

  • C 檔案中的第一個 #include(除了平臺特定的 compat/ 實現和 sha1dc/ 之外),必須是 <git-compat-util.h>。這個標頭檔案將其他標頭檔案和原始檔與平臺差異隔離開來,例如需要按什麼順序包含哪些系統標頭檔案,以及必須定義哪些 C 預處理器功能宏來觸發我們期望從系統中獲得的某些功能。其推論是 C 檔案本身不應直接包含系統標頭檔案。

    There are some exceptions, because certain group of files that
    implement an API all have to include the same header file that
    defines the API and it is convenient to include <git-compat-util.h>
    there.  Namely:
  • 位於 "builtin/" 目錄下的內建命令的實現,它們包含 "builtin.h" 以獲取 cmd_foo() 的原型定義。

  • 位於 "t/helper/" 目錄下的測試輔助程式,它們包含 "t/helper/test-tool.h" 以獲取 cmd__foo() 的原型定義。

  • 位於 "xdiff/" 目錄下的 xdiff 實現,它們包含 "xdiff/xinclude.h" 以獲取 xdiff 機器內部。

  • 位於 "t/unit-tests/" 目錄下的單元測試程式,它們包含 "t/unit-tests/test-lib.h",這為它們提供了單元測試框架。

  • 位於 "reftable/" 目錄下的 reftable 實現的原始檔,它們包含 "reftable/system.h" 以獲取 reftable 內部。

    are allowed to assume that they do not have to include
    <git-compat-util.h> themselves, as it is included as the first
    '#include' in these header files.  These headers must be the first
    header file to be "#include"d in them, though.
  • C 檔案必須直接包含宣告其使用的函式和型別的標頭檔案,但透過包含先前規則所必需的標頭檔案之一而可用的函式和型別除外。

  • 如果您計劃開發一個新命令,請考慮先用 shell 或 perl 編寫它,以便語義上的更改可以輕鬆地進行修改和討論。許多 Git 命令都是這樣開始的,其中一些仍然是指令碼。

  • 避免為 Git 引入新的依賴項。這意味著您通常應該遠離 Git 核心命令集中尚未使用的指令碼語言(除非您的命令明顯與之分開,例如用於將隨機 SCM-X 儲存庫轉換為 Git 的匯入器)。

  • 當我們將 <string, length> 對傳遞給函式時,我們應該嘗試按此順序傳遞它們。

  • 使用 Git 的 gettext 包裝器使使用者介面可翻譯。請參閱 po/README 中的“標記字串以供翻譯”。

  • 僅限於給定原始檔的變數和函式應標記為 "static"。對其他原始檔可見的變數必須在標頭檔案中用 "extern" 宣告。但是,函式宣告不應使用 "extern",因為這是預設的。

  • 您可以使用簡寫 GIT_DEBUGGER 來啟動 gdb 圍繞您的程式。執行 GIT_DEBUGGER=1 ./bin-wrappers/git foo 來直接使用 gdb,或執行 GIT_DEBUGGER="<debugger> <debugger-args>" ./bin-wrappers/git foo 來使用您自己的偵錯程式和引數。示例:GIT_DEBUGGER="ddd --gdb" ./bin-wrappers/git log(參見 bin-wrappers/wrap-for-bin.sh)。

  • 子系統 *S* 所處理的主要資料結構稱為 struct S。操作 struct S 的函式命名為 S_<verb>(),並且通常應將指向 struct S 的指標作為第一個引數。例如:

    struct strbuf;
    void strbuf_add(struct strbuf *buf, ...);
    void strbuf_reset(struct strbuf *buf);
    is preferred over:
    struct strbuf;
    void add_string(struct strbuf *buf, ...);
    void reset_strbuf(struct strbuf *buf);
  • 對於對結構 S 執行特定任務的函式,有幾種常見的慣用名稱:

  • S_init() 初始化一個結構,而不分配結構本身。

  • S_release() 釋放結構的內容,而不重新初始化結構以供立即重用,也不釋放結構本身。

  • S_clear() 等同於 S_release() 後跟 S_init(),以便結構在清除後可直接使用。當提供 S_clear() 時,S_init() 不應分配需要再次釋放的資源。

  • S_free() 釋放結構的內容並釋放結構。

  • 函式名應清晰且具有描述性,準確反映其目的或行為。不新增有意義上下文的任意字尾可能會導致混淆,尤其是對於新加入程式碼庫的人來說。

    Historically, the '_1' suffix has been used in situations where:
  • 一個函式處理一組需要類似處理的元素中的一個。

  • 遞迴函式已與其設定階段分開。

    The '_1' suffix can be used as a concise way to indicate these specific
    cases. However, it is recommended to find a more descriptive name wherever
    possible to improve the readability and maintainability of the code.
  • 位欄位定義時不應在冒號周圍留有空格。例如:

    unsigned my_field:1;
    unsigned other_field:1;
    unsigned field_with_longer_name:1;

對於 Perl 程式:

  • 上面的大多數 C 指導原則也適用。

  • 我們嘗試支援 Perl 5.8.1 及更高版本("use Perl 5.008001")。

  • 強烈建議使用 strict 和 warnings。

  • 除非使用它們能使結果更容易理解,否則不要過度使用語句修飾符。

    1. do something …​ do_this() unless (condition);

    2. do something else …​

      is more readable than:
    3. do something …​ unless (condition) { do_this(); }

    4. do something else …​

      *only* when the condition is so rare that do_this() will be almost
      always called.
  • 我們儘量避免在 "if ()" 條件中使用賦值。

  • 如果您需要該功能,請學習並使用 Git.pm。

對於 Python 指令碼:

  • 我們遵循 PEP-8(https://peps.python.org/pep-0008/)。

  • 至少,我們的目標是相容 Python 2.7。

  • 在必需的庫不限制我們使用 Python 2 的情況下,我們還嘗試相容 Python 3.1 及更高版本。

程式輸出

We make a distinction between a Git command's primary output and
output which is merely chatty feedback (for instance, status
messages, running transcript, or progress display), as well as error
messages. Roughly speaking, a Git command's primary output is that
which one might want to capture to a file or send down a pipe; its
chatty output should not interfere with these use-cases.
As such, primary output should be sent to the standard output stream
(stdout), and chatty output should be sent to the standard error
stream (stderr). Examples of commands which produce primary output
include `git log`, `git show`, and `git branch --list` which generate
output on the stdout stream.
Not all Git commands have primary output; this is often true of
commands whose main function is to perform an action. Some action
commands are silent, whereas others are chatty. An example of a
chatty action commands is `git clone` with its "Cloning into
'<path>'..." and "Checking connectivity..." status messages which it
sends to the stderr stream.
Error messages from Git commands should always be sent to the stderr
stream.

錯誤訊息

  • 不要在單句錯誤訊息的末尾加上句點。

  • 不要將第一個詞大寫,僅僅因為它是一個句子中的第一個詞("unable to open %s",而不是 "Unable to open %s")。但 "SHA-3 not supported" 是可以的,因為第一個詞大寫的原因不是因為它位於句子的開頭,而是因為即使出現在句子中間,該詞也會以大寫字母拼寫。

  • 先說明錯誤是什麼("cannot open %s",而不是 "%s: cannot open")。

  • 在錯誤的主題兩側加上一對單引號,例如 die(_("unable to open %s'"), path)

  • 除非有令人信服的理由不這樣做,否則 porcelain 命令的錯誤訊息應標記為可翻譯,例如 die(_("bad revision %s"), revision)

  • plumbing 命令的錯誤訊息有時是供機器使用的,不應標記為可翻譯,例如 die("bad revision %s", revision)

  • BUG("message") 用於向開發者傳達特定錯誤,因此不應被翻譯。

外部可見名稱

  • 對於配置變數名,請遵循現有約定。

    1. 節名指示受影響的子系統。

    2. 子節名(如果存在)指示要設定值的無界集合中的哪個。

    3. 變數名描述了調整此控制元件的效果。

      The section and variable names that consist of multiple words are
      formed by concatenating the words without punctuation marks (e.g. `-`),
      and are broken using bumpyCaps in documentation as a hint to the
      reader.
      When choosing the variable namespace, do not use variable name for
      specifying possibly unbounded set of things, most notably anything
      an end user can freely come up with (e.g. branch names).  Instead,
      use subsection names or variable values, like the existing variable
      branch.<name>.description does.

編寫文件

Most (if not all) of the documentation pages are written in the
AsciiDoc format in *.adoc files (e.g. Documentation/git.adoc), and
processed into HTML and manpages (e.g. git.html and git.1 in the
same directory).
The documentation liberally mixes US and UK English (en_US/UK)
norms for spelling and grammar, which is somewhat unfortunate.
In an ideal world, it would have been better if it consistently
used only one and not the other, and we would have picked en_US
(if you wish to correct the English of some of the existing
documentation, please see the documentation-related advice in the
Documentation/SubmittingPatches file).
In order to ensure the documentation is inclusive, avoid assuming
that an unspecified example person is male or female, and think
twice before using "he", "him", "she", or "her".  Here are some
tips to avoid use of gendered pronouns:
  • 傾向於簡潔地、實事求是地描述抽象功能。例如:

    --short

    以短格式輸出。

    and avoid something like these overly verbose alternatives:
    --short

    使用此選項以短格式輸出。

    --short

    您可以使用此選項以短格式獲取輸出。

    --short

    偏好短輸出的使用者可能會……

    --short

    如果某人或程式想要更短的輸出,他們/它就可以……

    This practice often eliminates the need to involve human actors in
    your description, but it is a good practice regardless of the
    avoidance of gendered pronouns.
  • 當堅持這種風格變得笨拙時,在稱呼假設的使用者時傾向於使用“you”,並在討論程式如何響應使用者時可能使用“we”。例如:

    You can use this option instead of `--xyz`, but we might remove
    support for it in future versions.
    while keeping in mind that you can probably be less verbose, e.g.
    Use this instead of `--xyz`. This option might be removed in future
    versions.
  • 如果您仍然需要引用一個假設的第三人稱單數人物,您可以求助於“單數 they”來避免“he/she/him/her”,例如:

    A contributor asks their upstream to pull from them.
    Note that this sounds ungrammatical and unnatural to those who
    learned that "they" is only used for third-person plural, e.g.
    those who learn English as a second language in some parts of the
    world.
    Every user-visible change should be reflected in the documentation.
    The same general rule as for code applies -- imitate the existing
    conventions.

標記

Literal parts (e.g. use of command-line options, command names,
branch names, URLs, pathnames (files and directories), configuration and
environment variables) must be typeset as verbatim (i.e. wrapped with
backticks):
  `--pretty=oneline`
  `git rev-list`
  `remote.pushDefault`
  `http://git.example.com`
  `.git/config`
  `GIT_DIR`
  `HEAD`
  `umask`(2)
An environment variable must be prefixed with "$" only when referring to its
value and not when referring to the variable itself, in this case there is
nothing to add except the backticks:
  `GIT_DIR` is specified
  `$GIT_DIR/hooks/pre-receive`
Word phrases enclosed in `backtick characters` are rendered literally
and will not be further expanded. The use of `backticks` to achieve the
previous rule means that literal examples should not use AsciiDoc
escapes.
  Correct:
     `--pretty=oneline`
  Incorrect:
     `\--pretty=oneline`
Placeholders are spelled in lowercase and enclosed in
angle brackets surrounded by underscores:
  _<file>_
  _<commit>_
If a placeholder has multiple words, they are separated by dashes:
  _<new-branch-name>_
  _<template-directory>_
When needed, use a distinctive identifier for placeholders, usually
made of a qualification and a type:
  _<git-dir>_
  _<key-id>_

字元也用下劃線環繞:LFCRCR/LFNULEOF

Git's Asciidoc processor has been tailored to treat backticked text
as complex synopsis. When literal and placeholders are mixed, you can
use the backtick notation which will take care of correctly typesetting
the content.
  `--jobs <n>`
  `--sort=<key>`
  `<directory>/.git`
  `remote.<name>.mirror`
  `ssh://[<user>@]<host>[:<port>]/<path-to-git-repo>`

作為副作用,反引號佔位符會被正確排版,但這種風格不被推薦。

When documenting multiple related `git config` variables, place them on
a separate line instead of separating them by commas.  For example, do
not write this:
  `core.var1`, `core.var2`::
Description common to `core.var1` and `core.var2`.

而是這樣寫:core.var1:: core.var2:: core.var1core.var2 的共同描述。

Synopsis 語法

The synopsis (a paragraph with [synopsis] attribute) is automatically
formatted by the toolchain and does not need typesetting.
A few commented examples follow to provide reference when writing or
modifying command usage strings and synopsis sections in the manual
pages:
Possibility of multiple occurrences is indicated by three dots:
  <file>...
  (One or more of <file>.)
Optional parts are enclosed in square brackets:
  [<file>...]
  (Zero or more of <file>.)
An optional parameter needs to be typeset with unconstrained pairs
  [<repository>]
--exec-path[=<path>]
(Option with an optional argument.  Note that the "=" is inside the
brackets.)
[<patch>...]
(Zero or more of <patch>.  Note that the dots are inside, not
outside the brackets.)
Multiple alternatives are indicated with vertical bars:
  [-q | --quiet]
  [--utf8 | --no-utf8]
Use spacing around "|" token(s), but not immediately after opening or
before closing a [] or () pair:
  Do: [-q | --quiet]
  Don't: [-q|--quiet]
Don't use spacing around "|" tokens when they're used to separate the
alternate arguments of an option:
   Do: --track[=(direct|inherit)]
   Don't: --track[=(direct | inherit)]
Parentheses are used for grouping:
  [(<rev>|<range>)...]
  (Any number of either <rev> or <range>.  Parens are needed to make
  it clear that "..." pertains to both <rev> and <range>.)
[(-p <parent>)...]
(Any number of option -p, each with one <parent> argument.)
git remote set-head <name> (-a|-d|<branch>)
(One and only one of "-a", "-d" or "<branch>" _must_ (no square
brackets) be provided.)
And a somewhat more contrived example:
  --diff-filter=[(A|C|D|M|R|T|U|X|B)...[*]]
  Here "=" is outside the brackets, because "--diff-filter=" is a
  valid usage.  "*" has its own pair of brackets, because it can
  (optionally) be specified only when one or more of the letters is
  also provided.
A note on notation:
 Use 'git' (all lowercase) when talking about commands i.e. something
 the user would type into a shell and use 'Git' (uppercase first letter)
 when talking about the version control system and its properties.
If some place in the documentation needs to typeset a command usage
example with inline substitutions, it is fine to use +monospaced and
inline substituted text+ instead of `monospaced literal text`, and with
the former, the part that should not get substituted must be
quoted/escaped.