日本語 ▾ トピック ▾ 最新バージョン ▾ gitattributes は2.49.0で最終更新されました

名前

gitattributes - パスごとの属性の定義

概要

$GIT_DIR/info/attributes, .gitattributes

説明

gitattributes ファイルは、パス名に属性を与える単純なテキストファイルです。

gitattributes ファイルの各行は、次の形式です。

pattern attr1 attr2 ...

つまり、パターンに続いて属性リストが空白で区切られて並びます。先頭と末尾の空白は無視されます。# で始まる行は無視されます。二重引用符で始まるパターンはC言語スタイルで引用されます。パターンが問題のパスに一致すると、行にリストされた属性がパスに与えられます。

各属性は、特定のパスに対して以下のいずれかの状態になります。

設定済み (Set)

パスは特殊値「true」の属性を持ちます。これは、属性リストに属性の名前のみを記述することで指定されます。

未設定 (Unset)

パスは特殊値「false」の属性を持ちます。これは、属性リストで属性の名前の前にダッシュ-を付けて記述することで指定されます。

値に設定済み (Set to a value)

パスは指定された文字列値の属性を持ちます。これは、属性リストで属性の名前の後に等号=とその値を付けて記述することで指定されます。

未指定 (Unspecified)

どのパターンもパスに一致せず、パスが属性を持つか持たないかを何も示さない場合、そのパスの属性は未指定であると言われます。

複数のパターンがパスに一致する場合、後続の行が以前の行を上書きします。この上書きは属性ごとに行われます。

パターンがパスに一致する規則は、.gitignore ファイル (参照: gitignore[5]) と同じですが、いくつかの例外があります。

  • 否定パターンは禁止されています。

  • ディレクトリに一致するパターンは、そのディレクトリ内のパスに再帰的に一致しません(したがって、属性ファイルで末尾のスラッシュ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ファイルに配置する必要があります。

時として、パスの属性設定を未指定状態に上書きする必要がある場合があります。これは、属性の名前の前に感嘆符!を付けて記述することで可能です。

予約済み BUILTIN_* 属性

builtin_* は、組み込み属性値のための予約された名前空間です。この名前空間の下でユーザーが定義した属性は無視され、警告がトリガーされます。

builtin_objectmode

この属性は、ファイルのビットモード (40000, 120000, 160000, 100755, 100644) でファイルをフィルタリングするためのものです。例: :(attr:builtin_objectmode=160000)。これらの値はgit check-attr builtin_objectmode -- <file>で確認することもできます。オブジェクトがインデックスにない場合、git check-attr --cachedは未指定を返します。

効果

Gitの特定の操作は、パスに特定の属性を割り当てることで影響を受けることがあります。現在、以下の操作が属性を認識します。

チェックアウトとチェックイン

これらの属性は、git switchgit checkoutgit mergeなどのコマンドが実行される際に、リポジトリに保存された内容がどのようにワーキングツリーファイルにコピーされるかに影響します。また、git addおよびgit commitによってワーキングツリーで準備した内容をGitがリポジトリにどのように保存するかにも影響します。

text

この属性はパスをテキストファイルとしてマークし、行末変換を有効にします。一致するファイルがインデックスに追加されると、ファイルの行末はインデックスでLFに正規化されます。逆に、ファイルがインデックスから作業ディレクトリにコピーされると、eol属性、Gitの設定、およびプラットフォームに応じて、行末がLFからCRLFに変換される場合があります(以下のeolの説明を参照)。

設定済み (Set)

パスにtext属性を設定すると、上述の通り、チェックインおよびチェックアウト時に行末変換が有効になります。ファイルがCRLF行末でGitに以前追加されていたとしても、ファイルがチェックインされるたびに行末はインデックスでLFに正規化されます。

未設定 (Unset)

パスのtext属性を未設定にすると、チェックインまたはチェックアウト時にGitが行末変換を試みないように指示します。

文字列値 "auto" に設定済み (Set to string value "auto")

textが「auto」に設定されている場合、Gitはファイルがテキストかバイナリかを自動で判断します。テキストファイルであり、CRLF行末でGitにまだ存在しないファイルの場合、上記のとおりチェックインおよびチェックアウト時に行末が変換されます。それ以外の場合、チェックインまたはチェックアウト時に変換は行われません。

未指定 (Unspecified)

text属性が未指定の場合、Gitはcore.autocrlf設定変数を使用して、ファイルを変換すべきかどうかを判断します。

その他の値は、Gitがtextが未指定のままになっているかのように動作させます。

eol

この属性は、パスをチェックアウトする際に、ワーキングツリーで特定の行末スタイルを使用するようにマークします。これは、textまたはtext=autoが設定されている場合にのみ効果があります(上記参照)が、eolを指定すると、textが未指定のままであった場合に自動的にtextを設定します。

文字列値 "crlf" に設定済み (Set to string value "crlf")

この設定は、ファイルがチェックアウトされる際に、ワーキングディレクトリ内のファイルの行末をCRLFに変換します。

文字列値 "lf" に設定済み (Set to string value "lf")

この設定は、ファイルがチェックアウトされる際に、ワーキングディレクトリの行末をインデックス内と同じにします。

未指定 (Unspecified)

ファイルのeol属性が未指定の場合、ワーキングディレクトリ内の行末はcore.autocrlfまたはcore.eol設定変数によって決定されます(git-config[1]のそれらのオプションの定義を参照)。textが設定されているが、これらの変数のどちらも設定されていない場合、Windowsではデフォルトでeol=crlf、その他のすべてのプラットフォームではeol=lfとなります。

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の設定に対して変換が可逆的かどうかを検証します。「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ウェブフロントエンドは、デフォルトではこれらのファイルの内容を視覚化しません。

このような場合、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をサポートしないクライアントは、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]を参照)。SHIFT-JIS(日本語文字セット)はUTF-8とのラウンドトリップ問題があることが知られており、デフォルトでチェックされます。

  • コンテンツの再エンコードにはリソースが必要であり、特定のGit操作(例: git checkoutgit add)を遅くする可能性があります。

