On Sun, Apr 30, 2017 at 8:56 PM, Chris Johnson <chrisjohnson0@xxxxxxxxx> wrote: > Good assessment/understanding of the issue. git clean -n does not > report anything as being targeted for removal, and git clean -f > matches that behavior. I agree with it probably being related > specifically to the -d flag. > > As another experiment I modified .gitignore to ignore /A/B/C instead > of /A/B/ and the same result occurs (-n reports nothing, -dn reports > removing A/) > > Lastly, I changed .gitignore to just be /A/, and in doing so, clean > -dn stops reporting that it will remove A/. I’m not exactly sure if > this last one is surprising or not. It doesn't seem so to me, since a trailing slash in .gitignore is an explicit directive to ignore the entire directory, so when pruning the tree of files/dirs to ignore, it drops everything in A/ before even getting to A/B/C. The issue is that ignoring A/B/C shouldn't leave A/ to be cleaned. > Also, and sorry for the noise, but I did a reply-all here, but will a > reply automatically include the rest of the list? Or was reply-all the > right move? > > On Sun, Apr 30, 2017 at 9:41 PM, Junio C Hamano <gitster@xxxxxxxxx> wrote: >> Chris Johnson <chrisjohnson0@xxxxxxxxx> writes: >> >>> I am a mailing list noob so I’m sorry if this is the wrong format or >>> the wrong please. >>> >>> Here’s the setup for the bug (I will call it a bug but I half expect >>> somebody to tell me I’m an idiot): >>> >>> git init >>> echo "/A/B/" > .gitignore >> >> You tell Git that anything in A/B/ are uninteresting. >> >>> git add .gitignore && git commit -m 'Add ignore' >>> mkdir -p A/B >>> touch A/B/C >> >> And create an uninteresting cruft. >> >>> git status >> >> And Git does not bug you about it. >> >>> git clean -dn >> >> This incorrectly reports "Would remove A/" and if you gave 'f' >> instead of 'n', it does remove A/, A/B, and A/B/C. >> >> Despite that "git clean --help" says 'only files unknown to Git are >> removed' (with an undefined term 'unknown to Git'). What it wants >> the term mean can be guessed by seeing 'if the -x option is >> specified, ignored files are also removed'---so 'unknown to Git' >> does not include what you told .gitignore that they are >> uninteresting. IOW, Git knows they are not interesting. >> >> It looks like a bug in "git clean -d" to me. I may be wrong (I'm not very familiar with the codebase), but I don't think it's a bug in specifically git clean -d. Throwing gdb at it, when builtin/clean.c:cmd_clean() calls dir.c:fill_directory(), A/ gets appended to dir->entries, regardless of whether or not git clean is called with or without -d. The difference is that if git clean is called without -d, the loop that strips out directories strips out the A/ entry. When dir.c:fill_directory() is invoked through git status, A/ does not, however, get appended to dir->entries. As best as I can tell, this seems to be because git status sets the DIR_HIDE_EMPTY_DIRECTORIES flag, whereas git clean does not (which makes sense), but the fact that DIR_HIDE_EMPTY_DIRECTORIES is responsible for not adding A/ to dir->entries seems to be the issue.