Hi, Jean-Philippe GariÃpy wrote: > When using sub-directory entries in .gitignore, while the entry is > ignored as expected, "git clean -X" doesn't clean the ignored > sub-directory. Thanks for reporting. $ cat test.sh rm -fr test && git init test && ( cd test && mkdir -p a/b/c && >a/b/c/f && echo '/a/b/' >.gitignore && git status -s && git clean -X -d -n && git ls-files -o -i --exclude-standard && git ls-files -o --directory -i --exclude-standard && git clean -X -d -f && echo ... drumroll ... && ! test -e a/b/c/f ) $ sh test.sh || echo fail Initialized empty Git repository in /tmp/test/.git/ ?? .gitignore ... drumroll ... fail Variations: 1) echo '/a/' >.gitignore 2) echo '/a/b/c/f' >.gitignore 3) >a/b/f (1) does not fail; (2) and (3) still do. Okay, so why does this happen? Tracing: -- 8< -- diff --git a/dir.c b/dir.c index 133f472..5707ad0 100644 --- a/dir.c +++ b/dir.c @@ -693,6 +693,9 @@ static enum path_treatment treat_one_path(struct dir_struct *dir, int dtype, struct dirent *de) { int exclude = excluded(dir, path, &dtype); + + trace_printf("treat_one_path: path=%s exclude=%d\n", path, exclude); + if (exclude && (dir->flags & DIR_COLLECT_IGNORED) && exclude_matches_pathspec(path, *len, simplify)) dir_add_ignored(dir, path, *len); -- >8 -- $ GIT_TRACE=true PATH=/home/jrn/src/git/bin-wrappers:$PATH sh test.sh trace: built-in: git 'init' 'test' Initialized empty Git repository in /tmp/test/.git/ trace: built-in: git 'status' '-s' treat_one_path: path=.gitignore exclude=0 treat_one_path: path=a exclude=0 treat_one_path: path=a/b exclude=1 ?? .gitignore trace: built-in: git 'clean' '-X' '-d' '-n' treat_one_path: path=.gitignore exclude=0 treat_one_path: path=a exclude=0 trace: built-in: git 'ls-files' '-o' '-i' '--exclude-standard' treat_one_path: path=.gitignore exclude=0 treat_one_path: path=a exclude=0 treat_one_path: path=a/b exclude=1 treat_one_path: path=a/b/c exclude=0 treat_one_path: path=a/b/c/f exclude=0 trace: built-in: git 'ls-files' '-o' '--directory' '-i' '--exclude-standard' treat_one_path: path=.gitignore exclude=0 treat_one_path: path=a exclude=0 trace: built-in: git 'clean' '-X' '-d' '-f' treat_one_path: path=.gitignore exclude=0 treat_one_path: path=a exclude=0 ... drumroll ... $ 1) a/b/f is not actually considered excluded; only its containing directory is. 2) git clean does not even examine a/b to consider whether to remove it: since a/ does not contain any tracked files, it stopped there. The following would cause "git clean -ndx" to print more than it should, but hopefully it illustrates the idea. diff --git a/builtin/clean.c b/builtin/clean.c index b508d2c..91624c2 100644 --- a/builtin/clean.c +++ b/builtin/clean.c @@ -84,8 +84,6 @@ int cmd_clean(int argc, const char **argv, const char *prefix) if (force > 1) rm_flags = 0; - dir.flags |= DIR_SHOW_OTHER_DIRECTORIES; - if (read_cache() < 0) die("index file corrupt"); -- -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html