working-tree-encoding属性は、ファイルをUTF-8エンコーディングで保存できない場合、かつGitがコンテンツをテキストとして処理できるようにしたい場合にのみ使用してください。

例として、もしあなたの*.ps1ファイルがバイトオーダーマーク(BOM)付きのUTF-16エンコードで、Gitにプラットフォームに基づいて自動行末変換を実行させたい場合、以下の属性を使用します。

*.ps1		text working-tree-encoding=UTF-16

BOMなしでUTF-16リトルエンディアンでエンコードされた*.ps1ファイルがあり、GitがワーキングディレクトリでWindowsの行末を使用するようにしたい場合、以下の属性を使用します(BOM付きのUTF-16リトルエンディアンが必要な場合は、UTF-16LEの代わりにUTF-16LE-BOMを使用してください)。あいまいさを避けるため、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文字の16進数BLOBオブジェクト名が続き、最後にドル記号$が続きます。作業ツリーファイル内で$Id:で始まり$で終わるバイトシーケンスは、チェックイン時に$Id$に置き換えられます。

filter

filter属性は、設定で指定されたフィルタードライバーの名前である文字列値に設定できます。

フィルタードライバーはcleanコマンドとsmudgeコマンドから成り、どちらか一方を未指定にすることができます。チェックアウト時、smudgeコマンドが指定されている場合、そのコマンドは標準入力からBLOBオブジェクトを受け取り、その標準出力がワークツリーファイルの更新に使用されます。同様に、cleanコマンドはチェックイン時にワークツリーファイルの内容を変換するために使用されます。デフォルトでは、これらのコマンドは単一のBLOBのみを処理し、終了します。もし、cleanおよび/またはsmudgeフィルターの代わりに長時間実行されるprocessフィルターが使用される場合、Gitは単一のGitコマンドの全ライフサイクル(例:git add --all)の間、単一のフィルターコマンド呼び出しで全てのBLOBを処理できます。もし長時間実行されるprocessフィルターが設定されている場合、それは常に設定された単一BLOBフィルターよりも優先されます。processフィルターとの通信に使用されるプロトコルの説明については、以下のセクションを参照してください。

