章節 ▾ 第二版

8.1 自定義 Git - Git 配置

到目前為止,我們已經介紹了 Git 的工作原理和使用方法,並介紹了一些 Git 提供的工具,幫助您輕鬆高效地使用它。在本章中,我們將透過介紹幾個重要的配置設定和鉤子系統,瞭解如何使 Git 以更自定義的方式執行。有了這些工具,您可以輕鬆地讓 Git 完全按照您、您的公司或您的團隊所需的方式工作。

Git 配置

正如您在入門中簡要閱讀的那樣,您可以使用git config命令指定 Git 配置設定。您做的第一件事就是設定您的姓名和電子郵件地址

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

現在您將學習一些更有趣的選項,您可以透過這種方式進行設定,以自定義您的 Git 使用。

首先,快速回顧一下:Git 使用一系列配置檔案來確定您可能想要的非預設行為。Git 查詢這些值的第一個地方是系統級的[path]/etc/gitconfig檔案,該檔案包含應用於系統上每個使用者及其所有倉庫的設定。如果您將--system選項傳遞給git config,它將專門從該檔案讀取和寫入。

Git 查詢的下一個地方是~/.gitconfig(或~/.config/git/config)檔案,該檔案特定於每個使用者。您可以透過傳遞--global選項使 Git 從該檔案讀取和寫入。

最後,Git 會在您當前使用的任何倉庫的 Git 目錄(.git/config)中的配置檔案中查詢配置值。這些值特定於該單個倉庫,並表示將--local選項傳遞給git config。如果您不指定要使用的級別,則這是預設值。

這些“級別”(系統、全域性、本地)中的每一個都會覆蓋前一個級別中的值,例如,.git/config中的值會覆蓋[path]/etc/gitconfig中的值。

注意

Git 的配置檔案是純文字檔案,因此您也可以透過手動編輯檔案並插入正確的語法來設定這些值。不過,通常執行git config命令會更容易。

基本客戶端配置

Git 識別的配置選項分為兩類:客戶端和伺服器端。大多數選項都是客戶端的——配置您的個人工作偏好。支援許多許多配置選項,但其中很大一部分只在某些邊緣情況下有用;我們在此只介紹最常見和最有用的選項。如果您想檢視您的 Git 版本識別的所有選項列表,可以執行

$ man git-config

此命令會列出所有可用選項,並且非常詳細。您還可以在https://git-scm.tw/docs/git-config找到此參考資料。

注意

對於高階用例,您可能需要查閱上述文件中的“條件包含”。

core.editor

預設情況下,Git 使用您透過 shell 環境變數VISUALEDITOR設定的預設文字編輯器,否則會回退到vi編輯器來建立和編輯您的提交和標籤訊息。要將該預設值更改為其他值,您可以使用core.editor設定

$ git config --global core.editor emacs

現在,無論您的預設 shell 編輯器設定為哪個,Git 都將啟動 Emacs 來編輯訊息。

commit.template

如果您將其設定為系統上檔案的路徑,Git 將在您提交時使用該檔案作為預設的初始訊息。建立自定義提交模板的價值在於,您可以使用它來提醒自己(或他人)在建立提交訊息時應遵循的正確格式和樣式。

例如,考慮一個位於~/.gitmessage.txt的模板檔案,它看起來像這樣

Subject line (try to keep under 50 characters)

Multi-line description of commit,
feel free to be detailed.

[Ticket: X]

請注意此提交模板如何提醒提交者保持主題行簡短(為了git log --oneline輸出的方便),在其下方新增更多細節,並在存在問題或錯誤跟蹤票號時進行引用。

要告訴 Git 在您執行git commit時將其用作編輯器中出現的預設訊息,請設定commit.template配置值

$ git config --global commit.template ~/.gitmessage.txt
$ git commit

然後,當您提交時,您的編輯器將開啟,顯示類似這樣的佔位符提交訊息

Subject line (try to keep under 50 characters)

Multi-line description of commit,
feel free to be detailed.

[Ticket: X]
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   lib/test.rb
#
~
~
".git/COMMIT_EDITMSG" 14L, 297C

如果您的團隊有提交訊息策略,那麼將該策略的模板放在您的系統上並配置 Git 預設使用它,可以幫助提高該策略被定期遵循的可能性。

core.pager

此設定決定了當 Git 分頁輸出(例如logdiff)時使用哪個分頁器。您可以將其設定為more或您喜歡的分頁器(預設是less),或者透過將其設定為空字串來關閉它

$ git config --global core.pager ''

如果您執行該命令,Git 將列印所有命令的完整輸出,無論它們有多長。

