-
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 命令
10.8 Git 內部機制 - 環境變數
環境變數
Git 始終在 bash shell 中執行,並使用一些 shell 環境變數來確定其行為。瞭解這些變數以及如何使用它們來讓 Git 按你想要的方式工作,偶爾會很有用。這不是 Git 所關注的所有環境變數的詳盡列表,但我們會涵蓋最常用的。
全域性行為
Git 作為計算機程式的一些通用行為取決於環境變數。
GIT_EXEC_PATH 決定了 Git 在哪裡查詢其子程式(如 git-commit、git-diff 等)。你可以透過執行 git --exec-path 來檢查當前設定。
HOME 通常不被認為是可自定義的(太多其他東西依賴它),但 Git 會在這裡查詢全域性配置檔案。如果你想要一個完全可移植的 Git 安裝,包含全域性配置,可以在可移植 Git 的 shell profile 中覆蓋 HOME。
PREFIX 類似,但用於系統範圍的配置。Git 在 $PREFIX/etc/gitconfig 查詢此檔案。
GIT_CONFIG_NOSYSTEM,如果已設定,則停用系統範圍的配置檔案。如果你的系統配置干擾了你的命令,但你又無法更改或刪除它,這會很有用。
GIT_PAGER 控制用於在命令列中顯示多頁輸出的程式。如果未設定,則將使用 PAGER 作為備選。
GIT_EDITOR 是 Git 在使用者需要編輯文字(例如,提交訊息)時啟動的編輯器。如果未設定,則使用 EDITOR。
倉庫位置
Git 使用幾個環境變數來確定它如何與當前倉庫進行互動。
GIT_DIR 是 .git 資料夾的位置。如果未指定,Git 會向上遍歷目錄樹,直到到達 ~ 或 /,並在每一步查詢 .git 目錄。
GIT_CEILING_DIRECTORIES 控制查詢 .git 目錄的行為。如果你訪問載入速度慢的目錄(例如,磁帶驅動器上的目錄或慢速網路連線上的目錄),你可能希望 Git 提前停止搜尋,特別是當 Git 在生成 shell 提示符時被呼叫時。
GIT_WORK_TREE 是非裸倉庫工作目錄根目錄的位置。如果指定了 --git-dir 或 GIT_DIR,但未指定 --work-tree、GIT_WORK_TREE 或 core.worktree,則當前工作目錄將被視為工作樹的頂層。
GIT_INDEX_FILE 是索引檔案的路徑(僅限非裸倉庫)。
GIT_OBJECT_DIRECTORY 可用於指定通常位於 .git/objects 的目錄的位置。
GIT_ALTERNATE_OBJECT_DIRECTORIES 是一個由冒號分隔的列表(格式為 /dir/one:/dir/two:…),它告訴 Git 在 GIT_OBJECT_DIRECTORY 中找不到物件時在哪裡查詢。如果你碰巧有許多具有相同內容的大型專案,可以使用此功能避免儲存過多副本。
路徑名
“路徑名”(pathspec)是指你在 Git 中指定事物路徑的方式,包括使用萬用字元。這些用於 .gitignore 檔案,也可用於命令列(git add *.c)。
GIT_GLOB_PATHSPECS 和 GIT_NOGLOB_PATHSPECS 控制路徑名中萬用字元的預設行為。如果 GIT_GLOB_PATHSPECS 設定為 1,則萬用字元字元充當萬用字元(這是預設設定);如果 GIT_NOGLOB_PATHSPECS 設定為 1,則萬用字元字元只匹配自身,這意味著像 *.c 這樣的內容只會匹配名為“\*.c”的檔案,而不是任何以 .c 結尾的檔案。你可以透過在路徑名之前加上 :(glob) 或 :(literal) 來覆蓋此行為,例如 :(glob)\*.c。
GIT_LITERAL_PATHSPECS 停用以上兩種行為;所有萬用字元字元都無效,並且覆蓋字首也被停用。
GIT_ICASE_PATHSPECS 將所有路徑名設定為不區分大小寫。
提交
Git 提交物件的最終建立通常由 git-commit-tree 完成,它將這些環境變數作為其主要資訊來源,僅在這些環境變數不存在時才回退到配置值。
GIT_AUTHOR_NAME 是“author”欄位中的人類可讀姓名。
GIT_AUTHOR_EMAIL 是“author”欄位的電子郵件。
GIT_AUTHOR_DATE 是用於“author”欄位的時間戳。
GIT_COMMITTER_NAME 設定“committer”欄位的人類姓名。
GIT_COMMITTER_EMAIL 是“committer”欄位的電子郵件地址。
GIT_COMMITTER_DATE 用於“committer”欄位的時間戳。
EMAIL 是備用電子郵件地址,以防 user.email 配置值未設定。如果此變數未設定,Git 會回退到系統使用者名稱和主機名。
網路
Git 使用 curl 庫透過 HTTP 進行網路操作,因此 GIT_CURL_VERBOSE 會讓 Git 輸出該庫生成的所有訊息。這類似於在命令列上執行 curl -v。
GIT_SSL_NO_VERIFY 告訴 Git 不驗證 SSL 證書。如果你使用自簽名證書透過 HTTPS 提供 Git 倉庫,或者你正在設定 Git 伺服器但尚未安裝完整證書,這有時是必要的。
如果 HTTP 操作的資料速率低於每秒 GIT_HTTP_LOW_SPEED_LIMIT 位元組,並且持續時間超過 GIT_HTTP_LOW_SPEED_TIME 秒,Git 將中止該操作。這些值會覆蓋 http.lowSpeedLimit 和 http.lowSpeedTime 的配置值。
GIT_HTTP_USER_AGENT 設定 Git 在透過 HTTP 進行通訊時使用的使用者代理字串。預設值類似於 git#2.0.0。
差異和合並
GIT_DIFF_OPTS 有點名不副實。唯一有效的值是 -u<n> 或 --unified=<n>,它控制在 git diff 命令中顯示的上下文行數。
GIT_EXTERNAL_DIFF 用作 diff.external 配置值的覆蓋。如果設定了它,Git 將在呼叫 git diff 時呼叫此程式。
GIT_DIFF_PATH_COUNTER 和 GIT_DIFF_PATH_TOTAL 在由 GIT_EXTERNAL_DIFF 或 diff.external 指定的程式內部很有用。前者表示正在 diff 的檔案系列中的哪個檔案(從 1 開始),後者是批處理中的檔案總數。
GIT_MERGE_VERBOSITY 控制遞迴合併策略的輸出。允許的值如下:
-
0 不輸出任何內容,但可能輸出一條錯誤訊息。
-
1 只顯示衝突。
-
2 也顯示檔案更改。
-
3 顯示由於檔案未更改而被跳過的情況。
-
4 顯示處理的所有路徑。
-
5 及以上顯示詳細的除錯資訊。
預設值為 2。
除錯
想真正瞭解 Git 在做什麼嗎?Git 包含一套相當完整的跟蹤功能,你只需要啟用它們即可。這些變數的可能值如下:
-
“true”、“1”或“2” – 跟蹤類別將被寫入 stderr。
-
以
/開頭的絕對路徑 – 跟蹤輸出將被寫入該檔案。
GIT_TRACE 控制通用跟蹤,這些跟蹤不屬於任何特定類別。這包括別名的展開和委託給其他子程式。
$ GIT_TRACE=true git lga
20:12:49.877982 git.c:554 trace: exec: 'git-lga'
20:12:49.878369 run-command.c:341 trace: run_command: 'git-lga'
20:12:49.879529 git.c:282 trace: alias expansion: lga => 'log' '--graph' '--pretty=oneline' '--abbrev-commit' '--decorate' '--all'
20:12:49.879885 git.c:349 trace: built-in: git 'log' '--graph' '--pretty=oneline' '--abbrev-commit' '--decorate' '--all'
20:12:49.899217 run-command.c:341 trace: run_command: 'less'
20:12:49.899675 run-command.c:192 trace: exec: 'less'
GIT_TRACE_PACK_ACCESS 控制 packfile 訪問的跟蹤。第一個欄位是正在訪問的 packfile,第二個欄位是該檔案內的偏移量。
$ GIT_TRACE_PACK_ACCESS=true git status
20:10:12.081397 sha1_file.c:2088 .git/objects/pack/pack-c3fa...291e.pack 12
20:10:12.081886 sha1_file.c:2088 .git/objects/pack/pack-c3fa...291e.pack 34662
20:10:12.082115 sha1_file.c:2088 .git/objects/pack/pack-c3fa...291e.pack 35175
# […]
20:10:12.087398 sha1_file.c:2088 .git/objects/pack/pack-e80e...e3d2.pack 56914983
20:10:12.087419 sha1_file.c:2088 .git/objects/pack/pack-e80e...e3d2.pack 14303666
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
GIT_TRACE_PACKET 為網路操作啟用資料包級跟蹤。
$ GIT_TRACE_PACKET=true git ls-remote origin
20:15:14.867043 pkt-line.c:46 packet: git< # service=git-upload-pack
20:15:14.867071 pkt-line.c:46 packet: git< 0000
20:15:14.867079 pkt-line.c:46 packet: git< 97b8860c071898d9e162678ea1035a8ced2f8b1f HEAD\0multi_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed no-done symref=HEAD:refs/heads/master agent=git#2.0.4
20:15:14.867088 pkt-line.c:46 packet: git< 0f20ae29889d61f2e93ae00fd34f1cdb53285702 refs/heads/ab/add-interactive-show-diff-func-name
20:15:14.867094 pkt-line.c:46 packet: git< 36dc827bc9d17f80ed4f326de21247a5d1341fbc refs/heads/ah/doc-gitk-config
# […]
GIT_TRACE_PERFORMANCE 控制性能資料的日誌記錄。輸出顯示每次 git 呼叫所花費的時間。
$ GIT_TRACE_PERFORMANCE=true git gc
20:18:19.499676 trace.c:414 performance: 0.374835000 s: git command: 'git' 'pack-refs' '--all' '--prune'
20:18:19.845585 trace.c:414 performance: 0.343020000 s: git command: 'git' 'reflog' 'expire' '--all'
Counting objects: 170994, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (43413/43413), done.
Writing objects: 100% (170994/170994), done.
Total 170994 (delta 126176), reused 170524 (delta 125706)
20:18:23.567927 trace.c:414 performance: 3.715349000 s: git command: 'git' 'pack-objects' '--keep-true-parents' '--honor-pack-keep' '--non-empty' '--all' '--reflog' '--unpack-unreachable=2.weeks.ago' '--local' '--delta-base-offset' '.git/objects/pack/.tmp-49190-pack'
20:18:23.584728 trace.c:414 performance: 0.000910000 s: git command: 'git' 'prune-packed'
20:18:23.605218 trace.c:414 performance: 0.017972000 s: git command: 'git' 'update-server-info'
20:18:23.606342 trace.c:414 performance: 3.756312000 s: git command: 'git' 'repack' '-d' '-l' '-A' '--unpack-unreachable=2.weeks.ago'
Checking connectivity: 170994, done.
20:18:25.225424 trace.c:414 performance: 1.616423000 s: git command: 'git' 'prune' '--expire' '2.weeks.ago'
20:18:25.232403 trace.c:414 performance: 0.001051000 s: git command: 'git' 'rerere' 'gc'
20:18:25.233159 trace.c:414 performance: 6.112217000 s: git command: 'git' 'gc'
GIT_TRACE_SETUP 顯示 Git 關於它正在發現的倉庫和互動環境的資訊。
$ GIT_TRACE_SETUP=true git status
20:19:47.086765 trace.c:315 setup: git_dir: .git
20:19:47.087184 trace.c:316 setup: worktree: /Users/ben/src/git
20:19:47.087191 trace.c:317 setup: cwd: /Users/ben/src/git
20:19:47.087194 trace.c:318 setup: prefix: (null)
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
雜項
GIT_SSH,如果指定,則是在 Git 嘗試連線到 SSH 主機時呼叫而不是 ssh 的程式。它的呼叫方式是 $GIT_SSH [username@]host [-p <port>] <command>。請注意,這不是自定義 ssh 呼叫方式的最簡單方法;它不支援額外的命令列引數。要支援額外的命令列引數,你可以使用 GIT_SSH_COMMAND,編寫一個包裝指令碼並將 GIT_SSH 指向它,或者使用 ~/.ssh/config 檔案。
GIT_SSH_COMMAND 設定 Git 嘗試連線到 SSH 主機時使用的 SSH 命令。該命令由 shell 解析,並且可以使用額外的命令列引數與 ssh 一起使用,例如 GIT_SSH_COMMAND="ssh -i ~/.ssh/my_key" git clone git@example.com:my/repo。
GIT_ASKPASS 是 core.askpass 配置值的覆蓋。這是 Git 需要向用戶詢問憑據時呼叫的程式,該程式可以接受文字提示作為命令列引數,並應在 stdout 上返回答案(有關此子系統的更多資訊,請參閱 憑據儲存)。
GIT_NAMESPACE 控制對名稱空間 ref 的訪問,等同於 --namespace 標誌。這在伺服器端很有用,你可能希望在一個倉庫中儲存單個倉庫的多個分支,只保留 ref 分開。
GIT_FLUSH 可用於強制 Git 在增量寫入 stdout 時使用非緩衝 I/O。值為 1 會使 Git 更頻繁地重新整理,值為 0 會使所有輸出都被緩衝。預設值(如果未設定此變數)是根據活動和輸出模式選擇合適的緩衝方案。
GIT_REFLOG_ACTION 允許你指定寫入 reflog 的描述性文字。示例如下:
$ GIT_REFLOG_ACTION="my action" git commit --allow-empty -m 'My message'
[master 9e3d55a] My message
$ git reflog -1
9e3d55a HEAD@{0}: my action: My message