SYNOPSIS

$GIT_DIR/info/attributes, .gitattributes

DESCRIPTION

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

gitattributes ファイルの各行は以下の形式です:

pattern attr1 attr2 ...

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

各属性は、特定のパスに対して以下のいずれかの状態になる可能性があります:

設定(set)

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

設定解除(unset)

パスには、特別な値 false を持つ属性があります。 これは、属性リストにマイナス記号 - (\x2d)で始まる属性の名前をリストすることによって指定されます。

値を設定

パスには、指定の文字列値を持つ属性があります。これは、属性の名前の後に等号 = とその値を、属性リストにリストすることによって指定されます。

未指定(unspecified)

パスに一致するパターンはなく、パスに属性があるかどうかはわかりません。パスの属性は未指定(unspecified)であると言われます。

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

パターンがパスと一致するルールは、以下のいくつかの例外を除いて、 .gitignore ファイル(gitignore(5) 参照)と同じです:

  • 否定パターンは使えません

  • ディレクトリに一致するパターンは、そのディレクトリ内のパスに再帰的に一致しません(したがって、属性ファイルで末尾のスラッシュの path/ 構文を使用しても意味がありません。代わりに path/** を使用してください)

パスに割り当てる属性を決定するとき、Gitは、(優先順位が最も高い) $GIT_DIR/info/attributes ファイルと、問題のパスと同じディレクトリにある .gitattributes ファイルと、作業ツリーの最上位までその親ディレクトリを参照します(.gitattributes を含むディレクトリが問題のパスから離れるほど、優先順位は低くなります)。最後に、(優先順位が最も低い)グローバルファイルとシステム全体のファイルが考慮されます。

.gitattributes ファイルが作業ツリーにない場合、インデックス内のパスがフォールバックとして使用されます。チェックアウト処理では、インデックスの .gitattributes が使用され、作業ツリーのファイルがフォールバックとして使用されます。

単一のリポジトリのみに影響を与えたい(つまり、そのリポジトリの1人のユーザーのワークフローに固有のファイルに属性を割り当てる)場合は、属性を $GIT_DIR/info/attributes ファイルに配置する必要があります。バージョン管理して他のリポジトリに配布する必要がある属性(つまり、すべてのユーザーが関心を持つ属性)は、 .gitattributes ファイルに入れる必要があります(git-config(1) を参照)。 あるユーザーのすべてのリポジトリに影響を与える属性は、 core.attributesFile 構成オプションで指定されたファイルに配置する必要があり、そのデフォルト値は $XDG_CONFIG_HOME/git/attributes です。 $XDG_CONFIG_HOME が設定されていないか空の場合、代わりに $HOME/.config/git/attributes が使用されます。システム上のすべてのユーザーの属性は、 $(prefix)/etc/gitattributes ファイルに配置する必要があります。

しばしばあなたは、 Unspecified(未指定)状態へのパスの属性の設定をオーバーライドする必要があります。これは、感嘆符 ! が前に付いた属性の名前をリストすることで行えます。

EFFECTS

Gitによる特定の操作は、特定の属性をパスに割り当てることによって影響を受ける可能性があります。 現在、以下の操作は属性対応(attributes-aware)です。

Checking-out and checking-in

これらの属性は、 git switchgit checkoutgit merge などのコマンドが実行されたときに、リポジトリに保存されているコンテンツが作業ツリーファイルにコピーされる方法に影響します。 また、Gitが git addgit commit する時に準備したコンテンツをリポジトリの作業ツリーに保存する方法にも影響します。

text

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

設定(set)

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

設定解除(unset)

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

文字列値 auto を設定

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

未指定(unspecified)

text 属性が指定されていない場合、Gitは core.autocrlf 構成変数を使用してファイルを変換する必要があるかどうかを判断します。

その他の値の場合、Gitは text が未指定(unspecified)であるかのように動作します。

eol

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

文字列値 crlf を設定

この設定により、ファイルがチェックアウトされるときに、作業ディレクトリ内のファイルの行末が CRLF に変換されます。

文字列値 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に正規化され、リポジトリですでに正規化されているファイルは正規化されたままになります。

貢献者(contributor)がリポジトリに導入するテキストファイルの行末が正規化されていることを確認する場合は、「全て」のファイルに対して 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
Note
中央リポジトリへのプッシュとプルを使用してクロスプラットフォームプロジェクトで text = auto 変換が有効になっている場合、CRLFを含むテキストファイルを正規化する必要があります。

クリーンな作業ディレクトリから始めます:

$ echo "* text=auto" >.gitattributes
$ git add --renormalize .
$ git status        # 正規化されるファイルを表示
$ 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またはそのスーパーセットの1つ(UTF-8、ISO-8859-1など)でエンコードされたファイルをテキストファイルとして認識します。他の特定のエンコーディング(UTF-16など)でエンコードされたファイルはバイナリとして解釈されるため、組み込みのGitテキスト処理ツール(git diff など)や、ほとんどのGitWebフロントエンドはデフォルトでこれらのファイルのコンテンツを視覚化しません 。

このような場合、 working-tree-encoding 属性を使用して作業ディレクトリ内のファイルのエンコーディングをGitに指示できます。この属性を持つファイルがGitに追加されると、Gitは指定されたエンコーディングからUTF-8にコンテンツを再エンコードします。最後に、GitはUTF-8でエンコードされたコンテンツを内部データ構造(「インデックス」と呼ばれます)に格納します。チェックアウト時に、コンテンツは指定されたエンコーディングに再エンコードされます。

注意: working-tree-encoding 属性を使用すると、いくつかの落とし穴があることに注意してください:

  • (2018年3月現在、)代替のGit実装(JGitやlibgit2など)やGit古いバージョンは、 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

あなたの * .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はチェックアウト時にブロブオブジェクト内の $Id$$Id: に置き換え、その後に40文字の16進ブロブオブジェクト名が続き、その後にドル記号 $ が続きます。ワークツリーファイルで $Id: で始まり、 $ で終わるバイトシーケンスは、チェックイン時に $Id$ に置き換えられます。

filter

filter 属性には、構成で指定されたフィルタドライバの名前を文字列で指定することができます。

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

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

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

これらの2つのフィルターの振る舞いは異なり、デフォルトでは、フィルターは前者と見なされ、コンテンツをより便利な形にもみもみ(massage)します。構成にフィルタードライバー定義がないか、ゼロ以外のステータスで終了するフィルタードライバーはエラーではありませんが、フィルターを無操作パススルーにします。

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

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

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

*.c     filter=indent

次に、あなたは以下のように .git/configfilter.indent.cleanfilter.indent.smudge 構成を定義して、ソースファイルがチェックインされたとき(clean が実行されます)と、チェックアウトされたとき(コマンドが cat であるため、変更は行われません)、にCプログラムの内容を変更するコマンドのペアを指定します。

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

最良の結果を得るには、 clean を2回実行しても出力を変更しないでください("clean→clean" は "clean" と同等である必要があります)。また、複数の smudge コマンドで clean の出力を変更しないでください("smudge→smudge→clean" は "clean” と同等である必要があります)。 以下のmergingセクションを参照してください。

"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コマンドは、ディスク上のファイルにアクセスしようとするのではなく、標準入力で提供されるコンテンツのフィルターとしてのみ機能する必要があります。

Long Running Filter Process

フィルタコマンド(文字列値)が filter.<driver>.process を介して定義されている場合、Gitは単一のGitコマンドの存続期間中、単一のフィルタ呼び出しですべてのブロブを処理できます。 これは、長時間実行プロセスプロトコル( technical/long-running-process-protocol.txt にて説明)を使用して実現されます。

Gitは、クリーニング(cleaned)またはスマッジング(smudged)が必要な最初のファイルを検出すると、フィルターを開始してハンドシェイクを実行します。ハンドシェイクでは、Gitによって送信されるウェルカムメッセージは "git-filter-client" であり、プロトコルバージョン2("version=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パケットで送信し、最後にフラッシュパケットを送信することが期待されます。最後に、フラッシュパケットで終了する "key=value" ペアの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!

結果のコンテンツが空の場合、フィルターは "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

"error"/"abort" ステータスが設定されている場合、Gitはフィルタープロセスを停止も再開もしません。 ただし、Gitは filter.<driver>.required`フラグに従って終了コードを設定し、 `filter.<driver>.clean / filter.<driver>.smudge メカニズムの振る舞いを真似っこします。

通信中にフィルターが停止した場合、またはプロトコルに準拠していない場合、Gitはフィルタープロセスを停止し、処理が必要な次のファイルでフィルターを再開します。 filter.<driver>.required フラグの設定によっては、Gitはそれをエラーとして解釈します。

Delay

フィルタが "delay" 機能をサポートしている場合、Gitはフィルタコマンドとパス名の後にフラグ "can-delay" を送信できます。このフラグは、コンテンツなしでステータス "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がこのコマンドを送信すると、フィルターは、以前に遅延されて現在使用可能なブロブを表すパス名のリストを返すことが期待されます。リストはフラッシュパケットで終了する必要があり、その後に "success" ステータスが続き、これもフラッシュパケットで終了します。 遅延パスのブロブがまだ利用できない場合、フィルターは少なくとも1つのブロブが利用可能になるまで応答をブロックすることが期待されます。フィルタは、空のリストを送信することで、遅延ブロブがなくなったことをGitに伝えることができます。フィルタが空のリストで応答するとすぐに、Gitは質問を停止します。この時点でGitが受信していないすべてのブロブは欠落していると見なされ、エラーが発生します。

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はパス名を受け取った後、対応するブロブを再度要求します。これらのリクエストには、パス名と空のコンテンツセクションが含まれています。フィルターは、上記で説明した通常の方法で汚れたコンテンツ(smudged content)に応答することが期待されます。

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!

Example

長時間実行されるフィルターのデモの実装は、Gitコアリポジトリにある contrib/long-running-filter/example.pl にあります。 独自の長時間実行フィルタープロセスを開発する場合は、 GIT_TRACE_PACKET 環境変数がデバッグに非常に役立ちます(git(1) を参照)。

既存の filter.<driver>.cleanfilter.<driver>.smudge コマンドを filter.<driver>.process で使用できないことに注意してください。前者は後者とは異なるプロセス間通信プロトコルを使用するからです。

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

チェックインのコードの流れでは、ワークツリーファイルは最初に(指定され、対応するドライバーが定義されている場合、) filter ドライバーで変換され、次に結果が(指定されている場合) ident で処理され、最後に(指定されて適用可能な場合) text で処理されます。

チェックアウトのコードの流れでは、ブロブコンテンツは最初に text で変換され、次に ident で変換され、 filter に送られます。

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

clean/smudge フィルターや text/eol/ident 属性の追加など、そのファイルの正規リポジトリ形式を変更する属性をファイルに追加した場合、属性が配置されていない場所で何かをマージすると、通常、マージの競合が発生します。

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

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

Generating diff text

diff

属性 diff は、Gitが特定のファイルのdiffを生成する方法に影響を与えます。パスのテキストパッチを生成するか、パスをバイナリファイルとして扱うかをGitに指示できます。 また、ハンクヘッダーの @@ -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 に設定されているパスの diff を表示する必要がある場合、上記の設定で指定したコマンド、つまり j-c-diff を 7 つのパラメータで、 GIT_EXTERNAL_DIFF プログラムが呼ばれるのと同じように呼び出します。 詳しくは git(1) を参照してください。

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

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

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

*.json diff=<name>

次に、 diff.<name>.algorithm 構成を定義して、 diff アルゴリズムを、 myers または patience または minimal または histogram から選んで指定します。

[diff "<name>"]
  algorithm = histogram

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

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

Defining a custom hunk-header

テキストdiff出力の変更の各グループ(ハンク(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\\{.*)$"

注意: 単一レベルのバックスラッシュは構成ファイルパーサーによって使用されるため、バックスラッシュを2重にする必要があります。 上記のパターンは、バックスラッシュで始まり、行の終わりまで、 subsection{ の順に0回以上出現する行を選択します。

これを簡単にするための組み込みパターンがいくつかあり、 tex はその1つであるため、構成ファイルに上記を書き込む必要はありません(これは、 .gitattributes を介して属性メカニズムで有効にする必要があります)。以下の組み込みパターンを使用できます:

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

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

  • bibtex はBibTeXでコード化されたリファレンスを持つファイルに適しています。

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

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

  • css はCSS(cascading style sheets)に適しています。

  • 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文書のソースコードに適しています。

Customizing word diff

diff.*.wordRegex 構成変数で適切な正規表現を指定することにより、 git diff --word-diff が単語を1行に分割するために使用するルールをカスタマイズできます。たとえば、TeXでは、バックスラッシュとそれに続く一連の文字がコマンドを形成しますが、そのようなコマンドのいくつかは、空白を介さずに一緒に実行できます。それらを分離するには、以下のように $GIT_DIR/config ファイル(または $HOME/.gitconfig ファイル)で正規表現を使用します:

[diff "tex"]
        wordRegex = "\\\\[a-zA-Z]+|[{}]|\\\\.|[^\\{}[:space:]]+"

前のセクションにリストされているすべての言語には組み込みのパターンが用意されています。

バイナリファイルのテキスト差分の取得

一部のバイナリファイルのテキスト変換バージョンの差分を確認することが望ましい場合があります。たとえば、ワードプロセッサ文書をASCIIテキスト表現に変換し、テキストの差分を表示することができます。この変換によって一部の情報が失われますが、結果のdiffは人間が見るのに役立ちます(ただし、直接適用(apply)することはできません)。

textconv configオプションは、そのような変換を実行するためのプログラムを定義するために使用されます。プログラムは、変換するファイルの名前である単一の引数を取り、結果のテキストをstdoutに生成する必要があります。

たとえば、バイナリ情報の代わりにファイルのexif情報の差分を表示するには(exifツールがインストールされていると仮定して)、以下のセクションを $GIT_DIR/config ファイル(または `$HOME/.gitconfig ファイル)に追加します:

[diff "jpg"]
        textconv = exif
Note
テキスト変換は通常、一方向の変換です。この例では、実際の画像コンテンツを失い、テキストデータのみに焦点を当てています。これは、textconvによって生成されたdiffが適用(apply)に適していないことを意味します。このため、テキスト変換を実行するのは、 git diffgit log ファミリーのコマンド(つまり、log、whatchanged、show)のみです。 git format-patch はこの出力を生成しません。バイナリファイルのテキスト変換された差分を誰かに送信したい場合(たとえば、行った変更をすばやく伝達するため)、それを別個に生成し、送信する通常のバイナリ差分に加えてコメントとして送信する必要があります。

特に git log -p を使用して大量のテキスト変換を行う場合、テキスト変換が遅くなる可能性があるため、Gitは出力をキャッシュし、将来の差分で使用するメカニズムを提供します。 キャッシュを有効にするには、diffドライバーの構成で「cachetextconv」変数を設定します。 例えば:

[diff "jpg"]
        textconv = exif
        cachetextconv = true

これにより、各ブロブで「exif」を実行した結果が無期限にキャッシュされます。diffドライバーのtextconv構成変数を変更すると、Gitはキャッシュエントリを自動的に無効にし、textconvフィルターを再実行します。キャッシュを手動で無効にしたい場合(たとえば、「exif」のバージョンが更新され、より良い出力が生成されようになった等)、 git update-ref -d refs/notes/textconv/jpg を使用してキャッシュを手動で削除できます( ここで、「jpg」は上記の例のように、diffドライバーの名前です)。

textconvと外部diffの選択

あなたがリポジトリ内のバイナリまたは特別にフォーマットされたブロブの違いを表示したい場合は、外部のdiffコマンドを使用するか、textconvを使用してそれらを差分可能(diff-able)なテキストフォーマットに変換するかを選択できます。どちらの方法を選択するかは、状況に完全に依存します。

外部diffコマンドを使用する利点は、柔軟性です。行指向の変更を見つける必要はありません。また、出力が統一されたdiff(unified diff)に似ている必要もありません。あなたはあなたのデータ形式に最も適した方法で変更を自由に見つけて報告できます。

それと比較すると、textconvははるかに制限的です。データを行指向のテキスト形式に変換すると、Gitは通常のdiffツールを使用して出力を生成します。この方法を選択することにはいくつかの利点があります:

  1. 容易に使えます。多くの場合、独自の差分を実行するよりも、バイナリからテキストへの変換を作成する方がはるかに簡単です。多くの場合、既存のプログラム(つまり exif や odt2txt)をtextconvフィルターとして使用できます。

  2. Gitのdiff機能。変換ステップのみを自分で実行することで、カラー化、単語diff、マージ用の複合diffなど、Gitのdiff機能の多くを引き続き利用できます。

  3. キャッシュ機能。 textconvキャッシングは、 git log -p を実行してトリガーするような、繰り返されるdiffを高速化できます。

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

Gitは通常、コンテンツの先頭を調べることで、ブロブにテキストデータとバイナリデータのどちらが含まれているかを正しく推測します。ただし、ブロブにファイルの後半にバイナリデータが含まれている、またはコンテンツが技術的にはテキスト文字で構成されているものの、人間の読者には不明瞭であるために、あなたは、その推測を上書きしたい場合があります。たとえば、多くのポストスクリプトファイルにはASCII文字しか含まれていません(つまりテキストデータです)が、ノイズが多く意味のないdiffが生成されます。

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

*.ps -diff

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

しかしながら、他のdiffドライバー属性を指定することもできます。 たとえば、 textconv を使用してポストスクリプトファイルをASCII表現に変換し、人間が表示できるようにしたい場合があるけども、それ以外の場合はバイナリファイルとして扱いたいとします。 -diff 属性 と diff=ps 属性の両方を指定することはできません。 解決策は、 diff.*.binary 構成オプションを使用することです:

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

Performing a three-way merge

merge

属性 merge は、 git merge 中にファイルレベルのマージが必要な場合にファイルの3つのバージョンをマージする方法や、 gitr evertgit cherry-pick などの他のコマンドに、影響します。

設定(set)

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

設定解除(unset)

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

未指定(unspecified)

デフォルトでは、これは merge 属性が設定されている場合と同じ組み込みの3方向マージドライバーを使用します。 ただし、 merge.default 構成変数は、 merge 属性未指定(unspecified)のパスで使用される別のマージドライバーに名前を付けることができます。

String(文字列値)

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

Built-in merge drivers

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

text

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

binary

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

union

テキストファイルに対して3方向のファイルレベルのマージを実行しますが、競合マーカーを残すのではなく、両方のバージョンから行を取得します。これにより、結果のファイルに追加された行がランダムな順序で残る傾向があり、ユーザーは結果を確認すべきです。影響を理解していない場合は、これを使用してはいけません。

Defining a custom merge driver

マージドライバの定義は、 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 によって kill された場合など)、ドライバーは 128 を超えるゼロ以外のステータスで終了(exit)すると期待され、かつ、そのような場合、マージは失敗(failure)します(これは競合の発生とは異なります)。

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

マージドライバーは、プレースホルダー %P を介して、マージされた結果が格納されるパス名を知ります。

conflict-marker-size

この属性は、競合するマージ中に作業ツリーファイルに残る競合マーカーの長さを制御します。値を正の整数に設定するだけで、意味のある効果があります。

たとえば、 ファイル Documentation/git-merge.txt の結果をマージすると競合するときに、.gitattributes で(通常の7文字の長さではなく)はるかに長い競合マーカーを残すようにマージ機構に指示できます。

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

Checking whitespace errors

whitespace

`core.whitespace` 設定変数を使用すると、プロジェクト内のすべてのパスに対して `diff` と `apply` が空白エラー(whitespace errors)をどうみなすかを定義します(linkgit:git-config[1] を参照)。この属性では、あなたはパスごとに細かく制御できます。
設定(set)

Gitでチェックできる全てのタイプの潜在的な空白エラーを通知します。タブ幅は core.whitespace 構成変数の値から取得されます。

設定解除(unset)

何もエラーとして通知しません。

未指定(unspecified)

core.whitespace 構成変数の値を使用して、エラーとして通知する内容を決定します。

String(文字列値)

core.whitespace 構成変数と同じ形式で、通知すべき一般的な空白の問題(whitespace problems)の、コンマ区切りリストを指定します。

Creating an archive

export-ignore

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

export-subst

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

Packing objects

delta

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

Viewing files in GUI tools

encoding

この属性の値は、関連するファイルの内容を表示するためにGUIツール(gitk(1)git-gui(1) など)で使用される文字エンコードを指定します。注意: パフォーマンス上の考慮事項により、 gitk(1) は、オプションでファイルごとのエンコーディングを手動で有効にしない限り、この属性を使用しないことに注意してください。

この属性が設定されていないか、値が無効な場合は、代わりに gui.encoding 構成変数の値が使用されます(git-config(1) を参照)。

USING MACRO ATTRIBUTES

追跡中のバイナリファイルに、行末変換を適用したり、テキストの差分を作成したりする必要はありません。あなたは、たとえば以下のように指定する必要があります。

*.jpg -text -diff

しかし、多くの属性がある場合、これはめんどくさいです。マクロ属性を使用すると、あなたは設定時に他の多くの属性を同時に設定または設定解除する属性を定義できます。システムは、組み込みのマクロ属性 binary を認識します:

*.jpg binary

「binary」属性を設定すると、上記のように「text」属性と「diff」属性の設定も解除されます。マクロ属性は「set」のみであることに注意してください。ただし、1つを設定すると、他の属性をsetまたはunsetしたり、他の属性を「Unspecified」状態に戻したりする事があります。

DEFINING MACRO ATTRIBUTES

カスタムマクロ属性は、最上位のgitattributesファイル($GIT_DIR/info/attributes または、作業ツリーの最上位にある ` .gitattributes` ファイルまたは、グローバルgitattributesファイルまたは、システム全体のgitattributesファイル)でのみ定義でき、作業ツリーサブディレクトリの .gitattributes ファイルでは定義できません。 組み込みのマクロ属性「binary」は、以下のものと同等です:

[attr]binary -diff -merge -text

NOTES

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

EXAMPLES

これらの以下の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行目が一致し、属性 foo と `bar`が設定解除(unseet)されていることもわかります。

  2. 次に (親ディレクトリにある) .gitattributes を調べ、最初の行がマッチすることを確認します。しかし、 t/.gitattributes ファイルでは、このパスに対して mergefoobar 属性をどのように与えるべきかを既に決めているので、foobar は設定解除(unset)のままにしています。属性 baz がsetされます。

  3. 最後に、 $GIT_DIR/info/attributes を調べます。このファイルは、ツリー内の設定を上書きするために使用されます。最初の行がマッチして foo がsetされ、 bar が指定解除(unset)の状態に戻され、 baz が設定解除(unset)されます。

その結果、 t/abc への属性の割り当ては以下のようになります:

foo     set to true
bar     unspecified
baz     set to false
merge   set to string value "filfre"
frotz   unspecified

SEE ALSO

GIT

Part of the git(1) suite