コンテンツフィルタリングの用途の一つは、コンテンツをプラットフォーム、ファイルシステム、およびユーザーにとってより便利な形式に調整することです。この操作モードでは、「より便利」というキーワードが重要であり、「使用不能なものを使用可能にする」ことではありません。言い換えれば、意図としては、誰かがフィルタードライバーの定義を解除したり、適切なフィルタープログラムを持っていなかったりしても、プロジェクトは依然として使用可能であるべきだということです。

コンテンツフィルタリングのもう一つの用途は、リポジトリで直接使用できないコンテンツ(例:Gitの外部に保存された実際のコンテンツを参照するUUID、または暗号化されたコンテンツ)を保存し、チェックアウト時に使用可能な形式に変換することです(例:外部コンテンツのダウンロード、または暗号化されたコンテンツの復号化)。

これら2つのフィルターは異なる動作をし、デフォルトでは前者の、内容をより便利な形式に調整するフィルターとみなされます。設定にフィルタードライバーの定義がない場合、またはゼロ以外のステータスで終了するフィルタードライバーは、エラーではなく、フィルターを何もしないパススルーにします。

フィルターがそれ自体では使用できないコンテンツを使用可能なコンテンツに変えることを、filter.<driver>.required設定変数をtrueに設定することで宣言できます。

注意:クリーンフィルターを変更するたびに、リポジトリを再正規化する必要があります:$ git add --renormalize .

たとえば、.gitattributesでは、パスにfilter属性を割り当てます。

*.c	filter=indent

次に、.git/configファイルで「filter.indent.clean」および「filter.indent.smudge」設定を定義し、ソースファイルがチェックインされるとき(「clean」が実行されるとき)およびチェックアウトされるとき(コマンドが「cat」であるため変更されないとき)にCプログラムの内容を変更するコマンドのペアを指定します。

[filter "indent"]
	clean = indent
	smudge = cat

