This will work, and from the root .gitignore
is the shortest sequence that will work efficiently:
app/migrations/*
!app/migrations/config
app/migrations/config/*
!app/migrations/config/Migrations
(It might be clearer and more explicit to write the second line as !app/migrations/config/
but as long as config
is a directory, the effect is the same. See my additional remarks below.)
In short you have to ignore then un-ignore each sub-directory.
That's correct, because when a directory is in fact ignored (by the last matching .gitignore
rule), this gives Git permission to omit scanning the directory entirely. As a result it never sees any of the files or sub-directories within that directory. It is, however, very efficient: Git never needs to open the directory in the first place! That's why this rule works the way it works.
However this does not work 100% since app/migrations/config/* is un-ignored when it should only be app/migrations/config/Migrations.
That's because you said to do that. Say to do what you mean, and you're OK. :-)
What's more this is not only over-complicated but also makes for an almost unreadable and bloated git-ignore file - 6 lines just to un-ignore a sub-sub-directory.
Well, four lines. That said, I do agree that this is overly complicated. Git should recognize the pattern:
dir/*
!dir/sub/something
and automatically insert the appropriate !dir/sub/
. Likewise for:
dir/*
!dir/sub1/sub2/something
Here, Git could automatically insert the !dir/sub1/
and !dir/sub1/sub2/
rules as needed, with corresponding "ignore all files within" rules as needed. These un-ignore insertions should end with /
in case dir/sub
, dir/sub1
, and/or dir/sub1/sub2
are files rather than directories.