user.signingkey

如果您正在建立帶簽名的標註標籤(如簽署工作中所述),將您的 GPG 簽名金鑰設定為配置設定會使事情變得更容易。像這樣設定您的金鑰 ID

$ git config --global user.signingkey <gpg-key-id>

現在,您可以簽署標籤,而無需每次都使用git tag命令指定您的金鑰

$ git tag -s <tag-name>

core.excludesfile

您可以將模式放入專案的.gitignore檔案中,以便 Git 不將它們視為未跟蹤檔案,也不會在您對其執行git add時嘗試暫存它們,這在忽略檔案中已討論。

但有時您希望忽略您使用的所有倉庫中的某些檔案。如果您的計算機執行 macOS,您可能熟悉.DS_Store檔案。如果您首選的編輯器是 Emacs 或 Vim,您就知道以~.swp結尾的檔名。

此設定允許您編寫一種全域性.gitignore檔案。如果您建立一個內容如下的~/.gitignore_global檔案

*~
.*.swp
.DS_Store

…然後您執行git config --global core.excludesfile ~/.gitignore_global,Git 將永遠不再為這些檔案煩擾您。

help.autocorrect

如果您輸入錯誤的命令,它會顯示類似這樣的內容

$ git chekcout master
git: 'chekcout' is not a git command. See 'git --help'.

The most similar command is
    checkout

Git 會很貼心地嘗試弄清楚您的意思,但它仍然拒絕執行。如果您將help.autocorrect設定為 1,Git 將實際為您執行此命令

$ git chekcout master
WARNING: You called a Git command named 'chekcout', which does not exist.
Continuing under the assumption that you meant 'checkout'
in 0.1 seconds automatically...

請注意“0.1 秒”的含義。help.autocorrect實際上是一個整數,代表十分之一秒。因此,如果您將其設定為 50,Git 將給您 5 秒鐘的時間來改變主意,然後才會執行自動更正的命令。

Git 中的顏色

Git 完全支援彩色終端輸出,這極大地有助於快速輕鬆地視覺解析命令輸出。許多選項可以幫助您根據自己的喜好設定顏色。

color.ui

Git 會自動為大部分輸出著色,但如果您不喜歡此行為,則有一個主開關。要關閉所有 Git 的彩色終端輸出,請執行此操作

$ git config --global color.ui false

預設設定是auto,當輸出直接傳送到終端時會著色,但當輸出重定向到管道或檔案時會省略顏色控制程式碼。

您也可以將其設定為always以忽略終端和管道之間的差異。您很少會需要這個;在大多數情況下,如果您希望在重定向輸出中包含顏色程式碼,您可以改為將--color標誌傳遞給 Git 命令,強制它使用顏色程式碼。預設設定幾乎總是您想要的。

color.*

如果您想更具體地控制哪些命令如何著色,Git 提供了特定於動詞的著色設定。這些設定都可以設定為truefalsealways

color.branch
color.diff
color.interactive
color.status

此外,每個設定都有子設定,如果您想覆蓋每種顏色,可以使用它們為輸出的特定部分設定特定顏色。例如,要將差異輸出中的元資訊設定為藍色前景、黑色背景和粗體文字,您可以執行

$ git config --global color.diff.meta "blue black bold"

您可以將顏色設定為以下任何值:normalblackredgreenyellowbluemagentacyanwhite。如果您想要像上一個示例中的粗體這樣的屬性,您可以從bolddimul(下劃線)、blinkreverse(交換前景和背景)中選擇。

外部合併和差異工具

儘管 Git 具有內部的差異實現(本書中一直展示的),但您可以設定一個外部工具來代替。您還可以設定一個圖形化的合併衝突解決工具,而無需手動解決衝突。我們將演示如何設定 Perforce Visual Merge Tool (P4Merge) 來執行您的差異和合並解決,因為它是一個很好的圖形工具,而且是免費的。

如果您想嘗試,P4Merge 可以在所有主流平臺上執行,因此您應該能夠做到。我們將在 macOS 和 Linux 系統上執行的示例中使用路徑名;對於 Windows,您需要將/usr/local/bin更改為環境中的可執行路徑。

首先,從 Perforce 下載 P4Merge。接下來,您將設定外部包裝指令碼來執行您的命令。我們將使用 macOS 路徑作為可執行檔案;在其他系統中,它將是您的p4merge二進位制檔案安裝的位置。設定一個名為extMerge的合併包裝指令碼,該指令碼使用提供的所有引數呼叫您的二進位制檔案