最良の結果を得るには、cleanは2回実行されても出力をさらに変更しないようにし(「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はフラッシュパケットで終了する「キー=値」のペアのリストを送信します。このリストには、少なくともフィルターコマンド(サポートされる機能に基づく)と、リポジトリのルートに対するフィルター対象ファイルのパス名が含まれます。フラッシュパケットの直後、Gitは0個以上のpkt-lineパケットで分割されたコンテンツと、コンテンツを終了させるためのフラッシュパケットを送信します。フィルターはコンテンツと最終的なフラッシュパケットを受信する前に、いかなる応答も送信してはならないことに注意してください。また、「キー=値」ペアの「値」は「=」文字を含むことができますが、キーはこの文字を絶対に含みません。

packet:          git> command=smudge
packet:          git> pathname=path/testfile.dat
packet:          git> 0000
packet:          git> CONTENT
packet:          git> 0000

フィルターは、フラッシュパケットで終了する「キー=値」のペアのリストで応答することが期待されます。フィルターが問題を経験しない場合、リストには「成功」ステータスが含まれている必要があります。これらのパケットの直後、フィルターは0個以上のpkt-lineパケットでコンテンツを送信し、最後にフラッシュパケットを送信することが期待されます。最後に、フラッシュパケットで終了する2番目の「キー=値」のペアのリストが期待されます。フィルターは2番目のリストでステータスを変更したり、空のリストでステータスをそのまま維持したりできます。空のリストでもフラッシュパケットで終了する必要があることに注意してください。

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は、「error」/「abort」ステータスが設定されている場合でも、フィルタープロセスを停止したり再起動したりしません。ただし、Gitはfilter.<driver>.requiredフラグに従って終了コードを設定し、filter.<driver>.clean / filter.<driver>.smudgeメカニズムの動作を模倣します。

通信中にフィルターが終了したり、プロトコルに従わなかったりした場合、Gitはフィルタープロセスを停止し、次に処理する必要があるファイルで再起動します。filter.<driver>.requiredフラグによっては、Gitはそれをエラーと解釈します。

遅延

フィルターが「delay」機能をサポートしている場合、Gitはフィルターコマンドとパス名の後に「can-delay」フラグを送信できます。このフラグは、フィルターが現在のBLOBのフィルタリングを遅延できる(例:ネットワーク遅延を補償するため)ことを示し、コンテンツなしで「delayed」ステータスとフラッシュパケットで応答します。

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を表すパス名のリストを返すことが期待されます。リストはフラッシュパケットで終了し、それに続く「成功」ステータスもフラッシュパケットで終了しなければなりません。遅延されたパスのBLOBがまだ利用可能でない場合、フィルターは少なくとも1つのBLOBが利用可能になるまで応答をブロックすることが期待されます。フィルターは空のリストを送信することで、遅延されたBLOBがもうないとGitに伝えることができます。フィルターが空のリストで応答するとすぐに、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を再度要求します。これらの要求にはパス名と空のコンテンツセクションが含まれます。フィルターは上記で説明した通常の方法でsmudgedされたコンテンツで応答することが期待されます。

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と一緒に使用することはできません。これら2つは後者とは異なるプロセス間通信プロトコルを使用するためです。

チェックイン/チェックアウト属性間の相互作用

チェックインのコードパスでは、ワークツリーファイルはまずfilterドライバー(指定され、対応するドライバーが定義されていれば)で変換され、次にident(指定されていれば)で処理され、最後にtext(再度、指定され、適用可能であれば)で処理されます。

チェックアウトのコードパスでは、BLOBの内容はまずtextで変換され、次にidentで変換されてfilterに供給されます。

異なるチェックイン/チェックアウト属性を持つブランチのマージ

クリーン/スマッジフィルターやtext/eol/ident属性の追加など、ファイルの正規リポジトリ形式を変更する属性をファイルに追加した場合、属性が適用されていないものをマージすると、通常はマージ競合が発生します。

これらの不要なマージ競合を防ぐため、merge.renormalize設定変数を設定することで、Gitに3-wayコンテンツマージが必要な各ファイルの3つのステージすべてについて仮想チェックアウトとチェックインを実行するように指示できます。これにより、変換されたファイルが未変換のファイルとマージされる際に、チェックイン変換によって引き起こされる偽のマージ競合が防止されます。

「smudge→clean」がすでにsmudgedされたファイルでも「clean」と同じ出力を生成する限り、この戦略はすべてのフィルター関連の競合を自動的に解決します。このように動作しないフィルターは、手動で解決する必要がある追加のマージ競合を引き起こす可能性があります。

差分テキストの生成

diff

属性diffは、Gitが特定のファイルの差分を生成する方法に影響を与えます。パスに対してテキストパッチを生成するか、パスをバイナリファイルとして扱うかをGitに指示できます。また、Hunkヘッダー@@ -k,l +n,m @@行に表示される行に影響を与えたり、差分を生成するために外部コマンドを使用するようにGitに指示したり、差分を生成する前にバイナリファイルをテキスト形式に変換するようにGitに要求したりできます。

設定済み (Set)

diff属性が設定されたパスは、NULのような通常テキストファイルには出現しないバイト値を含んでいても、テキストとして扱われます。

未設定 (Unset)

diff属性が未設定のパスは、Binary files differ(または、バイナリパッチが有効な場合はバイナリパッチ)を生成します。

未指定 (Unspecified)

diff属性が未指定のパスは、まずその内容が検査され、テキストのように見え、かつcore.bigFileThresholdより小さい場合はテキストとして扱われます。それ以外の場合はBinary files differを生成します。

文字列 (String)

指定されたdiffドライバを使用してdiffが表示されます。各ドライバは、次のセクションで説明するように、1つまたは複数のオプションを指定できます。diffドライバ「foo」のオプションは、Git設定ファイルの「diff.foo」セクションの設定変数によって定義されます。

外部diffドライバーの定義

diffドライバーの定義はgitattributesファイルではなくgitconfigで行うため、厳密に言えばこのマニュアルページで話すのは場違いです。しかし…​

外部diffドライバーjcdiffを定義するには、$GIT_DIR/configファイル(または$HOME/.gitconfigファイル)に次のようなセクションを追加します。

[diff "jcdiff"]
	command = j-c-diff

Gitがdiff属性がjcdiffに設定されたパスの差分を表示する必要がある場合、上記の構成で指定されたコマンド、つまりj-c-diffを、GIT_EXTERNAL_DIFFプログラムが呼び出されるのと同様に7つのパラメータで呼び出します。詳細はgit[1]を参照してください。

プログラムが特定の変更を無視できる場合(git diff --ignore-space-changeと同様)、オプションtrustExitCodeもtrueに設定します。この場合、重要な変更が見つかった場合は終了コード1を、見つからない場合は0を返すことが期待されます。

内部diffアルゴリズムの設定

diffアルゴリズムはdiff.algorithm設定キーを介して設定できますが、パスごとにdiffアルゴリズムを設定すると便利な場合があります。たとえば、.jsonファイルにはminimal diffアルゴリズムを、.cファイルにはhistogramを、といったように、毎回コマンドラインでアルゴリズムを渡す必要がありません。

まず、.gitattributesで、パスのdiff属性を割り当てます。

*.json diff=<name>

次に、"diff.<name>.algorithm" の設定を定義して、myers, patience, minimal, histogramの中から選択したdiffアルゴリズムを指定します。

[diff "<name>"]
  algorithm = histogram

このdiffアルゴリズムは、git-diff(1) や git-show(1) のようなユーザー向けdiff出力に適用され、--stat出力にも使用されます。マージ機構はこの方法で設定されたdiffアルゴリズムを使用しません。

diff=<name>属性を持つパスに対してdiff.<name>.commandが定義されている場合、それは外部diffドライバーとして実行され(上記参照)、diff.<name>.algorithmを追加しても効果はありません。アルゴリズムが外部diffドライバーに渡されないためです。

カスタムhunkヘッダーの定義

テキスト差分出力の各変更グループ(「hunk」と呼ばれる)は、次の形式の行でプレフィックスされます。

@@ -k,l +n,m @@ TEXT

これはhunkヘッダーと呼ばれます。「TEXT」部分は、デフォルトではアルファベット、アンダースコア、またはドル記号で始まる行です。これはGNU diff -pの出力が使用するものと一致します。しかし、このデフォルトの選択は一部のコンテンツには適しておらず、カスタムパターンを使用して選択を行うことができます。

まず、.gitattributesで、パスのdiff属性を割り当てます。

*.tex	diff=tex

次に、「diff.tex.xfuncname」設定を定義し、hunkヘッダー「TEXT」として表示させたい行に一致する正規表現を指定します。$GIT_DIR/configファイル(または$HOME/.gitconfigファイル)に次のようなセクションを追加します。

[diff "tex"]
	xfuncname = "^(\\\\(sub)*section\\{.*)$"

注意:設定ファイルのパーサーによってバックスラッシュが1レベル消費されるため、バックスラッシュを2重にする必要があります。上記のパターンは、バックスラッシュで始まり、0個以上のsubの後にsection、さらにオープンブレースが続き、行末まで続く行を選択します。

これを容易にするためのいくつかの組み込みパターンがあり、texはそのうちの一つなので、設定ファイルに上記を記述する必要はありません(.gitattributesを介して属性メカニズムでこれを有効にする必要はあります)。以下の組み込みパターンが利用可能です。

  • ada Ada言語のソースコードに適しています。

  • bash Bourne-Again SHell言語のソースコードに適しています。POSIXシェル関数定義のスーパーセットをカバーします。

  • 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ドキュメントのソースコードに適しています。

ワード差分のカスタマイズ

git diff --word-diffが1行内で単語を分割するために使用するルールは、"diff.*.wordRegex" 設定変数で適切な正規表現を指定することでカスタマイズできます。例えば、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 diffgit 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」は上記の例のようにdiffドライバーの名前)で手動でキャッシュを削除できます。

