-
1. 起步
-
2. Git 基礎
-
3. Git 分支
-
4. 伺服器上的 Git
- 4.1 協議
- 4.2 在伺服器上部署 Git
- 4.3 生成 SSH 公鑰
- 4.4 架設伺服器
- 4.5 Git Daemon
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方託管服務
- 4.10 小結
-
5. 分散式 Git
-
A1. 附錄 A: Git 在其他環境
- A1.1 圖形介面
- A1.2 Visual Studio 中的 Git
- A1.3 Visual Studio Code 中的 Git
- A1.4 IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine 中的 Git
- A1.5 Sublime Text 中的 Git
- A1.6 Bash 中的 Git
- A1.7 Zsh 中的 Git
- A1.8 PowerShell 中的 Git
- A1.9 小結
-
A2. 附錄 B: 在應用程式中嵌入 Git
-
A3. 附錄 C: Git 命令
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 識別的配置選項分為兩類:客戶端和伺服器端。大部分選項都是客戶端的——配置你的個人工作偏好。支援許多、許多配置選項,但其中很大一部分僅在某些邊緣情況下有用;我們只介紹最常用和最有用的選項。如果你想檢視你的 Git 版本識別的所有選項列表,你可以執行
$ man git-config
此命令會詳細列出所有可用選項。你也可以在 https://git-scm.tw/docs/git-config 找到這些參考資料。
|
注意
|
對於高階用例,你可能想在上述文件中查詢“條件包含”。 |
core.editor
預設情況下,Git 會使用你透過 shell 環境變數 VISUAL 或 EDITOR 設定的預設文字編輯器,否則會回退到 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 輸出),在此之後新增更多詳細資訊,並在存在問題或 Bug 跟蹤器門票號時引用它們。
要告訴 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 在分頁輸出(如 log 和 diff)時使用的分頁器。你可以將其設定為 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 提供了特定命令的著色設定。每個設定都可以是 true、false 或 always。
color.branch color.diff color.interactive color.status
此外,這些每個都有子設定,你可以用來為輸出的特定部分設定特定顏色,如果你想覆蓋每種顏色。例如,要將你的 diff 輸出中的元資訊設定為藍色前景、黑色背景和粗體文字,你可以執行:
$ git config --global color.diff.meta "blue black bold"
你可以將顏色設定為以下任何值:normal、black、red、green、yellow、blue、magenta、cyan 或 white。如果你想要像上例中的粗體這樣的屬性,你可以選擇 bold、dim、ul(下劃線)、blink 和 reverse(交換前景和背景)。
外部合併和 diff 工具
儘管 Git 有一個內部的 diff 實現,這也是我們在本書中一直展示的,但你可以設定一個外部工具來代替。你還可以設定一個圖形化的合併衝突解決工具,而不是手動解決衝突。我們將演示設定 Perforce Visual Merge Tool (P4Merge) 來處理你的 diff 和合並衝突,因為它是一個不錯的圖形化工具而且是免費的。
如果你想嘗試一下,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 $*
diff 包裝器會檢查是否提供了七個引數,並將其中兩個傳遞給你的合併指令碼。預設情況下,Git 會將以下引數傳遞給 diff 程式:
path old-file old-hex old-mode new-file new-hex new-mode
因為你只需要 old-file 和 new-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
現在你可以設定你的配置檔案來使用自定義的合併解決和 diff 工具。這需要一系列自定義設定:merge.tool 來告訴 Git 使用哪種策略,mergetool.<tool>.cmd 來指定如何執行命令,mergetool.<tool>.trustExitCode 來告訴 Git 該程式的退出程式碼是否表示合併解決成功,以及 diff.external 來告訴 Git 執行哪個命令進行 diff。所以,你可以執行四個配置命令:
$ 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
完成所有這些設定後,如果你執行 diff 命令,例如:
$ git diff 32d1776b1^ 32d1776b1
Git 將會啟動 P4Merge,而不是在命令列中顯示 diff 輸出,其介面看起來像這樣:
如果你嘗試合併兩個分支並隨後遇到合併衝突,你可以執行 git mergetool 命令;它會啟動 P4Merge,讓你透過該 GUI 工具來解決衝突。
這個包裝器設定的好處是你可以輕鬆地更改你的 diff 和合並工具。例如,要將你的 extDiff 和 extMerge 工具更改為執行 KDiff3 工具,你只需要編輯你的 extMerge 檔案:
$ cat /usr/local/bin/extMerge
#!/bin/sh
/Applications/kdiff3.app/Contents/MacOS/kdiff3 $*
現在,Git 將使用 KDiff3 工具進行 diff 檢視和合並衝突解決。
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 進行 diff,而只想將其用於合併解決,並且 kdiff3 命令在你的 PATH 中,那麼你可以執行:
$ git config --global merge.tool kdiff3
如果你執行此命令而不是設定 extMerge 和 extDiff 檔案,Git 將使用 KDiff3 進行合併解決,並使用普通的 Git diff 工具進行 diff。
格式和空格
格式和空格問題是許多開發人員在協作(尤其是跨平臺協作)時遇到的更令人沮喪和微妙的問題。由於編輯器會默默地引入它們,並且如果你的檔案觸碰到 Windows 系統,它們的行尾可能會被替換,因此補丁或其他協作工作很容易引入細微的空格更改。Git 有一些配置選項可以幫助解決這些問題。
core.autocrlf
如果你在 Windows 上程式設計並與非 Windows 使用者(反之亦然)合作,你可能會在某個時候遇到行尾問題。這是因為 Windows 在其檔案中使用回車符和換行符來表示新行,而 macOS 和 Linux 系統僅使用換行符。這是一個微妙但極其惱人的跨平臺工作事實;許多 Windows 上的編輯器會默默地將現有的 LF 風格行尾替換為 CRLF,或者在使用者按下回車鍵時插入兩個行尾字元。
Git 可以透過在將檔案新增到索引時自動轉換 CRLF 行尾為 LF,反之亦然,在將程式碼檢出到你的檔案系統時,來處理這個問題。你可以使用 core.autocrlf 設定來啟用此功能。如果你在 Windows 機器上,將其設定為 true——這會在你檢出程式碼時將 LF 結尾轉換為 CRLF。
$ git config --global core.autocrlf true
如果你在 macOS 或 Linux 系統上,使用的是 LF 行尾,那麼你不希望 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-eol 和 blank-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 會在你執行 git diff 命令時檢測這些問題,並嘗試為它們著色,以便你可能在提交之前修復它們。它還將使用這些值來幫助你應用補丁,例如使用 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
如果你 rebase 了已經推送過的提交然後再次嘗試推送,或者以其他方式嘗試將一個提交推送到遠端分支,而該遠端分支不包含當前指向的提交,你將被拒絕。這通常是一個好的策略;但在 rebase 的情況下,你可能認為你知道你在做什麼,並且可以使用 -f 標誌來強制更新遠端分支。
要告訴 Git 拒絕強制推送,請將 receive.denyNonFastForwards 設定為 true:
$ git config --system receive.denyNonFastForwards true
另一種方法是透過伺服器端接收鉤子,我們將在稍後介紹。該方法允許你做更復雜的事情,例如拒絕特定使用者進行非快進式推送。
receive.denyDeletes
denyNonFastForwards 策略的一個變通方法是讓使用者刪除分支然後重新推送。為了避免這種情況,將 receive.denyDeletes 設定為 true:
$ git config --system receive.denyDeletes true
這將拒絕刪除任何分支或標籤——沒有使用者可以這樣做。要刪除遠端分支,你必須手動從伺服器中刪除 ref 檔案。正如你將在 Git 強制策略示例 中學到的那樣,還有更有趣的基於使用者的方法可以透過 ACL 來實現。