.gitignore除外ルールは実際にどのように機能しますか?


146

大きなディレクトリ構造でgitignoreの問題を解決しようとしていますが、質問を簡単にするために、次のように減らしました。

新しいgitリポジトリに2つのファイル(foo、bar)の次のディレクトリ構造があります(これまでのところコミットはありません)。

a/b/c/foo
a/b/c/bar

明らかに、「git status -u」は以下を示します。

# Untracked files:
...
#       a/b/c/bar
#       a/b/c/foo

私がやりたいことは、a / b / c内のすべてを無視するが、ファイル「foo」を無視しない.gitignoreファイルを作成することです。

このように.gitignoreを作成すると、次のようになります。

c/

次に、「git status -u」を実行すると、fooとbarの両方が無視されます。

# Untracked files:
...
#       .gitignore

それは私が期待するとおりです。

ここで、fooの除外ルールを追加すると、次のようになります。

c/
!foo

gitignoreのマンページによると、これが機能することを期待しています。しかし、それはしません-それでもfooを無視します:

# Untracked files:
...
#       .gitignore

これも機能しません:

c/
!a/b/c/foo

これも行いません:

c/*
!foo

与える:

# Untracked files:
...
#       .gitignore
#       a/b/c/bar
#       a/b/c/foo

その場合、fooは無視されなくなりましたが、barも無視されません。

.gitignoreのルールの順序も重要ではないようです。

これも私が期待することをしません:

a/b/c/
!a/b/c/foo

それはfooとbarの両方を無視します。

機能する1つの状況は、ファイルa / b / c / .gitignoreを作成してそこに配置した場合です。

*
!foo

しかし、これの問題は、最終的にa / b / cの下に他のサブディレクトリがあり、個別の.gitignoreを1つ1つに配置する必要がないことです-「プロジェクトベース」の.gitignoreを作成することを望んでいました各プロジェクトの最上位ディレクトリに配置でき、すべての「標準」サブディレクトリ構造をカバーするファイル。

これも同等のようです:

a/b/c/*
!a/b/c/foo

これは私が達成できる「作業」に最も近いものかもしれませんが、完全な相対パスと明示的な例外を指定する必要があります。これは、さまざまなレベルで「foo」という名前のファイルが多数ある場合に苦痛になりますサブディレクトリツリーの。

とにかく、除外ルールのしくみがよくわからないか、/(ワイルドカードではなく)ディレクトリが/で終わるルールによって無視されたときにまったく機能しない

誰かがこれにいくつかの光を当てることができますか?

この不器用なシェルベースの構文の代わりに、正規表現のような賢明なものをgitignoreに使用させる方法はありますか?

私はこれをCygwin / bash3のgit-1.6.6.1およびUbuntu / bash3のgit-1.7.1で使用して観察しています。



4
よく書かれた質問!あなたが試みた事件の数は、私が私の同様の事件で私が何をしていたのかを理解するのに本当に役立ちました。神に感謝します、私は今日長い間探していました。
Alex G

回答:


153
/ a / b / c / *
!foo

私のために動作するようです(Linuxではgit 1.7.0.4)。*代わりに(除外することができます)ディレクトリ内のファイルの(gitのように、内部の見ていないだろう)そうでなければ、ディレクトリ自体を無視しているとして重要です。

「この1ではなく」発言として除外を考えるのではなく、「これを含める」 - 「(このディレクトリを無視する/a/b/c/)ではなく、この1( foo)、」あまり意味がありません。「このディレクトリ(/a/b/c/*)のすべてのファイルを無視しますが、このディレクトリ()は無視しません」は無視しますfoo。manページを引用するには:

オプションの接頭辞!これはパターンを無効にします。以前のパターンによって除外された一致するファイルは、再び含まれます。

つまり、ファイルを再度含めるには、ファイルがすでに除外されている必要があります。それがいくつかの光を当てることを願っています。


はい、あなたが与える例は私にとってもうまくいきます。問題は、fooがcにある場合、/ a / b / *が機能しないことです。つまり、cの下のさまざまなサブディレクトリに複数のfooファイルがある場合(d /、e /、f / g / h /、i / jなど) /など)その後、否定ルール '!foo'はそれらをキャッチしません。
davidA

1
@meowsqueak確かにありません。/ a / b / *を無視した場合、fooが存在するディレクトリはありません!/ a / bの下にあるディレクトリツリー全体を無視しようとしているが、ツリー内のどこにでもある "foo"という名前のファイルを含める場合、.gitignoreパターンで実行できないと思います:\
Chris

実際、これは私にとってこれが機能しない理由を説明しているかもしれません-次のルールは機能しません: "/ a / b / *"、 "!c / foo"。これで問題が解決した場合は、問題がない可能性があります。
davidA

5
「.gitignoreパターンで実行できるとは思わない」-残念ながら、あなたは正しいと思います。
davidA

@meowsqueak無視/a/b/cしてgit add --force、一致するファイルのプリコミットなどにフックを書き込むことができます
Chris

24

私は同様の状況にあり、私の解決策は次のものを使用することでした:

/a/**/*
!/a/**/foo

私が**正しく読んだ場合、それは任意の数の中間ディレクトリで機能するはずです。


6

これは.gitignoreのmanページからは明確にわかりません。これは機能します:

*
!/a
!/a/b
!/a/b/c
!/a/b/c/foo

# don't forget this one
!.gitignore

Chrisが述べたように、ディレクトリは除外されている場合でも開かれません。したがって、*を無視できるようにする場合は、上記のようにそれらのファイルへのパスを作成する必要があります。私にとってこれは便利です。ライブラリの1つのファイルでコードレビューを行いたいので、後で別のファイルを行いたい場合は追加するだけで、他のすべては無視されます。


6

ここに別のオプションがあります:

*
!/a*
!/a/*
!/a/*/*
!/a/*/*/*

これは、aの3レベル下のファイル/ディレクトリを除いて、すべてのファイルとディレクトリを無視します。


5

より一般的な注意として、git1.8.2には、ファイルを実際に無視するルールを特定するための、Adam Spiersからのパッチ(同じくv4にStack Overflowの質問が表示されます)が含まれます。gitignore

参照してくださいgit1.8.2リリースノートおよび「SOの質問gitignoreルールが私のファイルを無視している:」
コマンドとなりますgit check-ignore


1
この情報を放送してくれてありがとう。 check-ignoreその場合、どのルールがファイルの無視を妨げているかを通知します。
Adam Spiers 2013年

@AdamSpiersは素晴らしいですね。必ず遊んでみます。
VonC 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.