設定和配置
獲取和建立專案
基本快照
分支與合併
共享和更新專案
檢查和比較
打補丁
除錯
電子郵件
外部系統
伺服器管理
指南
管理
底層命令
- 2.46.1 → 2.50.1 無更改
-
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
描述
本常見問題解答中的示例假定使用標準的 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 將使用分塊傳輸編碼,因為它無法預先知道推送資料的大小。
除非您知道遠端伺服器或中間代理不支援 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
憑據管理器。所有這些都將憑據儲存在加密儲存中,以確保您的密碼或令牌安全。此外,您可以使用
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。這樣,當您使用憑據助手時,它將自動嘗試查詢您的帳戶的正確憑據。如果您已經設定了遠端倉庫,您可以使用類似git
remote
set-url
origin
https://author@git.example.org/org1/project1.git
的命令更改 URL(有關詳細資訊,請參閱 git-remote[1])。
- 如何使用同一個託管服務提供商的多個 SSH 帳戶?
-
對於大多數支援 SSH 的託管服務提供商,單個金鑰對唯一標識一個使用者。因此,要使用多個帳戶,需要為每個帳戶建立金鑰對。如果您使用的是相當現代的 OpenSSH 版本,您可以使用類似
ssh-keygen
-t
ed25519
-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
(例如,git
remote
set-url
git@example_author:org1/project1.git
)。
傳輸
- 如何在系統間同步工作區?
-
首先,決定您是否要這樣做。Git 在您使用典型的
git
push
和git
fetch
命令推送或拉取您的工作時效果最佳,並且不設計用於在系統間共享工作區。這具有潛在風險,在某些情況下可能導致倉庫損壞或資料丟失。通常,這樣做會導致
git
status
需要重新讀取工作區中的每個檔案。此外,Git 的安全模型不允許在不信任的使用者之間共享工作區,因此只有當工作區僅由一個使用者在所有機器上使用時,同步工作區才是安全的。重要的是不要使用雲同步服務來同步 Git 倉庫的任何部分,因為這可能導致損壞,例如物件丟失、檔案更改或新增、引用損壞以及各種其他問題。這些服務傾向於持續按檔案同步,並且不理解 Git 倉庫的結構。如果在倉庫更新過程中同步,情況會特別糟糕,因為這很可能導致不完整或部分更新,從而導致資料丟失。
可能發生的損壞示例是關於引用的狀態衝突,導致雙方在某個分支上都擁有對方沒有的不同提交。這可能導致重要物件變得不被引用,並可能被
git
gc
清理,從而導致資料丟失。因此,最好使用正常的推送和拉取機制,將您的工作推送到另一個系統或中央伺服器。然而,這並不總是能保留重要資料,例如暫存區內容(stashes),因此有些人更喜歡在系統之間共享工作區。
如果您這樣做,推薦的方法是對倉庫根目錄使用
rsync
-a
--delete-after
(理想情況下使用加密連線,例如ssh
)。當您這樣做時,應確保以下幾點:-
如果您有額外的
worktrees
或一個獨立的 Git 目錄,它們必須與主工作區和倉庫同時同步。 -
您接受目標目錄是源目錄的精確副本,刪除已有的任何資料。
-
在傳輸期間,倉庫(包括所有工作區和 Git 目錄)處於靜止狀態(即,沒有進行任何型別的操作,包括後臺操作如
git
gc
和您的編輯器呼叫的操作)。請注意,即使有這些建議,以這種方式同步仍存在一定風險,因為它繞過了 Git 對倉庫的正常完整性檢查,因此建議進行備份。您可能還希望在同步後在目標系統上執行
git
fsck
來驗證資料的完整性。
-
常見問題
- 我要求 Git 忽略某些檔案,但它們仍然被跟蹤
-
gitignore
檔案確保某些未被 Git 跟蹤的檔案保持未跟蹤狀態。然而,有時特定檔案在被新增到.gitignore
之前可能已經被跟蹤,因此它們仍然處於被跟蹤狀態。要取消跟蹤並忽略檔案/模式,請使用 git rm --cached <file/pattern> 並向.gitignore
新增一個與 <file> 匹配的模式。有關詳細資訊,請參閱 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
將需要超時,例如-t
10
。這是必需的,因為 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 中間盒、Windows Defender 和 Windows Firewall 之外的 Windows 防毒軟體和防火牆程式,以及過濾代理,都未能達到此標準,結果導致 Git 無法正常工作。鑑於大量問題報告及其糟糕的安全歷史,我們不建議使用這些類別的軟體和裝置。
合併與變基
- 使用 squash 合併來合併長期分支會發生什麼問題?
-
一般來說,使用 squash 合併多次合併兩個分支時可能會出現各種問題。這可能包括在
git
log
輸出、GUI 或使用 ... 符號表示範圍時看到額外的提交,以及可能需要反覆重新解決衝突的問題。當 Git 對兩個分支進行正常合併時,它會考慮三個點:這兩個分支和一個稱為合併基礎的第三個提交,通常是這些提交的共同祖先。合併的結果是合併基礎與每個頭之間的更改的總和。當您使用常規合併提交合並兩個分支時,這將生成一個新的提交,當它們再次合併時,該提交將成為新的合併基礎,因為現在有了一個新的共同祖先。Git 無需考慮合併基礎之前發生的更改,因此您不必重新解決之前解決過的任何衝突。
當您執行 squash 合併時,不會建立合併提交;相反,一方的更改將作為常規提交應用到另一方。這意味著這些分支的合併基礎不會改變,因此當 Git 執行下一次合併時,它會考慮上次考慮的所有更改以及新的更改。這意味著任何衝突可能需要重新解決。同樣,任何在
git
diff
、git
log
或 GUI 中使用 ... 符號的操作都將顯示自原始合併基礎以來的所有更改。因此,如果您想反覆合併兩個長期分支,最好始終使用常規合併提交。
- 如果我在兩個分支上都進行了更改,但在一個分支上撤銷了該更改,為什麼這些分支的合併仍然包含該更改?
-
預設情況下,當 Git 進行合併時,它使用一種稱為
ort
策略的方法,這是一種高階的三向合併。在這種情況下,當 Git 執行合併時,它只考慮三個點:兩個頭和一個稱為合併基礎的第三個點,該點通常是這些提交的共同祖先。Git 完全不考慮這些分支上發生的歷史或單個提交。因此,如果兩邊都有更改,而其中一邊撤銷了該更改,結果是包含該更改。這是因為程式碼在一邊發生了更改,而另一邊沒有淨更改,在這種情況下,Git 採用該更改。
如果這對您來說是個問題,您可以改為進行 rebase,將帶有撤銷的那個分支 rebase 到另一個分支上。在這種情況下,rebase 將撤銷更改,因為 rebase 會應用每個單獨的提交,包括撤銷。請注意,rebase 會重寫歷史記錄,因此除非您確定可以接受,否則應避免對已釋出的(published)分支進行 rebase。有關更多詳細資訊,請參閱 git-rebase[1] 中的 NOTES 部分。
鉤子
- 如何使用鉤子來阻止使用者進行某些更改?
-
進行這些更改的唯一安全位置是遠端倉庫(即 Git 伺服器),通常在
pre-receive
鉤子或持續整合 (CI) 系統中。這些是政策可以有效執行的位置。嘗試使用
pre-commit
鉤子(或者對於提交訊息,使用commit-msg
鉤子)來檢查這些事情是很常見的,如果您是單獨開發者並希望工具幫助您,這非常有用。然而,在開發者機器上使用鉤子作為策略控制是無效的,因為使用者可以(透過各種其他方式)使用--no-verify
繞過這些鉤子而不被發現。Git 假定使用者控制其本地倉庫,並且不會試圖阻止或告發使用者。此外,一些高階使用者發現
pre-commit
鉤子會妨礙使用臨時提交來暫存進行中的工作或建立 fixup 提交的工作流程,因此最好還是將此類檢查推送到伺服器。
跨平臺問題
- 我使用 Windows,並且我的文字檔案被檢測為二進位制檔案。
-
當您以 UTF-8 格式儲存文字檔案時,Git 的工作效果最佳。Windows 上的許多程式支援 UTF-8,但有些不支援,只使用小端 UTF-16 格式,Git 會將其檢測為二進位制檔案。如果您的程式不能使用 UTF-8,您可以指定一個工作區編碼,指示您的檔案應該以何種編碼檢出,同時仍將這些檔案以 UTF-8 儲存在倉庫中。這允許 git-diff[1] 等工具按預期工作,同時仍允許您的工具工作。
為此,您可以指定一個帶有
working-tree-encoding
屬性的 gitattributes[5] 模式。例如,以下模式將所有 C 語言檔案設定為使用 UTF-16LE-BOM,這是 Windows 上常見的編碼:*.c working-tree-encoding=UTF-16LE-BOM
您需要執行
git
add
--renormalize
才能使其生效。請注意,如果您在跨平臺使用的專案中進行這些更改,您可能希望在每個使用者的配置檔案中或$GIT_DIR/info/attributes
中的檔案中進行更改,因為在倉庫的.gitattributes
檔案中進行更改將應用於倉庫的所有使用者。有關標準化行尾的資訊,請參閱以下條目,並參閱 gitattributes[5] 獲取有關屬性檔案的更多資訊。
- 我使用 Windows,並且 `git diff` 顯示我的檔案末尾有
^M
。 -
預設情況下,Git 期望檔案以 Unix 行尾儲存。因此,作為 Windows 行尾一部分的回車符(
^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)。這些設定在跨平臺和使用諸如
git
diff
和git
merge
等工具時效果最佳。此外,如果您可以在基於文字和非基於文字的儲存格式之間進行選擇,我們建議將檔案儲存為文字格式,並在必要時將其轉換為其他格式。例如,每行一個記錄的基於文字的 SQL 轉儲在差異比較和合並方面比實際的資料庫檔案效果好得多。類似地,Markdown 和 AsciiDoc 等基於文字的格式比 Microsoft Word 和 PDF 等二進位制格式效果更好。
類似地,通常不建議在倉庫中儲存二進位制依賴項(例如共享庫或 JAR 檔案)或構建產品。依賴項和構建產品最好儲存在製品或包伺服器上,倉庫中只儲存引用、URL 和雜湊值。
我們還建議設定一個 gitattributes[5] 檔案,以明確標記哪些檔案是文字檔案,哪些是二進位制檔案。如果您希望 Git 猜測,可以將屬性
text=auto
設定為自動檢測。對於文字檔案,Git 通常會確保在倉庫中使用 LF 行尾。
core.autocrlf
和core.eol
配置變數指定檢出任何文字檔案時遵循的行尾約定。您還可以使用eol
屬性(例如eol=crlf
)來覆蓋哪些檔案獲得何種行尾處理。例如,通常 shell 檔案必須有 LF 行尾,批處理檔案必須有 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
這些設定有助於工具為補丁等輸出選擇正確的格式,並使檔案以適合平臺的正確行尾檢出。