English ▾ トピック ▾ 最新バージョン ▾ gitattributes は 2.50.0 で最終更新されました

名前

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

概要

$GIT_DIR/info/attributes, .gitattributes

説明

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

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

pattern attr1 attr2 ...

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

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

設定済み

パスには特別な値 "true" の属性があります。これは、属性リストに属性の名前のみをリストすることで指定されます。

未設定

パスには特別な値 "false" の属性があります。これは、属性リストにダッシュ - をプレフィックスとして属性の名前をリストすることで指定されます。

値に設定

パスには指定された文字列値の属性があります。これは、属性リストに属性の名前とそれに続く等号 = およびその値をリストすることで指定されます。

未指定

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

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

パターンがパスに一致するルールは .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 の説明を参照)。

設定済み

パスに text 属性を設定すると、上記のようにチェックインおよびチェックアウト時に改行コード変換が有効になります。ファイルが以前に CRLF 改行コードで Git に追加された場合でも、ファイルがチェックインされるたびにインデックス内の改行コードは LF に正規化されます。

未設定

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

文字列値 "auto" に設定

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

未指定

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

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

eol

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

文字列値 "crlf" に設定

この設定は、ファイルがチェックアウトされるときに、作業ディレクトリ内のファイルの改行コードを CRLF に変換します。

文字列値 "lf" に設定

この設定は、ファイルがチェックアウトされるときに、作業ディレクトリ内の改行コードをインデックス内の改行コードと同じにします。

未指定

ファイルの 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 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 をサポートしていないクライアントは、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 checkout または git add) の速度が低下する可能性があります。

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

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

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

*.ps1 ファイルが BOM なしの UTF-16 リトルエンディアンでエンコードされており、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 フィルターとの通信に使用されるプロトコルの説明については、以下のセクションを参照してください。

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

コンテンツフィルタリングのもう1つの用途は、リポジトリで直接使用できないコンテンツ(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 フィルターが自分の出力を変更せずに受け入れる "必要" があることを意味します。

保存されたコンテンツを使用可能にするためにフィルタが成功する「必要」がある場合、構成でフィルタが 必須 であることを宣言できます。

[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 はフラッシュパケットで終了する "key=value" ペアのリストを送信します。このリストには、少なくともフィルターコマンド (サポートされている機能に基づく) と、リポジトリのルートに対するフィルターするファイルのパス名が含まれます。フラッシュパケットの直後、Git は 0 個以上の pkt-line パケットに分割されたコンテンツと、コンテンツを終了するフラッシュパケットを送信します。フィルターは、コンテンツと最終的なフラッシュパケットを受信するまで、応答を送信してはならないことに注意してください。また、「key=value」ペアの「value」は「=」文字を含むことができますが、キーは「=」文字を含むことはありません。

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

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

packet:          git< status=success
packet:          git< 0000
packet:          git< SMUDGED_CONTENT
packet:          git< 0000
packet:          git< 0000  # empty list, keep "status=success" unchanged!

結果のコンテンツが空の場合、フィルターは「success」ステータスとフラッシュパケットで応答し、空のコンテンツを通知することが期待されます。

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」ステータスとフラッシュパケットで応答することで示します。

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 を表すパス名のリストを返すことが期待されます。リストはフラッシュパケットで終了し、その後に「success」ステータスが続き、これもフラッシュパケットで終了します。遅延されたパスの 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 を再度要求します。これらの要求には、パス名と空のコンテンツセクションが含まれます。フィルターは、上記で説明した通常の方法で、smudge されたコンテンツで応答することが期待されます。

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 属性の追加など)、属性が設定されていないものをマージすると、通常はマージの競合が発生します。

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

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

差分テキストの生成

diff

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

設定済み

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

未設定

diff 属性が未設定のパスは、バイナリファイルが異なります (バイナリパッチが有効な場合はバイナリパッチ) を生成します。

未指定

diff 属性が未指定のパスは、まず内容が検査され、テキストのように見え、かつ core.bigFileThreshold より小さい場合はテキストとして扱われます。そうでない場合は、バイナリファイルが異なります が生成されます。

文字列

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

外部差分ドライバの定義

差分ドライバの定義は gitattributes ファイルではなく gitconfig で行われるため、厳密に言えばこのマニュアルページでそれを説明するのは適切ではありませんが…​

外部差分ドライバ 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.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 を追加しても効果はありません。アルゴリズムは外部差分ドライバに渡されないためです。

カスタムハunkヘッダーの定義

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

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

これは ハunk ヘッダー と呼ばれます。"TEXT" 部分は、デフォルトではアルファベット、アンダースコア、またはドル記号で始まる行です。これは GNU diff -p 出力が使用するものと一致します。しかし、このデフォルトの選択は一部のコンテンツには適していないため、カスタマイズされたパターンを使用して選択できます。

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

*.tex	diff=tex

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

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

注: 設定ファイルパーサーによってバックスラッシュが1レベル消費されるため、バックスラッシュを二重にする必要があります。上記のパターンは、バックスラッシュで始まり、その後にゼロ個以上の sub が続き、その後に section が続き、その後に開き括弧が続き、行の終わりまでの行を選択します。

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

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

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

  • bibtex BibTeX コード化された参照を持つファイルに適しています。

  • cpp C および C++ 言語のソースコードに適しています。

  • csharp C# 言語のソースコードに適しています。

  • css カスケーディングスタイルシートに適しています。

  • dts devicetree (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 が行内の単語を分割するルールは、"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. 使いやすさ。独自の差分を実行するよりも、バイナリからテキストへの変換を記述する方がはるかに簡単です。多くの場合、既存のプログラムを textconv フィルターとして使用できます (例: exif、odt2txt)。

  2. Git diff 機能。変換ステップ自体を実行するだけで、色付け、単語差分、マージの結合差分など、Git の多くの diff 機能を引き続き利用できます。

  3. キャッシュ。git log -p を実行してトリガーされる可能性のある繰り返し差分を、textconv キャッシュによって高速化できます。

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

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

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

*.ps -diff

これにより、Git は通常の差分の代わりに バイナリファイルが異なります (バイナリパッチが有効な場合はバイナリパッチ) を生成します。

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

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

3方向マージの実行

merge

属性 merge は、git merge、および git revertgit cherry-pick などの他のコマンド中にファイルレベルのマージが必要な場合に、ファイルの3つのバージョンがどのようにマージされるかに影響を与えます。

設定済み

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

未設定

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

未指定

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

文字列

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

組み込みマージドライバ

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

text

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

バイナリ

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

ユニオン

テキストファイルの 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 設定変数は、プロジェクト内のすべてのパスについて diffapply が空白エラーと見なすべきものを定義することを可能にします (git-config[1] を参照)。この属性は、パスごとにきめ細かな制御を提供します。

設定済み

Gitが認識しているすべての種類の潜在的な空白エラーに注意してください。タブ幅は、core.whitespace 設定変数の値から取得されます。

未設定

何もエラーとみなさない。

未指定

core.whitespace 設定変数の値を使用して、何をエラーとして認識するかを決定します。

文字列

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

アーカイブの作成

export-ignore

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

export-subst

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

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

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 ファイルがすでにこのパスに mergefoo、および bar 属性をどのように与えるかを決定しているため、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