.gitignore構文:bin vs bin / vs. bin / * vs. bin / **


89

追加の違いは何ですかbinbin/bin/*そしてbin/**私の.gitignoreファイルで?私はこれまで使用してきましたがbin/他の .gitignoreファイルを見ると(日食ファイルでは、二重星と単一星が次のように一緒に使用さtmp/**/*れています:どうしたのですか?)最初の2つのパターンも広く使用されていることがわかります。誰かが3つの違いを説明できますか?


4
@unutbu:その質問に対して受け入れられた答えは明らかに論争中です。上位のコメントの1つは、答えは実際には完全な神話であると主張しています。
chandsie 2012年

動作はマンページで完全に指定されており、このあたり(または10個)にそのすべての情報を含む質問/回答があると確信しています。
カスカベル2012年

回答:


84

bin'bin'という名前のファイルまたはディレクトリに一致します。

bin/'bin'という名前のディレクトリと一致します。これは、Gitがディレクトリだけを追跡しないため、事実上すべてのコンテンツを意味します。

bin/*任意の内のすべてのファイルとディレクトリに直接一致しますbin/。これにより、Gitがサブディレクトリ内のファイルを自動的に検出するのを防ぎますが、たとえばbin/fooサブディレクトリが作成された場合、このルールはの内容と一致しませんfoo

bin/**任意のbin/ディレクトリとそのすべてのサブディレクトリ内のすべてのファイルとディレクトリに一致します。

ルールはリポジトリルートに関連しておらず、ファイルシステムツリーのどこにでも適用されるため、ここでは「any」という単語が重要です。ルールは/(または!/意図したものだけに一致させるには、システムのルートではなく、リポジトリのルートを意味する無視しない)で。

警告:あなたがすべき決してようなルールを使用しないdir/*/dir/**などだけでは、あなたもそのディレクトリ内に存在する何かをアン無視しない限り。アスタリスクを省略してください。そうしないとgit gcgit stashなどの特定の呼び出しから大量のデータが永久に失われる可能性があります。

どういうtmp/**/*意味なのかよくわかりません。私は当初tmp/tmp/それ自体に直接存在するファイルではなく、のサブディレクトリ内のファイルを照合するために使用できると考えていました。しかし、簡単なテストでは、これが内のすべてのファイルを無視することを示唆しているようですtmp/