textconvと外部diffの選択

リポジトリ内のバイナリまたは特殊な形式のBLOB間の違いを表示したい場合、外部diffコマンドを使用するか、textconvを使用してdiff可能なテキスト形式に変換するかを選択できます。どちらの方法を選択するかは、状況によって異なります。

外部diffコマンドを使用する利点は柔軟性です。行指向の変更を見つけることに縛られず、出力が統合diffに似ている必要もありません。データ形式に最適な方法で変更を特定し報告することができます。

一方、textconvははるかに制限されています。データを行指向のテキスト形式に変換する機能を提供し、Gitは通常のdiffツールを使用して出力を生成します。この方法を選択する利点はいくつかあります。

  1. 使いやすさ。バイナリからテキストへの変換を記述する方が、独自のdiffを実行するよりもはるかに単純であることが多いです。多くの場合、既存のプログラムをtextconvフィルターとして使用できます(例:exif、odt2txt)。

  2. Git diff機能。変換ステップ自体のみを実行することで、色付け、ワードdiff、マージのための結合diffなど、Gitの多くのdiff機能を依然として利用できます。

  3. キャッシュ。Textconvキャッシュは、git log -pを実行してトリガーする可能性のある繰り返しのdiffを高速化できます。

ファイルをバイナリとしてマークする

