Ignore all the files in the root except for some p

2019-04-14 09:57发布

问题:

I supposed this to do the trick:

*
!/dir1/
!/dir2/
!/file1
!/file2

But to my surprise, it didn't. It seems to work if I prepend a slash before the asterisk. But I don't really understand why it doesn't work before this change. Could anybody point out?

回答1:

To use negating patterns ! in .gitignore, just remember 2 rules.

Rule 1. Files and directories are separatedly handled in the patterns. To include a directory back doesn't mean its child files/directories are also included back.

I.E. The goal is to exclude all files/directories except everything inside /dir1. The following does NOT work.

# CANNOT work
*
!/dir1/

Why? The reason is just the first rule. Though the directory dir1 is included again, but not all its child files/directories. And only including the directory without its children means nothing to git, since git won't track empty folders.

As a comparison, the following works.

# works
/*
!/dir1/

Why? Because /* only matches the files/directories under the root directory directly, but not ignores any files/directories under sub-directories such as dir1 here. After !/dir1/ includes dir1 back, all its child files/directories are back naturely.

Someone may ask, if so, why the following doesn't work, since !/dir1/** will includes all child files/directories of dir1 back?

# CANNOT work
*
!/dir1/**

The reason is in rule 2.

Rule 2. It won't include files/directories back if their parent directory is still ignored. For this rule, please read my answer to a SO question first.

That's why the previous patterns won't work. And if we add another negating pattern to include the parent directory dir1 back first, it works.

# works
*
!/dir1/
!/dir1/**

After understanding the 2 rules, the solutions for OP's case is quite straightforward.

The following works.

/*
!/dir1/
!/dir2/
!/file1
!/file2

And the following also works.

*
!/dir1/
!/dir1/**
!/dir2/
!/dir2/**
!/file1
!/file2

To make it simple as follows.

*
!*/
!/dir1/**
!/dir2/**
!/file1
!/file2


标签: git gitignore