10
ただ明確にするために、違いは何だbin/とはbin/**
chandsie 2012年

1
bin/binディレクトリは無視されると思いbin/**ますが、binディレクトリは含まれますが、その内容は含まれません
Robin Winslow 2012

1
それはシッダールタの答えと矛盾しているようです。答えからbin/引き出すと、ディレクトリ自体(すべてのサブディレクトリとファイルを含む)bin/**が無視されますが、binディレクトリとそのサブディレクトリ内のすべてのファイルは無視されますが、binディレクトリ自体は無視されません。それが正確かどうかはわかりません。
クリストファーバーマン2012年

3
bin /ディレクトリ内のすべてのファイルを追跡したいが、そのサブディレクトリ内のすべてのファイルを無視したい場合は、(後続の行で)実行できます(bin/** \n !bin/*ミニ
マーク

9
この答えは多くの点で間違っています。まず、gitはディレクトリを追跡しないため、.gitignoreエントリはディレクトリの内容とのみ一致し、ディレクトリ自体と一致することはありません。第二に、bin一致した両方の名前のファイルbin の内容binのフォルダを。第三に、そのサブディレクトリ内のすべてのファイルとbin/* 一致します。あなたたちはこれをテストしましたか?
ThomasR 2016

46

binそしてbin/後者の意志が唯一のディレクトリと一致していることだけが異なります。

bin/**/*と同じですbin/**(@VonCの回答によると、明らかに1.8.2以降)。

トリッキーなのは、私が1時間ほどかけて髪を引き裂いたことですが、bin/それbin/**まったく同じではありません。前者はディレクトリ全体を無視し、後者はその中の各ファイルを無視し、ほとんどの場合gitはディレクトリを気にしないため、通常は違いはありません。ただし、を使用!してサブパスを無視しないようにしようとすると、親ディレクトリを無視するとgit(ahem)がサブパスを無視することがわかります。(ここでも、ディレクトリの内容ではなく)

これは例で最も明確なので、新しく初期化されたリポジトリの場合は次のように設定します。

$ cat .gitignore
ignored-file
or-dir
dir-only/
!dir-only/cant-reinclude
dir-contents/**
!dir-contents/can-reinclude

$ mkdir or-dir dir-only dir-contents

$ touch file ignored-file or-dir/ignored-file dir-only/cant-reinclude dir-contents/can-reinclude

次の追跡されていないファイルが存在します。

$ git ls-files --other
.gitignore
dir-contents/can-reinclude
dir-only/cant-reinclude
file
ignored-file
or-dir/ignored-file

ただし、次のファイルが無視されていないことがわかります。

$ git ls-files --other --exclude-standard
.gitignore
dir-contents/can-reinclude
file

そして、追加しようとすると、次のようになります。

$ git add dir-only/cant-reinclude
The following paths are ignored by one of your .gitignore files:
dir-only/cant-reinclude
Use -f if you really want to add them.
fatal: no files added

この動作はバグだと思います。(これはすべてオンですgit version 1.8.4.msysgit.0


1
確かに+1。動作が予期しないように見えるため、これに関する実際のバグレポートの提出を検討する必要があります。
chandsie 2013

1
まさに私のユースケース。ありがとう!
セバスチャングラフ

3
dir/dir/**reの異なる動作。!「ファイルの親ディレクトリが除外されている場合、ファイルを再インクルードすることはできません」[ソース]が原因で、無視しないことが発生します。紛らわしいですが、パフォーマンス上の理由で行われます。関連するSOの質問を参照してください。
tanius 2015年

23

厳密に言えば、gitはディレクトリを追跡せず、ファイルのみを追跡することに注意してください。したがって、ディレクトリを追加することはできず、その内容のみを追加できます。

.gitignoreただし、このコンテキストでは、gitは、次の唯一の理由でディレクトリを理解するふりをします。

そのファイルの親ディレクトリが除外されている場合、そのファイルを再度含めることはできません。
https://git-scm.com/docs/gitignore#_pattern_format

これは除外パターンにとってどういう意味ですか?それらを詳しく見ていきましょう:

bin

これは無視します

  • 名前の付いたファイル bin。。
  • 名前の付いたフォルダの内容 bin

bin後続の!エントリを追加することで、無視されたファイルとフォルダをホワイトリストに登録できますが、名前の付いたフォルダの内容をホワイトリストに登録することはできませんbin

bin

!bin/file_in_bin # has no effect, since bin/ is blacklisted!
!bin/* # has no effect, since bin/ is blacklisted!
!file_in_bin # has no effect, since bin/ is blacklisted!

!bin # this works

bin/

。という名前のファイルと一致しないことを除いて、上記と同じですbin。末尾を追加する/と、gitはディレクトリのみに一致するようになります。

bin/*

これは無視します

  • 名前の付いたフォルダに含まれるファイルbin
  • 名前の付いたフォルダの直接サブフォルダの内容 bin
bin/*  # blacklists bin/file_in_bin and bin/subfolder/

!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted!
!bin # whitelists files named bin/bin, since bin/ itself is not blacklisted
!bin/ # has no effect, since bin/ itself is not blacklisted


!bin/file_in_bin # works since bin/ itself is not blacklisted
!file_in_bin # works too
!bin/subfolder # works (so implicitly whitelists bin/subfolder/file_in_sub)
!bin/subfolder/ # works just as well
!bin/* # works for file_in_bin and subfolder/

bin/**

これは無視します

  • の内容 bin
  • 内のサブフォルダーの内容(任意のレベルのネスト) bin
bin/**  # blacklists bin/file_in_bin and
        # bin/subfolder/ and bin/subfolder/file_in_sub and
        # bin/subfolder/2/ and bin/subfolder/2/file_in_sub_2

!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/ # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/file_in_sub_2 # has no effect, since bin/subfolder is blacklisted

!bin/subfolder # works only in combinations with other whitelist entries,
               # since all contents of subfolder are blacklisted (1)

!bin/file_in_bin # works since bin itself is not blacklisted
!bin/* # works for file_in_bin and subfolder; see (1)

9

新しいリポジトリを作成して、いくつか試してみました。これが私の結果です:

新しい結果

gitバージョン2.10.1.windows.1

  1. ほぼ空のリポジトリを初期化します。READMEファイルのみ
  2. 移入bin深いディレクトリいくつかの層を
    • bin.txt
    • Test.txt
    • bin/a/b/bin.txt
    • bin/a/b/Test.txt
    • bin/a/bin/bin.txt
    • bin/a/bin/Test.txt
    • bin/a/bin.txt
    • bin/a/Test.txt
    • bin/bin.txt
    • bin/Test.txt
  3. bingitignoreに追加:結果
    • binディレクトリの下(およびそれより深い)はすべて無視されるようになりました
    • ルートレベルは無視されません(/bin.txtおよび/Test.txtは引き続き表示されます)
  4. 編集binbin/gitignoreで:結果
    • 変化なし
  5. 編集bin/するbin/*
    • 変化なし
  6. 編集bin/*するbin/**
    • 変化なし
  7. 編集bin/**するbin/**/
    • bin/bin.txtそしてbin/Test.txt、もはや無視されていません
  8. 編集bin/**/するbin/**/*
    • bin/bin.txtそして、bin/Test.txt、無視されることに戻っています

