# gitattributes
> 原文: [https://git-scm.com/docs/gitattributes](https://git-scm.com/docs/gitattributes)
## 名稱
gitattributes - 定義每個路徑的屬性
## 概要
$ GIT_DIR / info / attributes,.gitattributes
## 描述
`gitattributes`文件是一個簡單的文本文件,它為路徑名提供`attributes`。
`gitattributes`文件中的每一行都是以下形式:
```
pattern attr1 attr2 ...
```
也就是說,一個模式后跟一個屬性列表,用空格分隔。前導空格和尾隨空格被忽略。以_#_開頭的行將被忽略。以雙引號開頭的模式以C風格引用。當模式匹配相關路徑時,該行上列出的屬性將被賦予路徑。
對于給定路徑,每個屬性可以處于以下狀態之一:
```
Set
```
該路徑具有特殊值“true”的屬性;這是通過僅列出屬性列表中屬性的名稱來指定的。
```
Unset
```
該路徑具有特殊值“false”的屬性;這是通過在屬性列表中列出前綴為短劃線`-`的屬性的名稱來指定的。
```
Set to a value
```
該路徑具有指定字符串值的屬性;這是通過列出屬性的名稱,后跟等號`=`及其在屬性列表中的值來指定的。
```
Unspecified
```
沒有模式匹配路徑,沒有任何說明路徑是否具有屬性,路徑的屬性被稱為未指定。
當多個模式與路徑匹配時,后一行會覆蓋較早的行。這個覆蓋是按屬性完成的。
模式匹配路徑的規則與`.gitignore`文件中的規則相同(參見 [gitignore [5]](https://git-scm.com/docs/gitignore) ),但有一些例外:
* 消極的模式被禁止
* 與目錄匹配的模式不會遞歸地匹配該目錄中的路徑(因此在屬性文件中使用尾部斜杠`path/`語法是沒有意義的;使用`path/**`代替)
在確定為路徑分配了哪些屬性時,Git會查詢`$GIT_DIR/info/attributes`文件(具有最高優先級),`.gitattributes`文件與相關路徑位于同一目錄中,其父目錄最多為工作樹的頂層(包含`.gitattributes`的目錄越遠離有問題的路徑,其優先級越低)。最后考慮全局和系統范圍的文件(它們具有最低優先級)。
當工作樹中缺少`.gitattributes`文件時,索引中的路徑將用作后退。在檢出過程中,使用索引中的`.gitattributes`,然后將工作樹中的文件用作后備。
如果您希望僅影響單個存儲庫(即,將屬性分配給特定于該存儲庫的一個用戶工作流的文件),則應將屬性放在`$GIT_DIR/info/attributes`文件中。應該由版本控制并分發到其他存儲庫的屬性(即,所有用戶感興趣的屬性)應該進入`.gitattributes`文件。應該影響單個用戶的所有存儲庫的屬性應該放在由`core.attributesFile`配置選項指定的文件中(參見 [git-config [1]](https://git-scm.com/docs/git-config) )。其默認值為$ XDG_CONFIG_HOME / git / attributes。如果$ XDG_CONFIG_HOME未設置或為空,則使用$ HOME / .config / git / attributes。系統中所有用戶的屬性應放在`$(prefix)/etc/gitattributes`文件中。
有時您需要覆蓋`Unspecified`狀態路徑的屬性設置。這可以通過列出前綴為感嘆號`!`的屬性的名稱來完成。
## 影響
通過為路徑分配特定屬性可以影響Git的某些操作。目前,以下操作是屬性感知的。
### 退房和登記入住
當 _git checkout_ 和 _git merge_ 等命令運行時,這些屬性會影響存儲庫中存儲的內容如何復制到工作樹文件。它們還會影響Git如何在 _git add_ 和 _git commit_ 中存儲您在存儲庫中的工作樹中準備的內容。
#### `text`
此屬性啟用并控制行尾標準化。對文本文件進行規范化后,其行結尾將在存儲庫中轉換為LF。要控制工作目錄中使用的行結束樣式,請對單個文件使用`eol`屬性,對所有文本文件使用`core.eol`配置變量。請注意,將`core.autocrlf`設置為`true`或`input`會覆蓋`core.eol`(請參閱 [git-config [1]](https://git-scm.com/docs/git-config) 中這些選項的定義)。
```
Set
```
在路徑上設置`text`屬性可啟用行尾標準化,并將路徑標記為文本文件。在不猜測內容類型的情況下進行行尾轉換。
```
Unset
```
取消設置路徑上的`text`屬性會告訴Git在簽入或結帳時不要嘗試任何行尾轉換。
```
Set to string value "auto"
```
當`text`設置為“auto”時,路徑將標記為自動行結束轉換。如果Git決定內容是文本,則其行結尾將在簽入時轉換為LF。使用CRLF提交文件時,不會進行任何轉換。
```
Unspecified
```
如果未指定`text`屬性,Git使用`core.autocrlf`配置變量來確定是否應轉換文件。
任何其他值都會導致Git表現為好像沒有指定`text`。
#### `eol`
此屬性設置要在工作目錄中使用的特定行結束樣式。它可以在沒有任何內容檢查的情況下實現行尾轉換,從而有效地設置`text`屬性。請注意,在具有CRLF行結尾的索引中的路徑上設置此屬性可能會使路徑被視為臟。再次將索引添加到索引將規范化索引中的行結尾。
```
Set to string value "crlf"
```
此設置強制Git在簽入時規范化此文件的行結尾,并在簽出文件時將它們轉換為CRLF。
```
Set to string value "lf"
```
此設置強制Git在簽入時將行結尾標準化為LF,并在簽出文件時阻止轉換為CRLF。
#### 向后兼容`crlf`屬性
為了向后兼容,`crlf`屬性解釋如下:
```
crlf text
-crlf -text
crlf=input 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
```
| 注意 | 使用推送和拉到中央存儲庫的跨平臺項目中啟用`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`的轉換是否可逆。對于“真實”,Git拒絕不可逆轉的轉換;對于“警告”,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文件并添加`foo.ps1`并啟用`working-tree-encoding` Git客戶端,則`foo.ps1`將在內部存儲為UTF-8。沒有`working-tree-encoding`支持的客戶端將`foo.ps1`簽出為UTF-8編碼文件。這通常會給該文件的用戶帶來麻煩。
如果不支持`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]](https://git-scm.com/docs/git-config) )。已知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_ 文件是UTF-16小端編碼而沒有BOM,并且您希望Git在工作目錄中使用Windows行結尾,請使用以下屬性(如果您使用`UTF-16-LE-BOM`而不是`UTF-16LE`想要帶有BOM的UTF-16小端。請注意,如果使用`working-tree-encoding`屬性來避免歧義,強烈建議使用`eol`明確定義行結尾。
```
*.ps1 text working-tree-encoding=UTF-16LE eol=CRLF
```
您可以使用以下命令獲取平臺上所有可用編碼的列表:
```
iconv --list
```
如果您不知道文件的編碼,則可以使用`file`命令猜測編碼:
```
file foo.ps1
```
#### `ident`
當為路徑設置屬性`ident`時,Git用`$Id:`替換blob對象中的`$Id$`,后跟40個字符的十六進制blob對象名稱,然后在結帳時使用美元符號`$`。任何以`$Id:`開頭并以worktree文件中的`$`結尾的字節序列在簽入時將替換為`$Id$`。
#### `filter`
可以將`filter`屬性設置為字符串值,該值指定配置中指定的過濾器驅動程序。
過濾器驅動程序由`clean`命令和`smudge`命令組成,其中任何一個都可以不指定。簽出時,當指定`smudge`命令時,命令從其標準輸入中提供blob對象,其標準輸出用于更新工作樹文件。同樣,`clean`命令用于在簽入時轉換worktree文件的內容。默認情況下,這些命令僅處理單個blob并終止。如果使用長時間運行的`process`過濾器代替`clean`和/或`smudge`過濾器,那么Git可以在單個Git命令的整個生命周期內使用單個過濾器命令調用處理所有blob,例如`git add --all`。如果配置了長時間運行的`process`過濾器,則它始終優先于配置的單個blob過濾器。有關用于與`process`過濾器通信的協議的說明,請參閱以下部分。
內容過濾的一個用途是將內容按摩成對于平臺,文件系統和用戶更方便使用的形狀。對于這種操作模式,這里的關鍵短語是“更方便”而不是“將某些東西變為無法使用”。換句話說,目的是如果有人取消設置過濾器驅動程序定義,或者沒有適當的過濾程序,則該項目仍應可用。
內容過濾的另一個用途是存儲無法直接在存儲庫中使用的內容(例如,引用存儲在Git外部的真實內容的UUID,或加密內容),并在檢出時將其轉換為可用形式(例如,下載外部內容,或解密加密內容)。
這兩個過濾器的行為不同,默認情況下,過濾器被視為前者,將內容按摩為更方便的形狀。配置中缺少過濾器驅動程序定義,或者以非零狀態退出的過濾器驅動程序不是錯誤,而是使過濾器成為無操作通路。
您可以通過將過濾器< driver> .required配置變量設置為`true`來聲明過濾器將自身無法使用的內容轉換為可用內容。
注意:每當更改清理過濾器時,repo應重新規范化:$ 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`如果運行兩次(“清潔→清潔”應相當于“清潔”),則不應進一步改變其輸出,并且多個`smudge`命令不應改變`clean`的輸出(“涂抹→涂抹→清潔“應相當于”清潔“)。請參閱下面的合并部分。
“indent”過濾器在這方面表現良好:它不會修改已經正確縮進的輸入。在這種情況下,沒有污跡過濾器意味著清潔過濾器_必須_接受自己的輸出而不修改它。
如果過濾器_必須_成功才能使存儲的內容可用,您可以在配置中聲明過濾器為`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”是正在處理的路徑的名稱。根據要過濾的版本,磁盤上的相應文件可能不存在,或者可能具有不同的內容。因此,涂抹和清除命令不應該嘗試訪問磁盤上的文件,而只是作為標準輸入上提供給它們的內容的過濾器。
#### 長時間運行的過濾器
如果通過`filter.<driver>.process`定義過濾器命令(字符串值),則Git可以在單個Git命令的整個生命周期內使用單個過濾器調用處理所有blob。這是通過使用長時間運行的進程協議(在technical / long-running-process-protocol.txt中描述)實現的。
當Git遇到需要清理或污跡的第一個文件時,它會啟動過濾器并執行握手。在握手中,Git發送的歡迎消息是“git-filter-client”,只支持版本2,支持的功能是“干凈”,“涂抹”和“延遲”。
然后Git發送一個以flush數據包終止的“key = value”對列表。該列表至少包含filter命令(基于支持的功能)以及要相對于存儲庫根目錄進行篩選的文件的路徑名。在刷新數據包之后,Git發送內容分為零個或多個pkt-line數據包和一個刷新數據包以終止內容。請注意,過濾器在收到內容和最終刷新數據包之前不得發送任何響應。另請注意,“key = value”對的“值”可以包含“=”字符,而鍵永遠不會包含該字符。
```
packet: git> command=smudge
packet: git> pathname=path/testfile.dat
packet: git> 0000
packet: git> CONTENT
packet: git> 0000
```
期望過濾器響應一個以flush數據包終止的“key = value”對的列表。如果過濾器沒有遇到問題,則列表必須包含“成功”狀態。在這些數據包之后,預期過濾器將在最后發送零個或多個pkt-line數據包和一個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!
```
如果結果內容為空,則期望過濾器以“成功”狀態和刷新分組響應以發信號通知空內容。
```
packet: git< status=success
packet: git< 0000
packet: git< 0000 # empty content!
packet: git< 0000 # empty list, keep "status=success" unchanged!
```
如果過濾器不能或不想處理內容,則應該以“錯誤”狀態響應。
```
packet: git< status=error
packet: git< 0000
```
如果過濾器在處理過程中遇到錯誤,則可以在(部分或完全)發送內容后發送狀態“錯誤”。
```
packet: git< status=success
packet: git< 0000
packet: git< HALF_WRITTEN_ERRONEOUS_CONTENT
packet: git< 0000
packet: git< status=error
packet: git< 0000
```
如果過濾器不能或不想處理內容以及Git過程生命周期內的任何未來內容,則期望在協議中的任何點以“中止”狀態響應。
```
packet: git< status=abort
packet: git< 0000
```
如果設置了“錯誤”/“中止”狀態,Git既不會停止也不會重新啟動過濾器進程。但是,Git根據`filter.<driver>.required`標志設置其退出代碼,模仿`filter.<driver>.clean` / `filter.<driver>.smudge`機制的行為。
如果過濾器在通信期間死亡或者不遵守協議,那么Git將停止過濾器進程并使用下一個需要處理的文件重新啟動它。根據`filter.<driver>.required`標志,Git會將其解釋為錯誤。
#### 延遲
如果過濾器支持“延遲”功能,那么Git可以在過濾器命令和路徑名之后發送標志“can-delay”。該標志表示過濾器可以通過響應沒有內容但具有狀態“延遲”和刷新分組來延遲過濾當前blob(例如,以補償??網絡延遲)。
```
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
```
如果過濾器支持“延遲”功能,則它必須支持“list_available_blobs”命令。如果Git發送此命令,那么過濾器應該返回一個路徑名列表,這些路徑名表示先前已經延遲并且現在可用的blob。該列表必須以刷新數據包結束,然后是“成功”狀態,該狀態也以刷新數據包終止。如果延遲路徑的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]](https://git-scm.com/docs/git) )。
請注意,您不能將現有的`filter.<driver>.clean`或`filter.<driver>.smudge`命令與`filter.<driver>.process`一起使用,因為前者使用的是與后者不同的進程間通信協議。
#### 簽入/簽出屬性之間的交互
在簽入代碼路徑中,首先使用`filter`驅動程序轉換worktree文件(如果指定并定義相應的驅動程序),然后使用`ident`(如果指定)處理結果,最后使用`text`處理(再次) ,如果指定和適用)。
在簽出代碼路徑中,首先使用`text`轉換blob內容,然后使用`ident`轉換為`filter`。
#### 合并具有不同簽入/簽出屬性的分支
如果您為文件添加了導致該文件的規范存儲庫格式更改的屬性,例如添加clean / smudge過濾器或text / eol / ident屬性,那么合并屬性不存在的任何內容通常會導致合并沖突。
為了防止這些不必要的合并沖突,可以告訴Git在通過設置`merge.renormalize`配置變量解析三向合并時運行文件的所有三個階段的虛擬簽出和簽入。當轉換后的文件與未轉換的文件合并時,這可以防止由簽入轉換引起的更改導致虛假合并沖突。
只要“涂抹→清潔”產生與“干凈”相同的輸出,即使對于已經弄臟的文件,此策略也會自動解決所有與過濾器相關的沖突。不以這種方式操作的過濾器可能會導致必須手動解決的其他合并沖突。
### 生成差異文本
#### `diff`
屬性`diff`影響Git如何為特定文件生成差異。它可以告訴Git是為路徑生成文本補丁還是將路徑視為二進制文件。它還可以影響在hunk header `@@ -k,l +n,m @@`行上顯示的行,告訴Git使用外部命令生成diff,或者在生成diff之前讓Git將二進制文件轉換為文本格式。
```
Set
```
設置`diff`屬性的路徑被視為文本,即使它們包含通常永遠不會出現在文本文件中的字節值,例如NUL。
```
Unset
```
未設置`diff`屬性的路徑將生成`Binary files differ`(如果啟用了二進制補丁,則生成二進制補丁)。
```
Unspecified
```
首先指定`diff`屬性未指定的路徑檢查其內容,如果它看起來像文本并且小于core.bigFileThreshold,則將其視為文本。否則會產生`Binary files differ`。
```
String
```
使用指定的diff驅動程序顯示Diff。每個驅動程序可以指定一個或多個選項,如以下部分所述。 diff驅動程序“foo”的選項由Git配置文件的“diff.foo”部分中的配置變量定義。
#### 定義外部差異驅動程序
diff驅動程序的定義是在`gitconfig`中完成的,而不是`gitattributes`文件,所以嚴格來說這個手冊頁是一個錯誤的地方來討論它。然而...
要定義外部差異驅動程序`jcdiff`,請在`$GIT_DIR/config`文件(或`$HOME/.gitconfig`文件)中添加一個部分,如下所示:
```
[diff "jcdiff"]
command = j-c-diff
```
當Git需要顯示`diff`屬性設置為`jcdiff`的路徑的diff時,它會調用您使用上述配置指定的命令,即`j-c-diff`,帶有7個參數,就像調用`GIT_EXTERNAL_DIFF`程序一樣。有關詳細信息,請參閱 [git [1]](https://git-scm.com/docs/git) 。
#### 定義自定義的hunk-header
文本差異輸出中的每組更改(稱為“hunk”)都以以下形式的行為前綴:
```
@@ -k,l +n,m @@ TEXT
```
這稱為_塊頭_。默認情況下,“TEXT”部分是以字母,下劃線或美元符號開頭的行;這匹配GNU _diff -p_ 輸出使用的內容。但是,此默認選擇不適用于某些內容,您可以使用自定義模式進行選擇。
首先,在.gitattributes中,您將為路徑分配`diff`屬性。
```
*.tex diff=tex
```
然后,您將定義一個“diff.tex.xfuncname”配置來指定一個正則表達式,該表達式與您希望顯示為Hunk標題“TEXT”的行匹配。在`$GIT_DIR/config`文件(或`$HOME/.gitconfig`文件)中添加一個部分,如下所示:
```
[diff "tex"]
xfuncname = "^(\\\\(sub)*section\\{.*)$"
```
注意。配置文件解析器會使用單級反斜杠,因此您需要將反斜杠加倍;上面的模式選擇一個以反斜杠開頭的行,然后是`sub`后跟`section`后跟開放式大括號的零次或多次出現,直到行的末尾。
有一些內置模式可以使這更容易,`tex`就是其中之一,因此您不必在配置文件中編寫上述內容(您仍然需要通過屬性機制通過`.gitattributes`啟用它])。可以使用以下內置模式:
* `ada`適用于Ada語言的源代碼。
* `bibtex`適用于帶有BibTeX編碼參考的文件。
* `cpp`適用于C和C ++語言的源代碼。
* `csharp`適用于C#語言的源代碼。
* `css`適用于級聯樣式表。
* `fortran`適用于Fortran語言的源代碼。
* `fountain`適用于Fountain文檔。
* `golang`適用于Go語言的源代碼。
* `html`適用于HTML / XHTML文檔。
* `java`適用于Java語言的源代碼。
* `matlab`適用于MATLAB語言的源代碼。
* `objc`適用于Objective-C語言的源代碼。
* `pascal`適用于Pascal / Delphi語言的源代碼。
* `perl`適用于Perl語言的源代碼。
* `php`適用于PHP語言的源代碼。
* `python`適用于Python語言的源代碼。
* `ruby`適用于Ruby語言的源代碼。
* `tex`適用于LaTeX文檔的源代碼。
#### 自定義單詞差異
您可以通過在“diff。*。wordRegex”配置變量中指定適當的正則表達式來自定義`git diff --word-diff`用于分割行中單詞的規則。例如,在TeX中,反斜杠后跟一系列字母形成一個命令,但是幾個這樣的命令可以一起運行而不會插入空格。要分隔它們,請在`$GIT_DIR/config`文件(或`$HOME/.gitconfig`文件)中使用正則表達式,如下所示:
```
[diff "tex"]
wordRegex = "\\\\[a-zA-Z]+|[{}]|\\\\.|[^\\{}[:space:]]+"
```
為上一節中列出的所有語言提供了內置模式。
#### 執行二進制文件的文本差異
有時需要查看某些二進制文件的文本轉換版本的差異。例如,可以將文字處理器文檔轉換為ASCII文本表示,并顯示文本的差異。即使這種轉換失去了一些信息,生成的差異對人類觀看也很有用(但不能直接應用)。
`textconv`配置選項用于定義執行此類轉換的程序。程序應該采用單個參數,要轉換的文件的名稱,并在stdout上生成結果文本。
例如,要顯示文件的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提供了一種緩存輸出并在將來的差異中使用它的機制。要啟用緩存,請在diff驅動程序的配置中設置“cachetextconv”變量。例如:
```
[diff "jpg"]
textconv = exif
cachetextconv = true
```
這將緩存每個blob上無限期運行“exif”的結果。如果更改diff驅動程序的textconv配置變量,Git將自動使緩存條目無效并重新運行textconv過濾器。如果你想手動使緩存失效(例如,因為你的“exif”版本已更新并且現在產生更好的輸出),你可以用`git update-ref -d refs/notes/textconv/jpg`手動刪除緩存(其中“jpg”是差異驅動程序的名稱,如上例所示)。
#### 選擇textconv與外部差異
如果要在存儲庫中顯示二進制或特殊格式的blob之間的差異,可以選擇使用外部diff命令,或使用textconv將它們轉換為可擴展的文本格式。您選擇哪種方法取決于您的具體情況。
使用外部diff命令的優點是靈活性。您不一定要找到面向行的更改,輸出也不一定要像統一的diff那樣。您可以以最合適的方式為數據格式定位和報告更改。
相比之下,textconv更具限制性。您提供了將數據轉換為面向行的文本格式,Git使用其常規diff工具生成輸出。選擇此方法有幾個好處:
1. 便于使用。編寫二進制文本轉換通常要比執行自己的diff更簡單。在許多情況下,現有程序可以用作textconv過濾器(例如,exif,odt2txt)。
2. Git diff功能。通過自己僅執行轉換步驟,您仍然可以利用Git的許多差異功能,包括著色,字差異和合并差異進行合并。
3. 緩存。 Textconv緩存可以加速重復的差異,例如您可能通過運行`git log -p`觸發的差異。
#### 將文件標記為二進制文件
Git通常通過檢查內容的開頭來正確猜測blob是否包含文本或二進制數據。但是,有時您可能希望覆蓋其決定,因為blob在文件中稍后包含二進制數據,或者因為內容雖然在技術上由文本字符組成,但對于人類讀者來說是不透明的。例如,許多postscript文件僅包含ASCII字符,但會產生嘈雜且無意義的差異。
將文件標記為二進制文件的最簡單方法是取消設置`.gitattributes`文件中的diff屬性:
```
*.ps -diff
```
這將導致Git生成`Binary files differ`(或二進制補丁,如果啟用了二進制補丁)而不是常規差異。
但是,也可能需要指定其他diff驅動程序屬性。例如,您可能希望使用`textconv`將postscript文件轉換為ASCII表示形式以供人工查看,但另外將其視為二進制文件。您不能同時指定`-diff`和`diff=ps`屬性。解決方案是使用`diff.*.binary`配置選項:
```
[diff "ps"]
textconv = ps2ascii
binary = true
```
### 執行三向合并
#### `merge`
當`git merge`期間需要文件級合并以及`git revert`和`git cherry-pick`等其他命令時,屬性`merge`會影響文件的三個版本的合并方式。
```
Set
```
內置的3路合并驅動程序用于以類似于`RCS`套件的 _merge_ 命令的方式合并內容。這適用于普通文本文件。
```
Unset
```
將當前分支中的版本作為暫定合并結果,并聲明合并存在沖突。這適用于沒有明確定義的合并語義的二進制文件。
```
Unspecified
```
默認情況下,它使用與設置`merge`屬性時相同的內置3向合并驅動程序。但是,`merge.default`配置變量可以將不同的合并驅動程序命名為與未指定`merge`屬性的路徑一起使用。
```
String
```
使用指定的自定義合并驅動程序執行3向合并。可以通過詢問“text”驅動程序明確指定內置的3路合并驅動程序;可以使用“二進制”來請求內置的“取當前分支”驅動程序。
#### 內置合并驅動程序
定義了一些內置的低級合并驅動程序,可以通過`merge`屬性詢問。
```
text
```
通常的3向文件級合并文本文件。沖突區域標有沖突標記`<<<<<<<`,`=======`和`>>>>>>>`。分支的版本顯示在`=======`標記之前,合并分支的版本顯示在`=======`標記之后。
```
binary
```
保留工作樹中的分支版本,但保留路徑處于沖突狀態以供用戶進行整理。
```
union
```
對文本文件運行3向文件級別合并,但從兩個版本中獲取行,而不是留下沖突標記。這往往會以隨機順序在結果文件中保留添加的行,用戶應驗證結果。如果您不理解其含義,請不要使用此功能。
#### 定義自定義合并驅動程序
合并驅動程序的定義在`.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`命名的文件中,如果它設法干凈地合并它們,則退出為零狀態,如果存在沖突則為非零。
`merge.*.recursive`變量指定當共同驅動器被調用以在共同祖先之間進行內部合并時,要使用的其他合并驅動程序。如果未指定,則驅動程序本身用于內部合并和最終合并。
合并驅動程序可以通過占位符`%P`了解合并結果的路徑名。
#### `conflict-marker-size`
此屬性控制沖突合并期間留在工作樹文件中的沖突標記的長度。僅將值設置為正整數具有任何有意義的效果。
例如,`.gitattributes`中的這一行可用于告訴合并機器在合并文件`Documentation/git-merge.txt`導致沖突時留下更長的時間(而不是通常的7個字符長)沖突標記。
```
Documentation/git-merge.txt conflict-marker-size=32
```
### 檢查空白錯誤
#### `whitespace`
`core.whitespace`配置變量允許您定義 _diff_ 和_適用_應該考慮項目中所有路徑的空白錯誤(參見 [git-config [1]](https://git-scm.com/docs/git-config) )。此屬性為每個路徑提供更精細的控制。
```
Set
```
注意Git已知的所有類型的潛在空白錯誤。標簽寬度取自`core.whitespace`配置變量的值。
```
Unset
```
不要注意任何錯誤。
```
Unspecified
```
使用`core.whitespace`配置變量的值來確定要注意的錯誤。
```
String
```
以與`core.whitespace`配置變量相同的格式指定逗號單獨的常見空白問題列表。
### 創建檔案
#### `export-ignore`
具有`export-ignore`屬性的文件和目錄不會添加到存檔文件中。
#### `export-subst`
如果為文件設置了屬性`export-subst`,那么在將此文件添加到存檔時,Git將展開多個占位符。擴展取決于提交ID的可用性,即,如果 [git-archive [1]](https://git-scm.com/docs/git-archive) 已被賦予樹而不是提交或標記,則不會進行替換。占位符與 [git-log [1]](https://git-scm.com/docs/git-log) 的選項`--pretty=format:`的占位符相同,只是它們需要像這樣包裝:文件中的`$Format:PLACEHOLDERS$`。例如。字符串`$Format:%H$`將被提交哈希替換。
### 包裝物
#### `delta`
對于屬性`delta`設置為false的路徑,不會嘗試對blob進行增量壓縮。
### 在GUI工具中查看文件
#### `encoding`
此屬性的值指定GUI工具應使用的字符編碼(例如 [gitk [1]](https://git-scm.com/docs/gitk) 和 [git-gui [1]](https://git-scm.com/docs/git-gui) )以顯示相關文件的內容。請注意,由于性能方面的考慮, [gitk [1]](https://git-scm.com/docs/gitk) 不使用此屬性,除非您在其選項中手動啟用每個文件編碼。
如果未設置此屬性或具有無效值,則使用`gui.encoding`配置變量的值(參見 [git-config [1]](https://git-scm.com/docs/git-config) )。
## 使用宏觀屬性
您不希望應用任何行尾轉換,也不希望為您跟蹤的任何二進制文件生成文本差異。您需要指定例如
```
*.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`的屬性計算如下:
1. 通過檢查`t/.gitattributes`(與相關路徑在同一目錄中),Git發現第一行匹配。 `merge`屬性已設置。它還發現第二行匹配,并且未設置屬性`foo`和`bar`。
2. 然后它檢查`.gitattributes`(在父目錄中),并發現第一行匹配,但`t/.gitattributes`文件已經決定了如何將`merge`,`foo`和`bar`屬性賦予此路徑,所以它使`foo`和`bar`未設置。屬性`baz`已設置。
3. 最后它檢查了`$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
```
## 也可以看看
[git-check-attr [1]](https://git-scm.com/docs/git-check-attr) 。
## GIT
部分 [git [1]](https://git-scm.com/docs/git) 套件
- git
- git-config
- git-help
- git-init
- git-clone
- git-add
- git-status
- git-diff
- git-commit
- git-reset
- git-rm
- git-mv
- git-branch
- git-checkout
- git-merge
- git-mergetool
- git-log
- git-stash
- git-tag
- git-worktree
- git-fetch
- git-pull
- git-push
- git-remote
- git-submodule
- git-show
- git-log
- git-shortlog
- git-describe
- git-apply
- git-cherry-pick
- git-rebase
- git-revert
- git-bisect
- git-blame
- git-grep
- gitattributes
- giteveryday
- gitglossary
- githooks
- gitignore
- gitmodules
- gitrevisions
- gittutorial
- gitworkflows
- git-am
- git-format-patch
- git-send-email
- git-request-pull
- git-svn
- git-fast-import
- git-clean
- git-gc
- git-fsck
- git-reflog
- git-filter-branch
- git-instaweb
- git-archive
- git-bundle
- git-daemon
- git-update-server-info
- git-cat-file
- git-check-ignore
- git-checkout-index
- git-commit-tree
- git-count-objects
- git-diff-index
- git-for-each-ref
- git-hash-object
- git-ls-files
- git-merge-base
- git-read-tree
- git-rev-list
- git-rev-parse
- git-show-ref
- git-symbolic-ref
- git-update-index
- git-update-ref
- git-verify-pack
- git-write-tree