Gitは通常、内容の冒頭を調べて、BLOBがテキストデータかバイナリデータかを正しく推測します。しかし、時にはその決定を上書きしたい場合があります。BLOBがファイルの後方でバイナリデータを含んでいるため、または内容が技術的にはテキスト文字で構成されているものの、人間には不透明であるためです。たとえば、多くのPostScriptファイルはASCII文字のみを含んでいますが、ノイズが多く無意味な差分を生成します。

ファイルをバイナリとしてマークする最も簡単な方法は、.gitattributesファイルでdiff属性を未設定にすることです。

*.ps -diff

これにより、Gitは通常の差分ではなく、Binary files differ(またはバイナリパッチが有効な場合はバイナリパッチ)を生成します。

ただし、他のdiffドライバ属性も指定したい場合があります。たとえば、PostScriptファイルを人間が見るためにASCII表現に変換するためにtextconvを使用したいが、それ以外はバイナリファイルとして扱いたい場合です。-diffdiff=psの両方の属性を同時に指定することはできません。この解決策は、diff.*.binary設定オプションを使用することです。

[diff "ps"]
  textconv = ps2ascii
  binary = true

三方マージの実行

merge

merge属性は、git mergeや、git revertgit cherry-pickなどの他のコマンド中にファイルレベルのマージが必要になったときに、ファイルの3つのバージョンがどのようにマージされるかに影響します。

設定済み (Set)

組み込みの3-wayマージドライバは、RCSスイートのmergeコマンドと同様の方法でコンテンツをマージするために使用されます。これは通常のテキストファイルに適しています。

未設定 (Unset)

現在のブランチのバージョンを暫定的なマージ結果とし、マージに競合があることを宣言します。これは、明確なマージセマンティクスを持たないバイナリファイルに適しています。

未指定 (Unspecified)

デフォルトでは、merge属性が設定されている場合と同じ組み込みの3-wayマージドライバが使用されます。ただし、merge.default設定変数は、merge属性が未指定のパスで使用される異なるマージドライバを指定できます。

文字列 (String)

指定されたカスタムマージドライバを使用して3-wayマージが実行されます。組み込みの3-wayマージドライバは「text」ドライバを要求することで明示的に指定でき、組み込みの「現在のブランチを使用する」ドライバは「binary」で要求できます。

組み込みマージドライバ

merge属性を介して要求できる、いくつかの組み込み低レベルマージドライバが定義されています。

text

テキストファイルの通常の3-wayファイルレベルマージ。競合する領域は、競合マーカー<<<<<<<=======、および>>>>>>>でマークされます。あなたのブランチからのバージョンは=======マーカーの前に表示され、マージされたブランチからのバージョンは=======マーカーの後に表示されます。

binary

作業ツリー内のブランチのバージョンを保持しますが、ユーザーが解決するためにパスを競合状態のままにします。

union

テキストファイルの3-wayファイルレベルマージを実行しますが、競合マーカーを残す代わりに、両方のバージョンから行を取り込みます。これにより、結果ファイル内の追加された行はランダムな順序になりがちであり、ユーザーは結果を検証する必要があります。意味を理解していない場合はこれを使用しないでください。

カスタムマージドライバーの定義

マージドライバの定義はgitattributesファイルではなく.git/configファイルで行うため、厳密に言えばこのマニュアルページで話すのは場違いです。しかし…​