古い結果

gitバージョン:2.7.0.windows.1

  1. ほぼ空のリポジトリを初期化します。READMEファイルのみ
  2. 移入bin深いディレクトリいくつかの層を
    • bin/a/b/Test.txt
    • bin/a/bin/Test.txt
    • bin/a/Test.txt
    • bin/Test.txt
  3. bingitignoreに追加:結果
    • binディレクトリの下(およびそれより深い)はすべて無視されるようになりました
  4. 編集binbin/gitignoreで:結果
    • binディレクトリの下(およびそれより深い)はすべて無視されます(変更なし)
  5. 編集bin/するbin/*
    • binディレクトリの下(およびそれより深い)はすべて無視されます(変更なし)
  6. 編集bin/*するbin/**
    • binディレクトリの下(およびそれより深い)はすべて無視されます(変更なし)
  7. 編集bin/**するbin/**/
    • bin/Test.txt 無視されなくなりました
  8. 編集bin/**/するbin/**/*
    • binディレクトリの下(およびそれ以上)のすべてが再び無視されます

1
これは良いテストです。text.txtの名前をbin.txtに変更すると、いくつかの重要な違いがわかりやすくなると思います。あなたがこれをしたなら、私はこの答えに投票するでしょう。
マットジョンソン

@MattJohnson True ...残念ながら、現在、新しいgitバージョンを使用しています
Joe Phillips

@MattJohnson私はついにこれに取り掛かりました
Joe Phillips

8

なお、「**」、サブディレクトリと組み合わせたときに**/bar)するので、そのデフォルトの動作から変更されている必要がありますgit1.8.2のリリースノートは今言及:

.gitignoreおよび.gitattributesファイルのパターンは、**/サブディレクトリの0以上のレベルに一致するパターンとして持つことができます。

たとえば、「foo/**/barbarは「foo」自体または「foo」のサブディレクトリ内の「」と一致します。


覚えておくべきルール(そしてそれらの構文の背後にある意図の違いを理解するのに役立つ)は次のとおりです。

そのファイルの親ディレクトリが除外されている場合、そのファイルを再度含めることはできません。


通常、無視フォルダーfのサブフォルダーからファイルを除外する場合は、次のようにします。

f/**
!f/**/
!f/a/sub/folder/someFile.txt

あれは:

  • 最初のルールがであったf/場合、フォルダf/は無視され、以下のルールfは重要ではありません。
  • f/**同じを達成f/ますが、すべてのサブ要素を無視する(ファイルやサブフォルダを)。
    これにより、サブフォルダーをホワイトリストに登録する(gitignoreから除外する)機会が与えられます!f/**/
  • すべてのfサブフォルダーが無視されるわけでないため、ファイルを除外するルールを追加できます(!f/a/sub/folder/someFile.txt

これはどのように質問に答えますか?
ThomasR 2016

0

との間には別の違いがbin/*ありbin/ます。

bin/一致しますがfoo/bin/test.txt(予想どおり)、一致bin/*しません。これは奇妙に思えますが、文書化されています:https//git-scm.com/docs/gitignore

「Documentation / *。html」は「Documentation / git.html」と一致しますが、「Documentation / ppc /ppc.html」または「tools / perf / Documentation /perf.html」とは一致しません。

この理由は、次のルールのようです。

  • パターンがスラッシュで終わっている場合は、以下の説明のために削除されています…

  • パターンにスラッシュ/が含まれていない場合、Gitはそれをシェルグロブパターンとして扱い、.gitignoreファイルの場所に関連するパス名との一致をチェックします…

  • それ以外の場合、Gitはパターンをfnmatch(3)によるFNM_PATHNAMEフラグ付きの消費に適したシェルグロブとして扱います…

したがって、パターンがスラッシュで終わる場合、スラッシュは削除され、シェルグロブパターンとして扱われます。この場合、はにbin一致しfoo/bin/test.txtます。で終わる場合/*、スラッシュは削除されず、サブディレクトリで一致しないfnmatchに渡されます。

しかし、同じことが当てはまりないfoo/bin/foo/bin/*さえから最後のスラッシュを削除した後ので、foo/bin/それはのfnmatchパターンではなく、グロブとして扱われますので、それはまだ、スラッシュが含まれています。つまり、一致しませんbar/foo/bin/test.txt

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.