自定義 Git - Git 屬性



Git 屬性

我們可以使用**Git 屬性**來設定 Git 對倉庫中特定檔案或資料夾的行為。

對於臨時或本地設定,我們在**.git/info/attributes**檔案中或**.gitattributes**檔案中宣告這些屬性,後者通常位於根目錄。

  • 使用屬性,我們可以自定義合併技術來解決衝突。

  • 在進行合併和 diff 時,可以對非文字檔案進行不同的處理。

  • 為了確保 Git 按照專案的特定要求執行,我們還可以實現過濾器,在提交或檢出之前評估檔案內容。

**.gitattributes**檔案應放在倉庫的根目錄。您也可以在子目錄中建立它,以將規則應用於專案的特定部分。

二進位制檔案

Git 屬性允許我們識別二進位制檔案,併為 Git 提供關於如何處理它們的指令。

這些屬性幫助 Git 對它可能無法自動識別的二進位制檔案應用某些準則。

  • 雖然有些二進位制檔案可以進行 diff,但有些機器生成的文字檔案可能不行。

  • 透過指定這些屬性,我們確保 Git 正確處理每種型別的檔案。

  • 現在,Git 更有效地處理和比較我們倉庫中的各種檔案型別。

識別二進位制檔案

儘管某些檔案看起來像文字,但由於其預期用途,它們應被視為二進位制資料。

例如,Xcode 專案中名為**.pbxproj**的 UTF-8 文字檔案充當小型資料庫。

  • 由於其性質,這些檔案不適合合併或 diff。

  • 即使它們是基於文字的,其目的也不是人工編輯,而是機器使用。

  • 為了防止合併和 diff 出現問題,我們需要設定 Git 以使其將這些檔案作為二進位制檔案處理。