カスタムマージドライバー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) を実行するコマンドを構築するために使用されます。これらの3つのトークンは、コマンドラインが構築されるときに、これらのバージョンの内容を保持する一時ファイルの名前で置き換えられます。さらに、%Lは競合マーカーのサイズ(下記参照)で置き換えられます。

マージドライバは、%Aで指定されたファイルを上書きしてマージの結果を残し、クリーンにマージできた場合はゼロステータスで、競合があった場合はゼロ以外のステータスで終了することが期待されます。ドライバがクラッシュした場合(例:SEGVによって終了した場合)、128より高いゼロ以外のステータスで終了することが期待され、そのような場合、マージは失敗に終わります(競合を生成するのとは異なります)。

merge.*.recursive変数は、共通の祖先が複数ある場合に、マージドライバが内部マージのために呼び出されたときに使用する他のマージドライバを指定します。未指定の場合、ドライバ自体が内部マージと最終マージの両方に使用されます。

マージドライバは、マージ結果が保存されるパス名をプレースホルダー%Pを介して知ることができます。共通祖先、ローカルヘッド、および他のヘッドに使用される競合ラベルは、それぞれ%S%X、および%Yを使用して渡すことができます。

conflict-marker-size

この属性は、競合するマージ中にワークツリーファイルに残される競合マーカーの長さを制御します。正の整数のみが意味のある効果を持ちます。

例えば、.gitattributesのこの行は、Documentation/git-merge.adocのマージが競合を引き起こす場合に、マージ機構が通常よりはるかに長い(通常の7文字長ではなく)競合マーカーを残すように指示するために使用できます。

Documentation/git-merge.adoc	conflict-marker-size=32

空白エラーのチェック

whitespace

core.whitespace設定変数を使用すると、diffおよびapplyがプロジェクト内のすべてのパスについて空白エラーとみなすべきものを定義できます(git-config[1]を参照)。この属性により、パスごとにきめ細かな制御が可能になります。

設定済み (Set)

Gitが認識する可能性のあるすべての空白エラーの種類を検出します。タブ幅はcore.whitespace設定変数の値から取得されます。

未設定 (Unset)

何もエラーとして認識しません。

未指定 (Unspecified)

エラーとして認識する内容を決定するために、core.whitespace設定変数の値を使用します。

文字列 (String)

core.whitespace設定変数と同じ形式で、認識する一般的な空白問題のカンマ区切りリストを指定します。

アーカイブの作成

export-ignore

export-ignore属性を持つファイルとディレクトリは、アーカイブファイルに追加されません。

export-subst

ファイルのexport-subst属性が設定されている場合、Gitはこのファイルをアーカイブに追加する際にいくつかのプレースホルダーを展開します。展開はコミットIDの利用可能性に依存します。つまり、git-archive[1]にコミットまたはタグの代わりにツリーが与えられた場合、置換は行われません。プレースホルダーはgit-log[1]のオプション--pretty=format:と同じですが、ファイル内で$Format:PLACEHOLDERS$のようにラップする必要があります。例として、文字列$Format:%H$はコミットハッシュに置き換えられます。ただし、サービス拒否攻撃を避けるため、アーカイブごとに1つの%(describe)プレースホルダーのみが展開されます。

オブジェクトのパッキング

delta

delta属性がfalseに設定されているパスのBLOBについては、デルタ圧縮は試行されません。

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

注記

Gitは、作業ツリー内の.gitattributesファイルにアクセスする際に、シンボリックリンクを追跡しません。これにより、ファイルがインデックスまたはツリーからアクセスされる場合と、ファイルシステムからアクセスされる場合とで動作の一貫性が保たれます。

以下の3つの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属性が設定されます。また、2番目の行が一致し、foobar属性が未設定になることを見つけます。

  2. 次に、.gitattributes(親ディレクトリにある)を調べると、最初の行が一致しますが、t/.gitattributesファイルはすでにこのパスにmergefoobar属性をどのように与えるかを決定しているため、foobarは未設定のままになります。属性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

git[1]スイートの一部

scroll-to-top