設定和配置
獲取和建立專案
基本快照
分支與合併
共享和更新專案
檢查和比較
打補丁
除錯
電子郵件
外部系統
伺服器管理
指南
管理
底層命令
- 2.50.1 無更改
-
2.50.0
2025-06-16
- 2.49.1 無更改
-
2.49.0
2025-03-14
- 2.46.1 → 2.48.2 無變化
-
2.46.0
2024-07-29
- 2.44.1 → 2.45.4 無更改
-
2.44.0
2024-02-23
- 2.43.1 → 2.43.7 無更改
-
2.43.0
2023-11-20
- 2.42.1 → 2.42.4 無更改
-
2.42.0
2023-08-21
- 2.41.1 → 2.41.3 無更改
-
2.41.0
2023-06-01
- 2.40.1 → 2.40.4 無更改
-
2.40.0
2023-03-12
- 2.36.1 → 2.39.5 無變更
-
2.36.0
2022-04-18
- 2.32.1 → 2.35.8 無變化
-
2.32.0
2021-06-06
- 2.30.1 → 2.31.8 無更改
-
2.30.0
2020-12-27
- 2.27.1 → 2.29.3 無更改
-
2.27.0
2020-06-01
- 2.25.1 → 2.26.3 無更改
-
2.25.0
2020-01-13
- 2.24.1 → 2.24.4 無更改
-
2.24.0
2019-11-04
- 2.23.1 → 2.23.4 無更改
-
2.23.0
2019-08-16
- 2.22.1 → 2.22.5 無更改
-
2.22.0
2019-06-07
- 2.21.1 → 2.21.4 無更改
-
2.21.0
2019-02-24
- 2.19.3 → 2.20.5 無更改
-
2.19.2
2018-11-21
- 2.18.1 → 2.19.1 無變更
-
2.18.0
2018-06-21
- 2.17.1 → 2.17.6 無更改
-
2.17.0
2018-04-02
-
2.16.6
2019-12-06
- 2.15.4 無更改
-
2.14.6
2019-12-06
-
2.13.7
2018-05-22
- 2.12.5 無更改
-
2.11.4
2017-09-22
-
2.10.5
2017-09-22
-
2.9.5
2017-07-30
- 2.7.6 → 2.8.6 無更改
-
2.6.7
2017-05-05
-
2.5.6
2017-05-05
-
2.4.12
2017-05-05
- 2.3.10 無更改
-
2.2.3
2015-09-04
- 2.1.4 無更改
-
2.0.5
2014-12-17
描述
一個 gitattributes
檔案是一個簡單的文字檔案,它為路徑名指定 屬性
。
gitattributes
檔案中的每一行都採用以下形式
pattern attr1 attr2 ...
即,一個模式後面跟著一個屬性列表,由空格分隔。前導和尾隨空格被忽略。以#開頭的行被忽略。以雙引號開頭的模式以 C 風格引用。當模式匹配到相關路徑時,該行中列出的屬性將被賦予該路徑。
對於給定路徑,每個屬性可以處於以下狀態之一
當多個模式匹配同一路徑時,後來的行會覆蓋早前的行。這種覆蓋是針對每個屬性進行的。
模式匹配路徑的規則與 .gitignore
檔案中的規則相同(參見 gitignore[5]),但有一些例外
-
負模式是被禁止的
-
匹配目錄的模式不會遞迴地匹配該目錄內的路徑(因此,在 attributes 檔案中使用尾隨斜槓
path/
語法是無意義的;請改用path/**
)
在決定為路徑分配哪些屬性時,Git 會查閱 $GIT_DIR/info/attributes
檔案(優先順序最高)、與相關路徑在同一目錄中的 .gitattributes
檔案及其父目錄,直到工作樹的頂層(包含 .gitattributes
的目錄距離相關路徑越遠,其優先順序越低)。最後,全域性和系統級檔案也會被考慮(它們的優先順序最低)。
如果工作樹中缺少 .gitattributes
檔案,則使用索引中的路徑作為備用。在檢出過程中,首先使用索引中的 .gitattributes
,然後使用工作樹中的檔案作為備用。
如果您只想影響單個倉庫(即,為特定於某個使用者在該倉庫工作流程的檔案分配屬性),則屬性應放在 $GIT_DIR/info/attributes
檔案中。應進行版本控制並分發到其他倉庫的屬性(即,所有使用者都感興趣的屬性)應放在 .gitattributes
檔案中。應影響單個使用者所有倉庫的屬性應放在由 core.attributesFile
配置選項指定的檔案中(參見 git-config[1])。其預設值為 $XDG_CONFIG_HOME/git/attributes。如果 $XDG_CONFIG_HOME 未設定或為空,則使用 $HOME/.config/git/attributes。系統上所有使用者的屬性應放在 $
(prefix
)/etc/gitattributes
檔案中。
有時您需要將路徑的某個屬性設定覆蓋為 未指定
狀態。這可以透過在屬性名稱前加上一個感嘆號 !
來實現。
影響
Git 的某些操作可以透過為路徑分配特定屬性來影響。目前,以下操作是屬性感知的。
檢出和檢入
這些屬性影響當諸如 git switch、git checkout 和 git merge 等命令執行時,倉庫中儲存的內容如何複製到工作樹檔案。它們還影響 Git 在 git add 和 git commit 時如何將您在工作樹中準備好的內容儲存到倉庫中。
text
此屬性將路徑標記為文字檔案,從而啟用行結束符轉換:當匹配檔案新增到索引時,檔案的行結束符在索引中標準化為 LF。相反,當檔案從索引複製到工作目錄時,其行結束符可能會從 LF 轉換為 CRLF,具體取決於 eol
屬性、Git 配置和平臺(參見下面 eol
的解釋)。
- 設定
-
在路徑上設定
text
屬性會啟用如上所述的檢入和檢出時的行結束符轉換。每次檢入檔案時,行結束符都會在索引中標準化為 LF,即使該檔案以前是使用 CRLF 行結束符新增到 Git 的。 - 未設定
-
在路徑上取消設定
text
屬性會告訴 Git 不要在檢入或檢出時嘗試任何行結束符轉換。 - 設定為字串值“auto”
-
當
text
設定為“auto”時,Git 會自行決定檔案是文字還是二進位制。如果它是文字且檔案尚未以 CRLF 結束符儲存在 Git 中,則如上所述在檢入和檢出時進行行結束符轉換。否則,在檢入或檢出時不做任何轉換。 - 未指定
-
如果
text
屬性未指定,Git 使用core.autocrlf
配置變數來確定是否應轉換檔案。
任何其他值都會使 Git 表現得如同 text
未指定一樣。
eol
此屬性標記路徑,使其在檢出時在工作樹中使用特定的行結束符樣式。它僅在設定了 text
或 text=auto
時才生效(參見上文),但如果 text
未指定,指定 eol
會自動設定 text
。
- 設定為字串值“crlf”
-
此設定在檢出檔案時將其行結束符在工作目錄中轉換為 CRLF。
- 設定為字串值“lf”
-
此設定在檢出檔案時,工作目錄中的行結束符與索引中的相同。
- 未指定
-
如果檔案的
eol
屬性未指定,則其在工作目錄中的行結束符由core.autocrlf
或core.eol
配置變數決定(參見 git-config[1] 中這些選項的定義)。如果text
已設定但這兩個變數均未設定,則 Windows 上的預設值為eol=crlf
,所有其他平臺上的預設值為eol=lf
。
行結束符轉換
雖然 Git 通常不觸及檔案內容,但可以將其配置為在倉庫中將行結束符標準化為 LF,並(可選地)在檢出檔案時將其轉換為 CRLF。
如果您只是希望工作目錄中具有 CRLF 行結束符,無論您使用的是哪個倉庫,您都可以設定配置變數 "core.autocrlf" 而不使用任何屬性。
[core] autocrlf = true
這不會強制文字檔案進行標準化,但會確保您引入倉庫的文字檔案在新增時將其行結束符標準化為 LF,並且倉庫中已標準化的檔案保持標準化。
如果您想確保任何貢獻者引入倉庫的文字檔案都將其行結束符標準化,您可以為 所有 檔案將 text
屬性設定為 "auto"。
* text=auto
這些屬性允許對行結束符的轉換進行精細控制。以下是一個示例,它將使 Git 標準化 .txt、.vcproj 和 .sh 檔案,確保 .vcproj 檔案在工作目錄中使用 CRLF,.sh 檔案使用 LF,並防止 .jpg 檔案無論其內容如何都被標準化。
* text=auto *.txt text *.vcproj text eol=crlf *.sh text eol=lf *.jpg -text
注意
|
當在跨平臺專案中使用 push 和 pull 到中央倉庫時啟用 text=auto 轉換時,包含 CRLF 的文字檔案應被標準化。 |
從乾淨的工作目錄開始
$ echo "* text=auto" >.gitattributes $ git add --renormalize . $ git status # Show files that will be normalized $ git commit -m "Introduce end-of-line normalization"
如果任何不應標準化的檔案出現在 git status 中,請在執行 git add -u 之前取消設定它們的 text
屬性。
manual.pdf -text
反之,Git 未檢測到的文字檔案可以手動啟用標準化。
weirdchars.txt text
如果 core.safecrlf
設定為 "true" 或 "warn",Git 會驗證轉換對於 core.autocrlf
的當前設定是否可逆。對於 "true",Git 拒絕不可逆的轉換;對於 "warn",Git 只打印警告但接受不可逆的轉換。安全機制觸發以防止對工作樹中的檔案進行此類轉換,但也有一些例外。儘管…
-
git add 本身不會觸及工作樹中的檔案,但下一次檢出會,因此會觸發安全機制;
-
git apply 更新帶有補丁的文字檔案會觸及工作樹中的檔案,但該操作是關於文字檔案的,CRLF 轉換是為了修復行結束符不一致,因此不會觸發安全機制;
-
git diff 本身不會觸及工作樹中的檔案,它通常用於檢查您打算接下來 git add 的更改。為了儘早發現潛在問題,會觸發安全機制。
working-tree-encoding
Git 識別以 ASCII 或其超集(例如 UTF-8、ISO-8859-1 等)編碼的檔案作為文字檔案。以某些其他編碼(例如 UTF-16)編碼的檔案被解釋為二進位制,因此內建的 Git 文字處理工具(例如 git diff)以及大多數 Git Web 前端預設不顯示這些檔案的內容。
在這些情況下,您可以使用 working-tree-encoding
屬性告訴 Git 工作目錄中檔案的編碼。如果一個帶有此屬性的檔案被新增到 Git,那麼 Git 會將內容從指定的編碼重新編碼為 UTF-8。最後,Git 將 UTF-8 編碼的內容儲存在其內部資料結構中(稱為“索引”)。在檢出時,內容會被重新編碼回指定的編碼。
請注意,使用 working-tree-encoding
屬性可能會帶來許多陷阱
-
其他 Git 實現(例如 JGit 或 libgit2)和較舊的 Git 版本(截至 2018 年 3 月)不支援
working-tree-encoding
屬性。如果您決定在倉庫中使用working-tree-encoding
屬性,強烈建議確保所有使用該倉庫的客戶端都支援它。例如,Microsoft Visual Studio 資原始檔(
*.rc
)或 PowerShell 指令碼檔案(*.ps1
)有時以 UTF-16 編碼。如果您宣告*.ps1
檔案為 UTF-16,並且您使用啟用了working-tree-encoding
的 Git 客戶端新增foo.ps1
,那麼foo.ps1
將在內部儲存為 UTF-8。一個沒有working-tree-encoding
支援的客戶端將以 UTF-8 編碼的檔案檢出foo.ps1
。這通常會給該檔案的使用者帶來麻煩。如果不支援
working-tree-encoding
屬性的 Git 客戶端添加了一個新檔案bar.ps1
,那麼bar.ps1
將“原樣”儲存在內部(在此示例中可能為 UTF-16)。支援working-tree-encoding
的客戶端會將內部內容解釋為 UTF-8,並在檢出時嘗試將其轉換為 UTF-16。該操作將失敗並導致錯誤。 -
將內容重新編碼為非 UTF 編碼可能會導致錯誤,因為轉換可能不是 UTF-8 往返安全的。如果您懷疑您的編碼不是往返安全的,請將其新增到
core.checkRoundtripEncoding
以使 Git 檢查往返編碼(參見 git-config[1])。SHIFT-JIS(日文字元集)已知存在 UTF-8 往返問題,並預設進行檢查。 -
重新編碼內容需要資源,這可能會減慢某些 Git 操作(例如 git checkout 或 git add)。
僅當您無法將檔案儲存為 UTF-8 編碼並且希望 Git 能夠將內容作為文字處理時,才使用 working-tree-encoding
屬性。
例如,如果您的 *.ps1 檔案是帶有位元組順序標記(BOM)的 UTF-16 編碼,並且您希望 Git 根據您的平臺執行自動行結束符轉換,請使用以下屬性。
*.ps1 text working-tree-encoding=UTF-16
如果您的 *.ps1 檔案是無 BOM 的 UTF-16 小端編碼,並且您希望 Git 在工作目錄中使用 Windows 行結束符,請使用以下屬性(如果您想要帶 BOM 的 UTF-16 小端,請使用 UTF-16LE-BOM
而不是 UTF-16LE
)。請注意,強烈建議在使用 working-tree-encoding
屬性時顯式定義行結束符與 eol
,以避免歧義。
*.ps1 text working-tree-encoding=UTF-16LE eol=crlf
您可以使用以下命令獲取平臺上所有可用編碼的列表
iconv --list
如果您不知道檔案的編碼,則可以使用 file
命令猜測編碼
file foo.ps1
ident
當路徑設定了 ident
屬性時,Git 會在檢出時將 blob 物件中的 $Id$
替換為 $Id:
,後跟 40 個字元的十六進位制 blob 物件名稱,再後跟一個美元符號 $
。工作樹檔案中以 $Id:
開頭並以 $
結尾的任何位元組序列在檢入時都會被替換為 $Id$
。
filter
可以將 filter
屬性設定為一個字串值,該值命名了配置中指定的過濾器驅動程式。
一個過濾器驅動程式由一個 clean
命令和一個 smudge
命令組成,其中任何一個都可以不指定。在檢出時,如果指定了 smudge
命令,則將 blob 物件作為其標準輸入,並使用其標準輸出來更新工作樹檔案。類似地,clean
命令用於在檢入時轉換工作樹檔案的內容。預設情況下,這些命令只處理單個 blob 並終止。如果使用長時間執行的 process
過濾器代替 clean
和/或 smudge
過濾器,那麼 Git 可以透過一次過濾器命令呼叫處理所有 blob,該呼叫持續單個 Git 命令的整個生命週期,例如 git
add
--all
。如果配置了長時間執行的 process
過濾器,則它始終優先於配置的單個 blob 過濾器。有關與 process
過濾器通訊所用協議的描述,請參閱以下部分。
內容過濾的一種用途是,將內容整理成對平臺、檔案系統和使用者來說更方便使用的形式。對於這種操作模式,關鍵短語是“更方便”,而不是“將不可用的東西變成可用”。換句話說,其目的是,如果有人取消設定過濾器驅動程式定義,或者沒有合適的過濾器程式,專案仍然應該可用。
內容過濾的另一個用途是儲存無法直接在倉庫中使用的內容(例如,引用儲存在 Git 外部的真實內容的 UUID,或加密內容),並在檢出時將其轉換為可用形式(例如,下載外部內容,或解密加密內容)。
這兩種過濾器行為不同,預設情況下,過濾器被視為前者,將內容整理成更方便的形式。配置中缺少過濾器驅動程式定義,或者過濾器驅動程式以非零狀態退出,這不是錯誤,而是使過濾器成為無操作的直通。
您可以宣告過濾器透過將 filter.<driver>.required 配置變數設定為 true
來將內容轉換為自身不可用的可用內容。
注意:每當 clean 過濾器更改時,倉庫都應重新規範化:$ git add --renormalize .
例如,在 .gitattributes 中,您將為路徑分配 filter
屬性。
*.c filter=indent
然後,您將在 .git/config 中定義 "filter.indent.clean" 和 "filter.indent.smudge" 配置,以指定一對命令來修改 C 程式的內容,當原始碼檔案被檢入時(執行 "clean")和檢出時(不進行更改,因為命令是 "cat")。
[filter "indent"] clean = indent smudge = cat
為了獲得最佳結果,clean
在執行兩次時應不再更改其輸出(“clean→clean”應等同於“clean”),並且多個 smudge
命令不應更改 clean
的輸出(“smudge→smudge→clean”應等同於“clean”)。請參閱下面的合併部分。
“indent”過濾器在這方面表現良好:它不會修改已正確縮排的輸入。在這種情況下,缺少 smudge 過濾器意味著 clean 過濾器 必須 接受自己的輸出而不進行修改。
如果過濾器 必須 成功才能使儲存的內容可用,您可以在配置中宣告該過濾器是 required
的
[filter "crypt"] clean = openssl enc ... smudge = openssl enc -d ... required
過濾器命令列上的序列“%f”被替換為過濾器正在處理的檔名。過濾器可以在關鍵字替換中使用此功能。例如
[filter "p4"] clean = git-p4-filter --clean %f smudge = git-p4-filter --smudge %f
請注意,“%f”是正在處理的路徑的名稱。根據正在過濾的版本,磁碟上的相應檔案可能不存在,或者可能包含不同的內容。因此,smudge 和 clean 命令不應嘗試訪問磁碟上的檔案,而應僅作為標準輸入提供給它們的內容的過濾器。
長時間執行的過濾器程序
如果透過 filter.
<driver>.process
定義了過濾器命令(字串值),那麼 Git 可以在單個 Git 命令的整個生命週期內,透過一次過濾器呼叫處理所有 blob。這是透過使用長時間執行程序協議(在 Documentation/technical/long-running-process-protocol.adoc 中描述)實現的。
當 Git 遇到第一個需要清理或塗抹的檔案時,它會啟動過濾器並執行握手。在握手中,Git 傳送的歡迎訊息是“git-filter-client”,只支援版本 2,支援的功能是“clean”、“smudge”和“delay”。
之後,Git 會發送一個以 flush 包終止的“key=value”對列表。該列表將至少包含過濾器命令(基於支援的功能)以及相對於倉庫根目錄的檔案路徑。緊接著 flush 包,Git 會發送零個或多個 pkt-line 包以及一個 flush 包來終止內容。請注意,在收到內容和最終的 flush 包之前,過濾器不得傳送任何響應。另請注意,“key=value”對的“value”可以包含“=”字元,而 key 永遠不會包含該字元。
packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> 0000 packet: git> CONTENT packet: git> 0000
過濾器應以“key=value”對列表響應,並以 flush 包終止。如果過濾器沒有遇到問題,則該列表必須包含“success”狀態。緊接著這些包之後,過濾器應以零個或多個 pkt-line 包傳送內容,並在末尾傳送一個 flush 包。最後,應期望收到以 flush 包終止的第二個“key=value”對列表。過濾器可以在第二個列表中更改狀態,或透過空列表保持狀態不變。請注意,無論如何,空列表也必須以 flush 包終止。
packet: git< status=success packet: git< 0000 packet: git< SMUDGED_CONTENT packet: git< 0000 packet: git< 0000 # empty list, keep "status=success" unchanged!
如果結果內容為空,則過濾器應以“success”狀態和 flush 包響應,以表示內容為空。
packet: git< status=success packet: git< 0000 packet: git< 0000 # empty content! packet: git< 0000 # empty list, keep "status=success" unchanged!
如果過濾器無法或不想處理內容,則應以“error”狀態響應。
packet: git< status=error packet: git< 0000
如果在處理過程中過濾器遇到錯誤,則可以在內容(部分或完全)傳送後傳送“error”狀態。
packet: git< status=success packet: git< 0000 packet: git< HALF_WRITTEN_ERRONEOUS_CONTENT packet: git< 0000 packet: git< status=error packet: git< 0000
如果過濾器不能或不想處理內容,以及在 Git 程序的生命週期內任何未來的內容,那麼它應該在協議的任何時候響應“abort”狀態。
packet: git< status=abort packet: git< 0000
Git 不會因為設定了“error”/“abort”狀態而停止或重新啟動過濾器程序。但是,Git 會根據 filter.
<driver>.required
標誌設定其退出程式碼,模仿 filter.
<driver>.clean
/ filter.
<driver>.smudge
機制的行為。
如果在通訊過程中過濾器死亡或不遵守協議,那麼 Git 將停止過濾器程序,並在下一個需要處理的檔案時重新啟動它。根據 filter.
<driver>.required
標誌,Git 會將其解釋為錯誤。
延遲
如果過濾器支援“delay”功能,那麼 Git 可以在過濾器命令和路徑名之後傳送“can-delay”標誌。此標誌表示過濾器可以延遲過濾當前 blob(例如,為了補償網路延遲),透過不響應內容但響應“delayed”狀態和一個 flush 包來完成。
packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> can-delay=1 packet: git> 0000 packet: git> CONTENT packet: git> 0000 packet: git< status=delayed packet: git< 0000
如果過濾器支援“delay”功能,那麼它必須支援“list_available_blobs”命令。如果 Git 傳送此命令,則過濾器應返回一個路徑名列表,表示之前已延遲且現在可用的 blob。該列表必須以一個 flush 包終止,後跟一個“success”狀態,該狀態也以一個 flush 包終止。如果延遲路徑的 blob 尚未可用,則過濾器應阻塞響應,直到至少有一個 blob 可用。過濾器可以透過傳送一個空列表來告訴 Git 它沒有更多的延遲 blob。一旦過濾器響應空列表,Git 就會停止詢問。此時 Git 尚未收到的所有 blob 都將被視為丟失並導致錯誤。
packet: git> command=list_available_blobs packet: git> 0000 packet: git< pathname=path/testfile.dat packet: git< pathname=path/otherfile.dat packet: git< 0000 packet: git< status=success packet: git< 0000
Git 收到路徑名後,將再次請求相應的 blob。這些請求包含一個路徑名和一個空的內容部分。過濾器應按照上述方式以通常的方式響應塗抹後的內容。
packet: git> command=smudge packet: git> pathname=path/testfile.dat packet: git> 0000 packet: git> 0000 # empty content! packet: git< status=success packet: git< 0000 packet: git< SMUDGED_CONTENT packet: git< 0000 packet: git< 0000 # empty list, keep "status=success" unchanged!
示例
一個長時間執行的過濾器演示實現可以在 Git 核心倉庫中的 contrib/long-running-filter/example.pl
中找到。如果您開發自己的長時間執行過濾器程序,那麼 GIT_TRACE_PACKET
環境變數對除錯會非常有幫助(參見 git[1])。
請注意,您不能將現有的 filter.
<driver>.clean
或 filter.
<driver>.smudge
命令與 filter.
<driver>.process
一起使用,因為前兩者使用與後者不同的程序間通訊協議。
檢入/檢出屬性之間的互動
在檢入程式碼路徑中,工作樹檔案首先透過 filter
驅動程式(如果指定且定義了相應的驅動程式)進行轉換,然後結果透過 ident
(如果指定)進行處理,最後透過 text
(再次,如果指定且適用)進行處理。
在檢出程式碼路徑中,blob 內容首先透過 text
轉換,然後是 ident
,並提供給 filter
。
合併具有不同檢入/檢出屬性的分支
如果您向檔案添加了導致該檔案規範倉庫格式更改的屬性,例如新增 clean/smudge 過濾器或 text/eol/ident 屬性,那麼合併任何沒有這些屬性的地方通常會導致合併衝突。
為了防止這些不必要的合併衝突,可以透過設定 merge.renormalize
配置變數來告訴 Git 對每個需要三向內容合併的檔案執行所有三個階段的虛擬檢出和檢入。這可以防止檢入轉換引起的更改在轉換後的檔案與未轉換的檔案合併時導致虛假的合併衝突。
只要“smudge→clean”的結果與“clean”的結果相同,即使檔案已經被塗抹,這個策略也將自動解決所有與過濾器相關的衝突。不以這種方式工作的過濾器可能會導致必須手動解決的額外合併衝突。
生成差異文字
diff
屬性 diff
影響 Git 如何為特定檔案生成差異。它可以告訴 Git 是為路徑生成文字補丁還是將路徑視為二進位制檔案。它還可以影響 hunk 頭部 @@
-k,l
+n,m
@@
行上顯示哪一行,告訴 Git 使用外部命令生成差異,或者要求 Git 在生成差異之前將二進位制檔案轉換為文字格式。
- 設定
-
被設定了
diff
屬性的路徑被視為文字,即使它們包含通常不會出現在文字檔案中的位元組值,例如 NUL。 - 未設定
-
被取消設定
diff
屬性的路徑將生成Binary
files
differ
(如果啟用了二進位制補丁,則生成二進位制補丁)。 - 未指定
-
如果路徑的
diff
屬性未指定,Git 首先檢查其內容,如果看起來是文字且小於 core.bigFileThreshold,則將其視為文字。否則,它將生成Binary
files
differ
。 - 字串
-
差異使用指定的差異驅動程式顯示。每個驅動程式可以指定一個或多個選項,如下節所述。差異驅動程式“foo”的選項由 Git 配置檔案中“diff.foo”部分的配置變數定義。
定義外部差異驅動程式
差異驅動程式的定義是在 gitconfig
中完成的,而不是在 gitattributes
檔案中,所以嚴格來說,本手冊頁談論它是不對的。然而……
要定義外部差異驅動程式 jcdiff
,請在您的 $GIT_DIR/config
檔案(或 $HOME/.gitconfig
檔案)中新增如下部分
[diff "jcdiff"] command = j-c-diff
當 Git 需要向您顯示 diff
屬性設定為 jcdiff
的路徑的差異時,它會呼叫您透過上述配置指定的命令,即 j-c-diff
,帶有 7 個引數,就像呼叫 GIT_EXTERNAL_DIFF
程式一樣。詳情請參閱 git[1]。
如果程式能夠忽略某些更改(類似於 git
diff
--ignore-space-change
),那麼也請將選項 trustExitCode
設定為 true。屆時,如果發現顯著更改,它預計返回退出程式碼 1,否則返回 0。
設定內部差異演算法
可以透過 diff.algorithm
配置鍵設定差異演算法,但有時按路徑設定差異演算法可能會有所幫助。例如,您可能希望對 .json 檔案使用 minimal
差異演算法,對 .c 檔案使用 histogram
等,而無需每次都透過命令列傳遞演算法。
首先,在 .gitattributes
中,為路徑分配 diff
屬性。
*.json diff=<name>
然後,定義一個 "diff.<name>.algorithm" 配置以指定差異演算法,從 myers
、patience
、minimal
或 histogram
中選擇。
[diff "<name>"] algorithm = histogram
此差異演算法適用於面向使用者的差異輸出,如 git-diff(1)、git-show(1),也用於 --stat
輸出。合併機制不會使用透過此方法設定的差異演算法。
注意
|
如果為具有 diff= <name> 屬性的路徑定義了 diff. <name>.command ,它將作為外部差異驅動程式執行(參見上文),並且新增 diff. <name>.algorithm 無效,因為演算法不會傳遞給外部差異驅動程式。 |
定義自定義塊頭
文字差異輸出中每個更改組(稱為“hunk”)都以以下形式的行作為字首
@@ -k,l +n,m @@ TEXT
這被稱為 hunk header(塊頭)。“TEXT”部分預設是以字母、下劃線或美元符號開頭的行;這與 GNU diff -p 輸出使用的內容匹配。然而,此預設選擇不適用於某些內容,您可以使用自定義模式進行選擇。
首先,在 .gitattributes 中,您將為路徑分配 diff
屬性。
*.tex diff=tex
然後,您將定義 "diff.tex.xfuncname" 配置以指定一個正則表示式,該正則表示式匹配您希望作為塊頭“TEXT”出現的行。在您的 $GIT_DIR/config
檔案(或 $HOME/.gitconfig
檔案)中新增如下部分
[diff "tex"] xfuncname = "^(\\\\(sub)*section\\{.*)$"
注意:配置解析器會吞掉一層反斜槓,因此您需要雙倍的反斜槓;上面的模式選擇以反斜槓開頭、後跟零個或多個 sub
再後跟 section
再後跟開括號的行,直到行尾。
有一些內建模式可以使這更容易,其中 tex
就是其中之一,因此您不必在配置檔案中編寫上述內容(您仍然需要透過屬性機制,即 .gitattributes
啟用此功能)。以下內建模式可用
-
ada
適用於 Ada 語言原始碼。 -
bash
適用於 Bourne-Again SHell 語言原始碼。涵蓋 POSIX shell 函式定義的超集。 -
bibtex
適用於帶有 BibTeX 編碼引用的檔案。 -
cpp
適用於 C 和 C++ 語言原始碼。 -
csharp
適用於 C# 語言原始碼。 -
css
適用於層疊樣式表。 -
dts
適用於裝置樹(DTS)檔案。 -
elixir
適用於 Elixir 語言原始碼。 -
fortran
適用於 Fortran 語言原始碼。 -
fountain
適用於 Fountain 文件。 -
golang
適用於 Go 語言原始碼。 -
html
適用於 HTML/XHTML 文件。 -
java
適用於 Java 語言原始碼。 -
kotlin
適用於 Kotlin 語言原始碼。 -
markdown
適用於 Markdown 文件。 -
matlab
適用於 MATLAB 和 Octave 語言原始碼。 -
objc
適用於 Objective-C 語言原始碼。 -
pascal
適用於 Pascal/Delphi 語言原始碼。 -
perl
適用於 Perl 語言原始碼。 -
php
適用於 PHP 語言原始碼。 -
python
適用於 Python 語言原始碼。 -
ruby
適用於 Ruby 語言原始碼。 -
rust
適用於 Rust 語言原始碼。 -
scheme
適用於 Scheme 語言原始碼。 -
tex
適用於 LaTeX 文件原始碼。
自定義詞差異
您可以透過在“diff.*.wordRegex”配置變數中指定合適的正則表示式來定製 git
diff
--word-diff
用於將一行拆分為單詞的規則。例如,在 TeX 中,反斜槓後跟字母序列構成一個命令,但幾個這樣的命令可以連續執行而無需中間空格。要將它們分開,請在您的 $GIT_DIR/config
檔案(或 $HOME/.gitconfig
檔案)中使用如下正則表示式
[diff "tex"] wordRegex = "\\\\[a-zA-Z]+|[{}]|\\\\.|[^\\{}[:space:]]+"
上一節中列出的所有語言都提供了內建模式。
執行二進位制檔案的文字差異
有時,需要檢視某些二進位制檔案文字轉換版本的差異。例如,文字處理文件可以轉換為 ASCII 文字表示,並顯示文字的差異。儘管這種轉換會丟失一些資訊,但生成的差異對於人類檢視很有用(但無法直接應用)。
textconv
配置選項用於定義執行此類轉換的程式。該程式應接受一個引數,即要轉換的檔名,並將結果文字輸出到標準輸出。
例如,要顯示檔案的 exif 資訊而不是二進位制資訊的差異(假設您已安裝 exif 工具),請將以下部分新增到您的 $GIT_DIR/config
檔案(或 $HOME/.gitconfig
檔案)中
[diff "jpg"] textconv = exif
注意
|
文字轉換通常是單向轉換;在此示例中,我們丟失了實際影像內容,僅關注文字資料。這意味著 textconv 生成的差異不適用於應用。因此,只有 git diff 和 git log 系列命令(即 log、whatchanged、show)會執行文字轉換。git format-patch 絕不會生成此輸出。如果您想向某人傳送二進位制檔案的文字轉換差異(例如,因為它能快速傳達您所做的更改),您應該單獨生成它並將其作為評論,除 通常您可能傳送的二進位制差異之外。 |
由於文字轉換可能很慢,尤其是在使用 git
log
-p
進行大量轉換時,Git 提供了一種機制來快取輸出並在未來的差異中使用它。要啟用快取,請在您的差異驅動程式的配置中設定“cachetextconv”變數。例如
[diff "jpg"] textconv = exif cachetextconv = true
這將無限期地快取對每個 blob 執行“exif”的結果。如果您更改差異驅動程式的 textconv 配置變數,Git 將自動使快取條目失效並重新執行 textconv 過濾器。如果您想手動使快取失效(例如,因為您的“exif”版本已更新,現在生成了更好的輸出),您可以使用 git
update-ref
-d
refs/notes/textconv/jpg
手動刪除快取(其中“jpg”是差異驅動程式的名稱,如上面的示例所示)。
選擇 textconv 與外部差異
如果您想顯示倉庫中二進位制或特殊格式 blob 之間的差異,您可以選擇使用外部差異命令,或者使用 textconv 將它們轉換為可差異的文字格式。選擇哪種方法取決於您的具體情況。
使用外部差異命令的優點是靈活性。您不受限於查詢面向行的更改,也不要求輸出類似於統一差異。您可以自由地以最適合您的資料格式的方式查詢和報告更改。
相比之下,textconv 更具限制性。您提供將資料轉換為面向行的文字格式的轉換,Git 使用其常規差異工具生成輸出。選擇此方法有幾個優點
-
易用性。編寫二進位制到文字的轉換通常比執行自己的差異簡單得多。在許多情況下,現有程式可以用作 textconv 過濾器(例如 exif、odt2txt)。
-
Git 差異功能。透過只執行轉換步驟,您仍然可以使用 Git 的許多差異功能,包括著色、詞差異和合並的組合差異。
-
快取。Textconv 快取可以加速重複的差異,例如您透過執行
git
log
-p
可能觸發的那些。
將檔案標記為二進位制
Git 通常透過檢查內容開頭來正確猜測 blob 是包含文字還是二進位制資料。然而,有時您可能希望覆蓋它的決定,無論是由於 blob 在檔案中包含後來的二進位制資料,還是因為內容,儘管技術上由文字字元組成,但對人類讀者來說是不透明的。例如,許多 Postscript 檔案只包含 ASCII 字元,但會產生嘈雜且無意義的差異。
將檔案標記為二進位制的最簡單方法是在 .gitattributes
檔案中取消設定 diff 屬性
*.ps -diff
這將導致 Git 生成 Binary
files
differ
(或二進位制補丁,如果啟用了二進位制補丁)而不是常規差異。
但是,可能還需要指定其他差異驅動程式屬性。例如,您可能希望使用 textconv
將 Postscript 檔案轉換為 ASCII 表示以供人工檢視,但否則將它們視為二進位制檔案。您不能同時指定 -diff
和 diff=ps
屬性。解決方案是使用 diff.*.binary
配置選項
[diff "ps"] textconv = ps2ascii binary = true
執行三向合併
merge
merge
屬性影響在 git
merge
和其他命令(例如 git
revert
和 git
cherry-pick
)期間需要檔案級合併時,檔案的三個版本如何合併。
- 設定
-
內建的三向合併驅動程式用於合併內容,其方式類似於
RCS
套件的 merge 命令。這適用於普通文字檔案。 - 未設定
-
將當前分支的版本作為暫定的合併結果,並宣告合併存在衝突。這適用於沒有明確合併語義的二進位制檔案。
- 未指定
-
預設情況下,這會使用與
merge
屬性設定時相同的內建三向合併驅動程式。但是,merge.default
配置變數可以指定不同的合併驅動程式,用於merge
屬性未指定的路徑。 - 字串
-
使用指定的自定義合併驅動程式執行三向合併。內建的三向合併驅動程式可以透過請求“text”驅動程式顯式指定;內建的“take the current branch”驅動程式可以透過“binary”請求。
定義自定義合併驅動程式
合併驅動程式的定義是在 .git/config
檔案中完成的,而不是在 gitattributes
檔案中,所以嚴格來說,本手冊頁談論它是不對的。然而……
要定義自定義合併驅動程式 filfre
,請在您的 $GIT_DIR/config
檔案(或 $HOME/.gitconfig
檔案)中新增如下部分
[merge "filfre"] name = feel-free merge driver driver = filfre %O %A %B %L %P recursive = binary
merge.*.name
變數為驅動程式提供了一個人類可讀的名稱。
merge.*.driver
變數的值用於構建一個命令,該命令執行以處理共同祖先版本 (%O
)、當前版本 (%A
) 和其他分支的版本 (%B
)。當構建命令列時,這些三個令牌將替換為儲存這些版本內容的臨時檔案的名稱。此外,%L
將替換為衝突標記大小(見下文)。
合併驅動程式預期透過覆蓋 %A
指定的檔案來留下合併結果,如果能幹淨合併則以零狀態退出,否則以非零狀態退出表示存在衝突。當驅動程式崩潰(例如被 SEGV 殺死)時,預期以高於 128 的非零狀態退出,在這種情況下,合併會導致失敗(這與產生衝突不同)。
merge.*.recursive
變數指定當合併驅動程式被呼叫以進行多個共同祖先之間的內部合併時,使用哪個其他合併驅動程式。如果未指定,則驅動程式本身將用於內部合併和最終合併。
合併驅動程式可以透過佔位符 %P
瞭解儲存合併結果的路徑名。用於共同祖先、本地頭部和其他頭部的衝突標籤可以透過使用 %S
、%X
和 %Y
分別傳遞。
檢查空白錯誤
whitespace
core.whitespace
配置變數允許您定義 diff 和 apply 應將哪些空白視為專案所有路徑的錯誤(參見 git-config[1])。此屬性使您能夠對每個路徑進行更精細的控制。
建立存檔
export-subst
如果檔案設定了 export-subst
屬性,那麼 Git 在將此檔案新增到存檔時將展開幾個佔位符。展開取決於提交 ID 的可用性,即,如果 git-archive[1] 已給定樹而不是提交或標籤,則不會進行替換。佔位符與 git-log[1] 的 --pretty=format:
選項的佔位符相同,只是它們需要在檔案中像這樣包裝:$Format:PLACEHOLDERS$
。例如,字串 $Format:%H$
將被提交雜湊替換。但是,每個存檔只展開一個 %
(describe
) 佔位符,以避免拒絕服務攻擊。
在 GUI 工具中檢視檔案
encoding
此屬性的值指定 GUI 工具(例如 gitk[1] 和 git-gui[1])顯示相關檔案內容時應使用的字元編碼。請注意,出於效能考慮,gitk[1] 不使用此屬性,除非您在其選項中手動啟用按檔案編碼。
如果此屬性未設定或具有無效值,則改用 gui.encoding
配置變數的值(參見 git-config[1])。
使用宏屬性
您不希望對任何您跟蹤的二進位制檔案應用行結束符轉換,也不希望生成文字差異。您需要指定例如
*.jpg -text -diff
但這可能會變得很麻煩,當您有許多屬性時。使用宏屬性,您可以定義一個屬性,當它被設定時,同時設定或取消設定許多其他屬性。系統知道一個內建的宏屬性 binary
*.jpg binary
設定“binary”屬性也會像上面那樣取消設定“text”和“diff”屬性。請注意,宏屬性只能是“設定”狀態,儘管設定一個可能會導致設定或取消設定其他屬性,甚至將其他屬性恢復到“未指定”狀態。
定義宏屬性
自定義宏屬性只能在頂級 gitattributes 檔案中定義($GIT_DIR/info/attributes
、工作樹頂層的 .gitattributes
檔案,或全域性或系統範圍的 gitattributes 檔案),不能在工作樹子目錄中的 .gitattributes
檔案中定義。內建宏屬性“binary”等同於
[attr]binary -diff -merge -text
示例
如果您有這三個 gitattributes
檔案
(in $GIT_DIR/info/attributes) a* foo !bar -baz (in .gitattributes) abc foo bar baz (in t/.gitattributes) ab* merge=filfre abc -foo -bar *.c frotz
路徑 t/abc
的屬性計算如下
-
透過檢查
t/.gitattributes
(它與相關路徑位於同一目錄中),Git 發現第一行匹配。merge
屬性被設定。它還發現第二行匹配,並且屬性foo
和bar
被取消設定。 -
然後它檢查
.gitattributes
(位於父目錄),發現第一行匹配,但是t/.gitattributes
檔案已經決定了如何將merge
、foo
和bar
屬性賦予此路徑,因此它將foo
和bar
保持未設定。屬性baz
被設定。 -
最後,它檢查
$GIT_DIR/info/attributes
。此檔案用於覆蓋樹內設定。第一行匹配,foo
被設定,bar
被恢復到未指定狀態,baz
被取消設定。
結果,分配給 t/abc
的屬性變為
foo set to true bar unspecified baz set to false merge set to string value "filfre" frotz unspecified