設定與組態
取得與建立專案
基本快照
分支與合併
分享與更新專案
檢查與比較
修補
除錯
電子郵件
外部系統
伺服器管理
指南
- gitattributes
- 命令列介面規範
- Git 日常使用
- 常見問題 (FAQ)
- 詞彙表
- 掛鉤 (Hooks)
- gitignore
- gitmodules
- 修訂版本 (Revisions)
- 子模組
- 教學
- 工作流程
- 所有指南...
管理
底層命令 (Plumbing Commands)
- 2.54.0 → 2.55.0 無變更
-
2.53.0
2026-02-02
- 2.46.1 → 2.52.0 無變更
-
2.46.0
2024-07-29
- 2.34.1 → 2.45.4 無變更
-
2.34.0
2021-11-15
- 2.29.1 → 2.33.8 無變更
-
2.29.0
2020-10-19
- 2.27.1 → 2.28.1 無變更
-
2.27.0
2020-06-01
描述
本 FAQ 中的範例假設使用標準 POSIX shell(例如 bash 或 dash),以及一位名為 A U Thor 的使用者,其在託管服務商 git.example.org 上擁有帳號 author。
組態設定
- 我應該在
user.name中填入什麼? -
您應該填入您的個人姓名,通常使用名與姓的格式。例如,目前的 Git 維護者使用的是 "Junio C Hamano"。這將作為姓名部分儲存在您所做的每一次提交中。
此設定對遠端服務的驗證沒有任何影響;若要設定驗證,請參閱 git-config[1] 中的
credential.username。
http.postBuffer到底有什麼作用?-
此選項會改變 Git 透過 HTTP 或 HTTPS 將資料推送到遠端時所使用的緩衝區大小。如果資料大於此大小,負責處理 Git HTTP 支援的 libcurl 將使用區塊傳輸編碼(chunked transfer encoding),因為推送資料的總大小無法提前得知。
除非您知道遠端伺服器或中間的代理伺服器不支援 HTTP/1.1(該版本引入了區塊傳輸編碼)或者已知處理區塊資料時會出錯,否則保留此值的預設大小即可。這通常被(錯誤地)視為解決一般推送問題的方法,但由於幾乎每個伺服器和代理伺服器至少都支援 HTTP/1.1,提高此值通常無法解決大多數的推送問題。一個無法正確支援 HTTP/1.1 和區塊傳輸編碼的伺服器或代理伺服器在現今的網際網路上並無太大用處,因為它會導致大量流量中斷。
請注意,增加此值會增加 Git 透過 HTTP 或 HTTPS 進行相關推送時所使用的記憶體,因為無論是否用完,整個緩衝區都會被配置。因此,除非您確信需要不同的值,否則最好將其保留為預設值。
- 如何設定不同的編輯器?
-
如果您尚未為 Git 指定特定的編輯器,它預設會使用您透過
VISUAL或EDITOR環境變數設定的編輯器;如果兩者皆未指定,則使用系統預設值(通常是vi)。由於有些人覺得vi很難使用或偏好不同的編輯器,因此可能需要更改所使用的編輯器。如果您想為大多數需要編輯器的程式設定一個通用編輯器,您可以編輯您的 shell 設定檔(例如
~/.bashrc或~/.zshenv),加入一行將EDITOR或VISUAL環境變數設定為合適的值。例如,如果您偏好使用nano編輯器,則可以寫入以下內容:export VISUAL=nano
如果您想為 Git 設定特定的編輯器,可以設定
core.editor設定值或GIT_EDITOR環境變數。您可以參閱 git-var[1] 以了解這些選項的查詢順序。請注意,在所有情況下,編輯器值都會傳遞給 shell,因此任何包含空格的參數都應適當地加上引號。此外,如果您的編輯器在呼叫時通常會與終端機分離,您應該指定一個參數使其不會發生這種情況,否則 Git 將無法看到任何變更。在 Windows 上解決這兩個問題的設定範例是 "C:\Program Files\Vim\gvim.exe" --nofork,它為帶有空格的檔名加上了引號,並指定了
--nofork選項以避免將程序放到背景執行。
認證憑證
- 當透過 HTTP 推送時,如何指定我的認證憑證?
-
最簡單的方法是透過
credential.helper設定使用憑證協助程式。大多數系統提供與系統憑證管理員整合的標準選擇。例如,Git for Windows 提供wincred憑證管理員,macOS 有osxkeychain憑證管理員,而具有標準桌面環境的 Unix 系統可以使用libsecret憑證管理員。所有這些都會將憑證儲存在加密儲存庫中,以保護您的密碼或權杖(token)安全。此外,您可以使用將憑證儲存在家目錄檔案中的
store憑證管理員,或是不會永久儲存您的憑證,但可避免在一段時間內重複提示輸入憑證的cache憑證管理員。您也可以在收到提示時直接輸入密碼。雖然可以將密碼(必須經過百分比編碼)放在 URL 中,但這並不安全,且可能導致憑證意外洩露,因此不建議這樣做。
- 如何在使用 HTTP 時針對同一個託管服務商使用多個帳號?
-
區分這些帳號最簡單的方法通常是在 URL 中使用使用者名稱。例如,如果您在
git.example.org上擁有author和committer帳號,您可以使用 URL https://author@git.example.org/org1/project1.git 和 https://committer@git.example.org/org2/project2.git。這樣一來,當您使用憑證協助程式時,它會自動嘗試尋找您帳號的正確憑證。如果您已經設定好遠端,可以使用類似gitremoteset-urloriginhttps://author@git.example.org/org1/project1.git的指令來更改 URL(詳情請參閱 git-remote[1])。
- 如何在使用 SSH 時針對同一個託管服務商使用多個帳號?
-
對於大多數支援 SSH 的託管服務商,單一金鑰對唯一識別一個使用者。因此,要使用多個帳號,必須為每個帳號建立一個金鑰對。如果您使用的是較現代的 OpenSSH 版本,可以使用類似
ssh-keygen-ted25519-f~/.ssh/id_committer的指令建立新的金鑰對。然後,您可以將公開金鑰(此例中為~/.ssh/id_committer.pub;注意.pub副檔名)註冊到託管服務商。大多數託管服務商使用單一 SSH 帳號進行推送;也就是說,所有使用者都推送到
git帳號(例如git@git.example.org)。如果是這種情況,您可以在 SSH 中設定多個別名,以明確指定要使用哪個金鑰對。例如,您可以在~/.ssh/config中寫入以下內容,並替換為正確的私密金鑰檔案:# This is the account for author on git.example.org. Host example_author HostName git.example.org User git # This is the key pair registered for author with git.example.org. IdentityFile ~/.ssh/id_author IdentitiesOnly yes # This is the account for committer on git.example.org. Host example_committer HostName git.example.org User git # This is the key pair registered for committer with git.example.org. IdentityFile ~/.ssh/id_committer IdentitiesOnly yes
然後,您可以調整您的推送 URL,使用
git@example_author或git@example_committer,而不是git@example.org(例如gitremoteset-urlgit@example_author:org1/project1.git)。
傳輸
- 如何跨系統同步工作目錄(working tree)?
-
首先,請決定您是否真的需要這樣做。當您使用典型的
gitpush和gitfetch指令推送或提取工作時,Git 的運作效果最好,且它並非設計用於跨系統共享工作目錄。這具有潛在風險,在某些情況下可能導致儲存庫毀損或資料遺失。通常,這樣做會導致
gitstatus需要重新讀取工作目錄中的每一個檔案。此外,Git 的安全模型不允許在不受信任的使用者之間共享工作目錄,因此只有在所有機器上都由單一使用者使用時,同步工作目錄才是安全的。切勿使用雲端同步服務來同步 Git 儲存庫的任何部分,這一點非常重要,因為這可能導致儲存庫毀損,例如遺失物件、檔案被變更或新增、參考(refs)損毀,以及其他各種問題。這些服務傾向於持續地逐個檔案同步,並不理解 Git 儲存庫的結構。如果它們在儲存庫更新過程中進行同步,情況會特別嚴重,因為這極有可能導致更新不完整或部分更新,從而造成資料遺失。
可能發生的一種毀損範例是參考狀態發生衝突,導致雙方在同一個分支上擁有不同的提交,而另一方卻沒有。這可能導致重要物件變成未被引用,並可能被
gitgc修剪,進而導致資料遺失。因此,最好使用正常的推送和提取機制,將您的工作推送到另一個系統或中央伺服器。在 Git 2.51 中,Git 增加了匯入和匯出暫存(stashes)的功能,因此可以透過
gitstash將工作目錄狀態暫存,然後使用gitstashexport--to-refrefs/heads/stashes(假設您想匯出到stashes分支)匯出所有暫存,或者透過在指令末尾添加數字來選擇特定的暫存。您也可以在最初暫存資料時使用--include-untracked參數來包含未追蹤的檔案,但如果其中包含敏感資訊,請務必小心。然後,您可以推送
stashes分支(或您匯出到的任何分支),將其提取到本機系統(例如使用gitfetchorigin+stashes:stashes),並在另一個系統上使用gitstashimportstashes(同樣,根據需要更改名稱)匯入這些暫存。應用變更到工作目錄可以使用gitstashpop或gitstashapply完成。這是最穩健且最能避免意外問題的方法。話雖如此,在某些情況下人們仍然偏好跨系統共享工作目錄。如果您這樣做,建議的方法是在儲存庫根目錄使用
rsync-a--delete-after(最好配合加密連線,例如ssh)。執行此操作時,您應確保以下幾點:-
如果您有額外的工作樹(worktrees)或獨立的 Git 目錄,它們必須與主工作目錄和儲存庫同時同步。
-
您能接受目標目錄成為來源目錄的精確副本,刪除已存在於該處的所有資料。
-
在傳輸期間,儲存庫(包括所有工作樹和 Git 目錄)必須處於靜止狀態(即不進行任何類型的操作,包括像
gitgc這樣的背景操作,以及由您的編輯器所引發的操作)。請注意,即使有這些建議,以這種方式同步工作目錄仍有風險,因為它繞過了 Git 對儲存庫正常的完整性檢查,因此建議進行備份。同步後,您可能還希望執行
gitfsck以驗證目標系統上資料的完整性。
-
常見問題
- 如何忽略對已追蹤檔案的變更?
-
Git 沒有提供執行此操作的方法。原因是如果 Git 需要覆寫此檔案(例如在 checkout 期間),它不知道對檔案的變更是否珍貴且應該保留,還是不重要且可以安全銷毀。因此,它必須採取安全的路徑,始終保留它們。
使用
gitupdate-index的某些功能(即 assume-unchanged 和 skip-worktree 位元)可能會很誘人,但這些功能在此目的下無法正常運作,且不應以這種方式使用。如果您的目標是修改設定檔,通常將一個模板或預設值檔案檢入儲存庫會很有幫助,然後將其複製並進行相應修改。這個經過修改的第二個檔案通常會被忽略,以防止意外提交它。
- 我要求 Git 忽略各種檔案,但它們仍然被追蹤
-
gitignore檔案可確保某些未被 Git 追蹤的檔案保持不被追蹤。然而,有時特定的檔案可能在添加到.gitignore之前就已經被追蹤,因此它們仍然保持被追蹤狀態。若要取消追蹤並忽略檔案/模式,請使用 git rm --cached <file/pattern>,並將與 <file> 相符的模式添加到.gitignore中。詳情請參閱 gitignore[5]。
- 我如何知道我該執行 fetch 還是 pull?
-
fetch 會儲存遠端儲存庫最新變更的副本,而不修改工作目錄或目前分支。然後,您可以隨時檢查、合併、在之上進行重定基底,或忽略上游的變更。pull 則包含一個 fetch,隨後立即進行合併或重定基底。請參閱 git-pull[1]。
- 我可以在 Git 中使用代理伺服器嗎?
-
可以,Git 支援使用代理伺服器。Git 會尊重 Unix 上常用的標準
http_proxy、https_proxy和no_proxy環境變數,也可以透過http.proxy和類似選項為 HTTPS 進行設定(參閱 git-config[1])。http.proxy及相關選項可依 URL 模式進行客製化。此外,理論上 Git 可以與網路上的透明代理伺服器正常運作。對於 SSH,Git 可以透過 OpenSSH 的
ProxyCommand支援代理。常用的工具包括netcat和socat。然而,必須設定它們在標準輸入中看到 EOF 時不會退出,這通常意味著netcat需要-q,而socat需要類似-t10的逾時設定。這是必須的,因為 Git SSH 伺服器得知不再有更多請求的方式是標準輸入上的 EOF,但當這種情況發生時,伺服器可能尚未處理完最後一個請求,因此在那一點斷開連線會中斷該請求。在
~/.ssh/config中使用 HTTP 代理的設定範例可能如下所示:Host git.example.org User git ProxyCommand socat -t 10 - PROXY:proxy.example.org:%h:%p,proxyport=8080請注意,在所有情況下,為了使 Git 正常運作,代理伺服器必須是完全透明的。代理伺服器不能以任何方式修改、篡改或緩衝連線,否則 Git 幾乎肯定會無法運作。請注意,許多代理伺服器,包括許多 TLS 中間盒(middleboxes)、除了 Windows Defender 和 Windows 防火牆之外的 Windows 防毒軟體與防火牆程式,以及過濾型代理伺服器,都無法達到此標準,導致 Git 運作中斷。由於有許多關於問題的報告及其不良的安全歷史,我們建議不要使用這些類別的軟體和裝置。
合併與重定基底
- 在對長期存在的分支使用壓縮合併(squash merge)時,會發生什麼類型的問題?
-
總體而言,當多次使用壓縮合併來合併兩個分支時,可能會發生各種問題。這些可能包括在
gitlog輸出、GUI 中,或當使用 ... 符號來表示範圍時,看到額外的提交,以及可能需要反覆重新解決衝突。當 Git 在兩個分支之間進行正常合併時,它考慮三個精確點:兩個分支和一個稱為「合併基準」(merge base)的第三個提交,這通常是提交的共同祖先。合併的結果是合併基準與每個分支頂端(head)之間變更的總和。當您使用一般的合併提交來合併兩個分支時,這會產生一個新的提交,當它們再次合併時,該提交最終會成為合併基準,因為現在有一個新的共同祖先。Git 不必考慮合併基準之前發生的變更,因此您不必重新解決之前已經解決過的任何衝突。
當您執行壓縮合併時,不會建立合併提交;相反,一側的變更作為一般的提交應用到另一側。這意味著這些分支的合併基準不會改變,因此當 Git 下次執行合併時,它會考慮上次考慮的所有變更加上新的變更。這意味著可能需要重新解決任何衝突。同樣地,任何在
gitdiff、gitlog中使用 ... 符號的內容,或 GUI 都將顯示自原始合併基準以來的所有變更。因此,如果您想反覆合併兩個長期存在的分支,最好始終使用一般的合併提交。
- 如果我在兩個分支上都進行了變更,但在其中一個分支上復原了它,為什麼合併這些分支時會包含該變更?
-
預設情況下,當 Git 執行合併時,它會使用一種稱為
ort的策略,這是一種精巧的三方合併(three-way merge)。在這種情況下,當 Git 執行合併時,它考慮三個精確點:兩個頂端和一個稱為「合併基準」的第三點,這通常是這些提交的共同祖先。Git 完全不會考慮在這些分支上發生的歷史紀錄或個別提交。因此,如果雙方都有變更,且其中一方復原了該變更,結果就是包含該變更。這是因為程式碼在一側發生了變更,而在另一側沒有淨變更,在這種情況下,Git 會採用該變更。
如果這對您造成問題,您可以改為進行重定基底,將帶有復原的分支重定基底到另一個分支上。在這種情況下,重定基底將會復原該變更,因為重定基底會應用每個個別的提交,包括復原提交。請注意,重定基底會改寫歷史紀錄,因此除非您確定自己能夠接受,否則應避免重定基底已發布的分支。詳情請參閱 git-rebase[1] 中的 NOTES 章節。
勾子(Hooks)
- 我該如何使用勾子來防止使用者進行某些變更?
-
進行這些變更唯一安全的地方是在遠端儲存庫(即 Git 伺服器)上,通常是在
pre-receive勾子或持續整合(CI)系統中。這些位置才能有效地執行政策。嘗試使用
pre-commit勾子(或者對於提交訊息,使用commit-msg勾子)來檢查這些事項是很常見的做法,如果您是獨立開發者並希望工具協助您,這非常好。然而,在開發人員的機器上使用勾子作為政策控制並不有效,因為使用者可以使用--no-verify繞過這些勾子而不被察覺(除此之外還有各種其他方法)。Git 假設使用者可以控制他們本機的儲存庫,且不會試圖阻止這一點或向使用者打小報告。此外,一些進階使用者發現
pre-commit勾子會阻礙使用臨時提交來暫存進度或建立修正提交的工作流程,因此無論如何,將這類檢查推送到伺服器會更好。
跨平台問題
- 我正在使用 Windows,但我的文字檔案被偵測為二進位檔。
-
當您將文字檔案儲存為 UTF-8 時,Git 的運作效果最好。Windows 上的許多程式支援 UTF-8,但有些不支援,僅使用小端序 UTF-16 格式,Git 會將其偵測為二進位檔。如果您無法在程式中使用 UTF-8,您可以指定工作目錄編碼,指示您的檔案應以哪種編碼進行檢出(checkout),同時在儲存庫中仍將這些檔案儲存為 UTF-8。這使得像 git-diff[1] 這樣的工具能按預期運作,同時仍允許您的工具正常工作。
為此,您可以指定一個具有
working-tree-encoding屬性的 gitattributes[5] 模式。例如,以下模式設定所有 C 檔案使用 UTF-16LE-BOM,這是在 Windows 上常見的編碼:*.c working-tree-encoding=UTF-16LE-BOM
您需要執行
gitadd--renormalize才能使其生效。請注意,如果您是在跨平台使用的專案上進行這些變更,您可能希望在每位使用者的設定檔中或$GIT_DIR/info/attributes中的檔案中進行,因為在儲存庫中的.gitattributes檔案中進行設定,將適用於儲存庫的所有使用者。請參閱下一個項目以了解關於標準化換行符號的資訊,並參閱 gitattributes[5] 以取得關於屬性檔案的更多資訊。
- 我正在使用 Windows,git diff 顯示我的檔案結尾有
^M。 -
預設情況下,Git 預期檔案儲存為 Unix 換行符號。因此,作為 Windows 換行符號一部分的歸位字元(carriage return,
^M)會被顯示出來,因為它被視為行尾空白。Git 預設僅在新行上顯示行尾空白,而不是在已存在的行上。您可以將檔案以 Unix 換行符號儲存在儲存庫中,並自動將它們轉換為您平台的換行符號。若要這樣做,請將設定選項
core.eol設定為native,並參閱關於推薦儲存設定的問題,了解如何將檔案設定為文字或二進位格式的資訊。如果您不希望從換行符號中刪除歸位字元,也可以透過
core.whitespace設定來控制此行為。
- 為什麼我有一個檔案總是顯示為已修改?
-
在內部,Git 始終將檔名儲存為位元組序列,且不執行任何編碼或大小寫折疊。然而,Windows 和 macOS 預設都會對檔名執行大小寫折疊。因此,最終可能會出現多個檔案或目錄,其名稱僅在大小寫上有所不同。Git 可以很好地處理這種情況,但檔案系統只能儲存其中一個檔案,因此當 Git 讀取另一個檔案以查看其內容時,它看起來就像是被修改了。
最好刪除其中一個檔案,只保留一個檔案。您可以在其他方面乾淨的工作目錄中使用類似以下的指令(假設有兩個檔案
AFile.txt和afile.txt):$ git rm --cached AFile.txt $ git commit -m 'Remove files conflicting in case' $ git checkout .
這避免了觸碰磁碟,但刪除了額外的檔案。您的專案可能偏好採用命名慣例,例如全小寫名稱,以避免此問題再次發生;可以使用
pre-receive勾子或作為持續整合(CI)系統的一部分來檢查此慣例。如果您的系統正在使用 smudge 或 clean 篩選器,但檔案先前在未執行 smudge 或 clean 篩選器的情況下被提交,那麼在任何平台上都可能出現永久被修改的檔案。若要修復此問題,請在其他方面乾淨的工作目錄中執行以下指令:
$ git add --renormalize .
- 在 Git 中儲存檔案的推薦方式是什麼?
-
雖然 Git 可以儲存和處理任何類型的任何檔案,但有些設定效果比其他設定更好。總體而言,我們建議文字檔案以 UTF-8 儲存且不帶位元組順序標記(BOM),並使用 LF(Unix 風格)換行符號。我們也建議在提交訊息中使用 UTF-8(同樣不帶 BOM)。這些設定在跨平台以及與像
gitdiff和gitmerge這樣的工具配合時效果最好。此外,如果您在文字格式與非文字格式之間有選擇餘地,我們建議以文字格式儲存檔案,並在必要時將其轉換為其他格式。例如,一行一筆紀錄的文字格式 SQL 傾印(dump)在進行差異比較與合併時,效果會比實際的資料庫檔案好得多。同樣地,Markdown 和 AsciiDoc 等文字格式在處理時會比 Microsoft Word 和 PDF 等二進位格式更好。
同樣地,通常不建議在儲存庫中儲存二進位依賴項(例如共享函式庫或 JAR 檔案)或建置產物。依賴項和建置產物最好儲存在構件或套件伺服器上,儲存庫中僅儲存參照、URL 和雜湊值。
我們也建議設定一個 gitattributes[5] 檔案,明確標記哪些檔案是文字檔,哪些是二進位檔。如果您希望 Git 進行推測,可以設定屬性
text=auto。對於文字檔案,Git 通常會確保在儲存庫中使用 LF 換行符號。
core.autocrlf和core.eol設定變數會指定在檢出任何文字檔案時應遵循的換行符號慣例。您也可以使用eol屬性(例如eol=crlf)來覆寫哪些檔案應採用哪種換行符號處理方式。例如,一般來說 shell 檔案必須使用 LF 換行符號,而 batch 檔案必須使用 CRLF 換行符號,因此以下設定在某些專案中可能是合適的:
# By default, guess. * text=auto # Mark all C files as text. *.c text # Ensure all shell files have LF endings and all batch files have CRLF # endings in the working tree and both have LF in the repo. *.sh text eol=lf *.bat text eol=crlf # Mark all JPEG files as binary. *.jpg binary
這些設定有助於工具為修補程式(patches)等輸出選擇正確的格式,並使檔案以適合該平台的換行符號檢出。
GIT
git[1] 套件的一部分