要指示 Git 將所有**.pbxproj**檔案作為二進位制資料處理,請在我們的**.gitattributes**檔案中包含**/*.pbxproj binary**。

使用**git show**或**git diff**時,此設定會阻止 Git 轉換 CRLF 行尾,並阻止它為某些檔案的更改建立 diff。

*.pbxproj binary

二進位制檔案的 Diff

Git 屬性可用於透過將二進位制資料轉換為文字格式進行比較來管理二進位制檔案的 diff。

此方法在 Git 中非常適合管理二進位制檔案,例如 Microsoft Word 文件。

  • 透過配置 Git 以轉換二進位制資料,我們可以有效地跟蹤更改並將版本控制應用於這些檔案。

  • 使用此方法,即使是原始二進位制檔案,我們也可以在 Git 中對二進位制檔案使用 diff 工具。

  • 透過正確的配置,我們可以更有效地管理和版本控制 Git 倉庫中的二進位制檔案。

對二進位制檔案執行**git diff**的結果表明,**report.docx**的兩個版本有所不同,但 Git 只顯示檔案已更改,而不是實際內容。

必須配置 Git 屬性才能直接在編輯器中比較二進位制檔案(例如 docx)的版本。

例如,我們可以實現自定義過濾器來執行比較**.docx**檔案的任務。以下是配置方法:

在**.gitattributes**檔案中寫入以下內容:

*.docx diff=word

此行指示 Git 使用**word**過濾器顯示**.docx**檔案的 diff。

  • 為了將 Word 檔案轉換為可讀格式,需要設定**word**過濾器。

  • 例如,我們可以配置 Git 使用**docx2text**或其他工具將 docx 轉換為文字格式,以便可以進行 diff。

  • 透過此配置,可以透過將 docx 檔案轉換為文字檔案進行 diff 分析,從而輕鬆比較 docx 版本。

使用 Git 對**.docx**檔案進行 diff

從 SourceForge 下載**docx2txt**並按照設定指南進行安裝。

建立包裝器指令碼:將以下內容鍵入名為**docx2txt**的指令碼中:

#!/bin/bash
docx2txt.pl "$1" -

將此指令碼放在系統 PATH 中的目錄。

**使指令碼可執行**:要為指令碼提供可執行許可權,請執行以下命令:

chmod a+x /path/to/docx2txt

**配置 Git**:在 Git 的配置中設定 textconv 過濾器,以指示 Git 對.docx 檔案使用該指令碼。

git config diff.word.textconv docx2txt
  • Git 已設定為對涉及**.docx**檔案的 diff 使用**docx2txt**工具。

  • Git 使用**word**過濾器將**.docx**檔案轉換為文字。

  • 因此,Git 現在可以生成可讀的基於文字的 Word 文件 diff。

可以透過提取和比較影像資訊(而不是實際影像內容)來解決 diff 影像檔案的問題。

  • 我們可以使用諸如**exiftool**之類的工具將影像的 EXIF 元資料轉換為文字格式。

  • 現在,Git 可以根據文字元資料的更改進行 diff,從而提供有關對影像檔案所做任何更改的資訊。

要設定 Git 以比較影像的元資料以進行 diff:

修改**.gitattributes**:在**.gitattributes**檔案中包含以下行,以指示**.png**檔案需要使用**exif**過濾器:

*.png diff=exif

**設定 Git**:使用此命令配置 Git 以對**exif**過濾器使用 exiftool:

git config diff.exif.textconv exiftool

透過此配置,Git 將能夠使用**exiftool**將影像元資料轉換為文字,從而基於元資料的更改啟用有意義的 diff。

當我們替換影像並執行**git diff**時,Git 會顯示使用**exiftool**從影像檔案提取的元資料的 diff。

這不會直接比較影像內容,而是透過顯示影像元資料的變化(包括檔案大小、修改日期和尺寸)來提供更改的文字表示。

關鍵字擴充套件

**SVN**或**CVS**的一個特定功能,它將元資料(例如版本號或修訂 ID)嵌入檔案中,稱為**關鍵字擴充套件**。

Git 使用校驗和跟蹤檔案更改,從而防止提交後更新檔案,這使得傳統的關鍵字擴充套件不切實際。

  • 相反,Git 允許在檢出期間將元資料新增到檔案,然後在提交之前將其刪除。

  • 此方法使用 Git 屬性來控制何時以及如何新增和刪除元資料。

  • Git 屬性提供兩種處理關鍵字擴充套件的方法:使用內建演算法或建立自定義過濾器。

使用 Git 屬性,我們可以自動將檔案的(或 blob 的)SHA-1 校驗和放入指定的欄位(例如**$Id$**)。

  • 每次檢出分支時,都會在此欄位中更新檔案的校驗和。

  • 檔案的內容由校驗和表示,而不是它所屬的提交。

要允許自動將 SHA-1 校驗和附加到檔案,請執行以下步驟:

在名為**.gitattributes**的檔案中包含以下行:

*.txt ident

建立一個包含對**$Id$**的引用的測試檔案。

echo '$Id$' > test.txt

刪除測試檔案,然後再次檢出。

rm test.txt
git checkout -- test.txt

檢視修改後的檔案,檢視注入的 SHA-1 校驗和。

cat test.txt
$Id: 42812b7653c7b88933f8a9d6cad0ca16714b9bb3 $

由於它缺乏有關檔案年齡的資訊,因此 Git 的關鍵字替換獲得的 SHA-1 校驗和結果本身並不十分有用。

與 CVS 或 Subversion(可能包含日期戳)相比,Git 的 SHA-1 是隨機的,不會顯示檔案的年齡。

git attributes

但是,Git 允許我們設計獨特的**smudge**和**clean**過濾器來處理檢出和提交期間的檔案。

在檢出或暫存檔案之前,可以在**.gitattributes**檔案中設定這些過濾器以執行不同的操作。

git attributes

示例提交訊息演示瞭如何在提交之前使用 indent 程式自動格式化 C 原始碼。

為此,請將後續行新增到我們的**.gitattributes**檔案中:

*.c filter=indent

配置以下命令以指定 Git 的**indent**過濾器的行為:

指定應使用 indent 程式清理檔案(在暫存之前)。

git config --global filter.indent.clean indent

在檢出之前,設定 cat 命令用於塗抹檔案。

git config --global filter.indent.smudge cat

透過此配置,Git 將在檢出 C 原始碼檔案之前使用**cat**程式(什麼也不做),並且在暫存它們之前將透過**indent**程式執行它們。

這保證了在提交之前,所有 C 檔案都使用**indent**進行了格式化。

匯出我們的倉庫

Git 屬性使我們能夠管理專案存檔期間進行的檔案處理,允許我們建立包含附加元資料、過濾和轉換的自定義匯出。

  • 我們可以使用**export-ignore**屬性指定哪些檔案或目錄不應包含在存檔中。

  • 我們可以使用它來保留倉庫中我們在匯出的存檔中不需要的目錄或檔案。

  • 要確保某些檔案或目錄不包含在存檔中,請在其上設定**export-ignore**屬性。

  • 透過保留倉庫中的重要檔案並刪除不相關的檔案,這有助於管理匯出存檔的內容。

如果我們在 docs/ 目錄中有一些內部文件,我們不希望將其包含在專案的 zip 存檔中,我們可以將以下行新增到我們的 Git 屬性檔案中:

docs/ export-ignore

當我們使用 git archive 生成專案的 zip 檔案時,**docs/**目錄將不包含在存檔中。

export-subst

我們可以使用**export-subst**屬性在匯出期間將 Git 的日誌格式和關鍵字擴充套件應用於特定檔案部分。

  • 它可以將動態資料(例如版本號或提交詳細資訊)替換為檔案中的佔位符。

  • 它保證我們匯出的檔案中的元資料是最新的,因為它來自儲存庫。

要在建立存檔時自動將元資料注入名為 LAST_COMMIT 的檔案,請按照以下步驟操作

配置 **.gitattributes**

echo 'LAST_COMMIT export-subst' > .gitattributes

建立包含元資料佔位符的 **LAST_COMMIT** 檔案

echo 'Last commit date: $Format:%cd by %aN$' > LAST_COMMIT

新增並提交更改

git add LAST_COMMIT .gitattributes
git commit -am 'Add LAST_COMMIT file for archives'

建立存檔並檢查內容

git archive HEAD | tar xCf ../deployment-testing -
cat ../deployment-testing/LAST_COMMIT

存檔中的 **LAST_COMMIT** 檔案將顯示元資料,例如上次提交的日期和作者。

建立存檔時,我們可以使用 export-subst 屬性在檔案中包含格式化的提交元資料。

合併策略

Git 屬性允許我們在合併時對特定檔案使用多種合併演算法。

  • 發生衝突時,我們可以設定 Git 合併更改,或自動偏向我們的檔案版本而不是其他版本。

  • 這保證了在合併期間,關鍵檔案或特殊檔案不會發生更改。

  • 透過定義這些合併方法,我們可以控制在複雜的合併場景中如何處理檔案。

我們可以這樣設定屬性:

strings.json merge=ours

然後,使用以下命令配置虛擬的 **ours** 合併策略:

git config --global merge.ours.driver true

當我們從另一個分支執行合併時,我們將避免與 **strings.json** 發生合併衝突。

相反,我們會看到這樣的輸出:

$ git merge feature-branch
Auto-merging strings.json
Merge made by recursive.

在這種情況下,**strings.json** 將保持其原始狀態,不會發生合併更改。

使用 Git 屬性的優勢

以下是使用 **Git 屬性**的一些優勢:

  • 它確保在各種環境和作業系統中一致地處理檔案。

  • 對於特定檔案,它有助於管理合併衝突和差異。

  • 它為檔案處理定義了清晰而精確的規則,從而使協作更加輕鬆有效。

廣告