$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/p4merge.app/Contents/MacOS/p4merge $*

差異包裝器會檢查是否提供了七個引數,並將其中兩個傳遞給您的合併指令碼。預設情況下,Git 會將以下引數傳遞給差異程式

path old-file old-hex old-mode new-file new-hex new-mode

因為您只想要old-filenew-file引數,所以您使用包裝指令碼傳遞您需要的引數。

$ cat /usr/local/bin/extDiff
#!/bin/sh
[ $# -eq 7 ] && /usr/local/bin/extMerge "$2" "$5"

您還需要確保這些工具是可執行的

$ sudo chmod +x /usr/local/bin/extMerge
$ sudo chmod +x /usr/local/bin/extDiff

現在您可以設定配置檔案以使用自定義合併解決和差異工具。這需要一些自定義設定:merge.tool用於告訴 Git 使用哪種策略,mergetool.<tool>.cmd用於指定如何執行命令,mergetool.<tool>.trustExitCode用於告訴 Git 該程式的退出程式碼是否表示成功的合併解決,以及diff.external用於告訴 Git 對差異執行哪個命令。因此,您可以執行四個配置命令

$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
  'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'
$ git config --global mergetool.extMerge.trustExitCode false
$ git config --global diff.external extDiff

或者您可以編輯您的~/.gitconfig檔案以新增這些行

[merge]
  tool = extMerge
[mergetool "extMerge"]
  cmd = extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
  trustExitCode = false
[diff]
  external = extDiff

設定完所有這些後,如果您執行差異命令,例如這樣

$ git diff 32d1776b1^ 32d1776b1

Git 不會直接在命令列中輸出差異結果,而是會啟動 P4Merge,看起來像這樣

P4Merge
圖 168. P4Merge

如果您嘗試合併兩個分支並隨後遇到合併衝突,您可以執行命令git mergetool;它會啟動 P4Merge,讓您透過該 GUI 工具解決衝突。

這種包裝器設定的好處是您可以輕鬆更改差異和合並工具。例如,要將您的extDiffextMerge工具更改為執行 KDiff3 工具,您只需編輯您的extMerge檔案

$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*

現在,Git 將使用 KDiff3 工具進行差異檢視和合並衝突解決。

Git 預設了許多其他合併解決工具,您無需設定 cmd 配置。要檢視它支援的工具列表,請嘗試此操作

$ git mergetool --tool-help
'git mergetool --tool=<tool>' may be set to one of the following:
        emerge
        gvimdiff
        gvimdiff2
        opendiff
        p4merge
        vimdiff
        vimdiff2

The following tools are valid, but not currently available:
        araxis
        bc3
        codecompare
        deltawalker
        diffmerge
        diffuse
        ecmerge
        kdiff3
        meld
        tkdiff
        tortoisemerge
        xxdiff

Some of the tools listed above only work in a windowed
environment. If run in a terminal-only session, they will fail.

如果您不感興趣使用 KDiff3 進行差異比較,而只想將其用於合併解決,並且 kdiff3 命令在您的路徑中,那麼您可以執行

$ git config --global merge.tool kdiff3

如果您執行此命令而不是設定extMergeextDiff檔案,Git 將使用 KDiff3 進行合併解決,並使用正常的 Git 差異工具進行差異比較。

格式和空白符

格式和空白符問題是許多開發人員在協作時,特別是跨平臺協作時,遇到的更令人沮喪和微妙的問題。補丁或其他協作工作很容易引入細微的空白符更改,因為編輯器會靜默地引入它們,而且如果您的檔案接觸過 Windows 系統,它們的行尾可能會被替換。Git 有一些配置選項可以幫助解決這些問題。

core.autocrlf

如果您在 Windows 上程式設計並與非 Windows 使用者(或反之)協作,您很可能會在某個時候遇到行尾問題。這是因為 Windows 在其檔案中使用回車符和換行符作為新行,而 macOS 和 Linux 系統只使用換行符。這是跨平臺工作一個微妙但令人難以置信的煩人事實;許多 Windows 上的編輯器會靜默地將現有的 LF 風格行尾替換為 CRLF,或者在使用者按下 Enter 鍵時插入兩個行尾字元。

Git 可以透過在您將檔案新增到索引時自動將 CRLF 行尾轉換為 LF,並在將程式碼檢出到您的檔案系統時反之來處理此問題。您可以使用core.autocrlf設定啟用此功能。如果您在 Windows 機器上,請將其設定為true——這會在您檢出程式碼時將 LF 行尾轉換為 CRLF

$ git config --global core.autocrlf true

如果您在使用 LF 行尾的 Linux 或 macOS 系統上,那麼您不希望 Git 在您檢出檔案時自動轉換它們;但是,如果一個帶有 CRLF 行尾的檔案意外引入,那麼您可能希望 Git 修復它。您可以透過將core.autocrlf設定為input來告訴 Git 在提交時將 CRLF 轉換為 LF,而不是反過來

$ git config --global core.autocrlf input

這種設定應該使您的 Windows 檢出中保留 CRLF 行尾,但在 macOS 和 Linux 系統以及倉庫中保留 LF 行尾。

如果您是一名 Windows 程式設計師,正在進行一個僅限 Windows 的專案,那麼您可以關閉此功能,透過將配置值設定為false,在倉庫中記錄回車符

$ git config --global core.autocrlf false

core.whitespace

Git 預設了檢測和修復一些空白符問題的功能。它可以查詢六個主要的空白符問題——其中三個預設啟用並可以關閉,另外三個預設停用但可以啟用。

預設啟用的三個是blank-at-eol,它查詢行尾的空格;blank-at-eof,它注意到檔案末尾的空白行;以及space-before-tab,它查詢行開頭製表符前的空格。

預設停用但可以啟用的三個是indent-with-non-tab,它查詢以空格而不是製表符開頭的行(由tabwidth選項控制);tab-in-indent,它監視行縮排部分的製表符;以及cr-at-eol,它告訴 Git 行尾的回車符是可以的。

您可以透過將core.whitespace設定為您想要啟用或停用的值(用逗號分隔)來告訴 Git 啟用哪些。您可以透過在其名稱前加上-來停用一個選項,或者透過將其完全排除在設定字串之外來使用預設值。例如,如果您想設定除space-before-tab之外的所有選項,您可以這樣做(其中trailing-space是同時涵蓋blank-at-eolblank-at-eof的簡寫)

$ git config --global core.whitespace \
    trailing-space,-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol

或者您只指定自定義部分

$ git config --global core.whitespace \
    -space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol

當您執行git diff命令時,Git 會檢測這些問題並嘗試將其著色,以便您可以在提交之前可能修復它們。當您使用git apply應用補丁時,它也會使用這些值來幫助您。當您應用補丁時,您可以要求 Git 警告您是否正在應用具有指定空白符問題的補丁

$ git apply --whitespace=warn <patch>

或者您可以讓 Git 在應用補丁之前嘗試自動修復問題

$ git apply --whitespace=fix <patch>

這些選項也適用於git rebase命令。如果您已提交空白符問題但尚未推送到上游,您可以執行git rebase --whitespace=fix,讓 Git 在重寫補丁時自動修復空白符問題。

伺服器配置

Git 伺服器端可用的配置選項不多,但有一些有趣的選項您可能需要注意。

receive.fsckObjects

Git 能夠確保在推送過程中接收到的每個物件仍然與其 SHA-1 校驗和匹配並指向有效物件。然而,它預設不這樣做;這是一個相當昂貴的操作,可能會減慢操作速度,尤其是在大型倉庫或推送時。如果您希望 Git 在每次推送時檢查物件一致性,可以透過將receive.fsckObjects設定為 true 來強制執行此操作

$ git config --system receive.fsckObjects true

現在,Git 將在接受每次推送之前檢查您的倉庫的完整性,以確保有缺陷(或惡意)的客戶端不會引入損壞的資料。

receive.denyNonFastForwards

如果您變基了已經推送的提交,然後嘗試再次推送,或者嘗試將提交推送到一個不包含遠端分支當前指向的提交的遠端分支,您將被拒絕。這通常是好的策略;但在變基的情況下,您可能會認為您知道自己在做什麼,並且可以使用-f標誌強制更新遠端分支。

要告訴 Git 拒絕強制推送,請設定receive.denyNonFastForwards

$ git config --system receive.denyNonFastForwards true

另一種方法是透過伺服器端接收鉤子,我們稍後會介紹。這種方法允許您做更復雜的事情,例如拒絕向特定使用者子集進行非快進式推送。

receive.denyDeletes

denyNonFastForwards策略的一種解決方法是使用者刪除分支,然後用新引用將其推送回去。為了避免這種情況,將receive.denyDeletes設定為 true

$ git config --system receive.denyDeletes true

這拒絕了任何分支或標籤的刪除——任何使用者都無法執行此操作。要刪除遠端分支,您必須手動從伺服器中刪除引用檔案。還有更多有趣的方法可以按使用者基於 ACL 執行此操作,您將在Git 強制策略示例中學習。

scroll-to-top