git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Bug Report: .gitignore behavior is not matching in git clean and git status

From
Samuel Lijin <sxlijin@gmail.com>
Date
May 1, 2017, 13:51 UTC
Message-ID
<CAJZjrdXfcaUrJXbAoPtRtvigouZ2eNyNsZ=2WtSY20_D+Ow6qw@mail.gmail.com>
In-Reply-To
<CABfTTAdQPGei6CZoHGJGUtKHdJ4eT822pzc=DATynfeaZ94gxA@mail.gmail.com>
On Sun, Apr 30, 2017 at 8:56 PM, Chris Johnson <chrisjohnson0@gmail.com> wrote:
Show 12 quoted lines
> 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.

Show 41 quoted lines
> 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@pobox.com> wrote:
>> Chris Johnson <chrisjohnson0@gmail.com> 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.

Previous: Junio C HamanoNext: Samuel Lijin
Message 5 of 89 in “Bug Report: .gitignore behavior is not matching in git clean and git status”
  1. Chris JohnsonApr 28, 2017
  2. Junio C HamanoMay 1, 2017
  3. Chris JohnsonMay 1, 2017
  4. Junio C HamanoMay 1, 2017
  5. Samuel LijinMay 1, 2017
  6. Samuel LijinMay 1, 2017
  7. Junio C HamanoMay 2, 2017
  8. 0/7 Keep git clean -d from inadvertently removing ignored filesSamuel Lijin, May 3, 2017
  9. 1/7 t7300: skip untracked dirs containing ignored filesSamuel Lijin, May 3, 2017
  10. Stefan BellerMay 3, 2017
  11. Samuel LijinMay 3, 2017
  12. Stefan BellerMay 3, 2017
  13. 7/7 t7061: check for ignored file in untracked dirSamuel Lijin, May 3, 2017
  14. 5/7 dir: change linkage of cmp_name() and check_contains()Samuel Lijin, May 3, 2017
  15. 3/7 dir: add method to check if a dir_entry lexically contains anotherSamuel Lijin, May 3, 2017
  16. Stefan BellerMay 3, 2017
  17. 6/7 builtin/clean: teach clean -d to skip dirs containing ignored filesSamuel Lijin, May 3, 2017
  18. 2/7 dir: recurse into untracked dirs for ignored filesSamuel Lijin, May 3, 2017
  19. 4/7 dir: hide untracked contents of untracked dirsSamuel Lijin, May 3, 2017
  20. 0/9 Keep git clean -d from inadvertently removing ignored filesSamuel Lijin, May 5, 2017
  21. 1/9 t7300: skip untracked dirs containing ignored filesSamuel Lijin, May 5, 2017
  22. Torsten BögershausenMay 7, 2017
  23. Samuel LijinMay 8, 2017
  24. 2/9 t7061: expect failure where expected behavior will changeSamuel Lijin, May 5, 2017
  25. Junio C HamanoMay 8, 2017
  26. 4/9 dir: add method to check if a dir_entry lexically contains anotherSamuel Lijin, May 5, 2017
  27. 6/9 dir: change linkage of cmp_name() and check_contains()Samuel Lijin, May 5, 2017
  28. Junio C HamanoMay 8, 2017
  29. 3/9 dir: recurse into untracked dirs for ignored filesSamuel Lijin, May 5, 2017
  30. 7/9 builtin/clean: teach clean -d to skip dirs containing ignored filesSamuel Lijin, May 5, 2017
  31. 8/9 t7300: clean -d now skips untracked dirs containing ignored filesSamuel Lijin, May 5, 2017
  32. 5/9 dir: hide untracked contents of untracked dirsSamuel Lijin, May 5, 2017
  33. 9/9 t7061: expect ignored files in untracked dirsSamuel Lijin, May 5, 2017
  34. Junio C HamanoMay 8, 2017
  35. Junio C HamanoMay 8, 2017
  36. Samuel LijinMay 8, 2017
  37. Junio C HamanoMay 9, 2017
  38. 0/8 Fix clean -d and status --ignoredSamuel Lijin, May 16, 2017
  39. 1/8 t7300: clean -d should skip dirs with ignored filesSamuel Lijin, May 16, 2017
  40. 3/8 dir: recurse into untracked dirs for ignored filesSamuel Lijin, May 16, 2017
  41. Junio C HamanoMay 17, 2017
  42. Samuel LijinMay 17, 2017
  43. 2/8 t7061: status --ignored should search untracked dirsSamuel Lijin, May 16, 2017
  44. 4/8 dir: hide untracked contents of untracked dirsSamuel Lijin, May 16, 2017
  45. Junio C HamanoMay 17, 2017
  46. Samuel LijinMay 17, 2017
  47. Junio C HamanoMay 17, 2017
  48. 5/8 dir: expose cmp_name() and check_contains()Samuel Lijin, May 16, 2017
  49. 6/8 clean: teach clean -d to skip dirs containing ignored filesSamuel Lijin, May 16, 2017
  50. Junio C HamanoMay 18, 2017
  51. Samuel LijinMay 18, 2017
  52. 7/8 t7300: clean -d now skips untracked dirs containing ignored filesSamuel Lijin, May 16, 2017
  53. Junio C HamanoMay 18, 2017
  54. 8/8 t7061: status --ignored now searches untracked dirsSamuel Lijin, May 16, 2017
  55. Junio C HamanoMay 18, 2017
  56. 0/6 Fix clean -d and status --ignoredSamuel Lijin, May 18, 2017
  57. 1/6 t7300: clean -d should skip dirs with ignored filesSamuel Lijin, May 18, 2017
  58. 5/6 dir: expose cmp_name() and check_contains()Samuel Lijin, May 18, 2017
  59. Junio C HamanoMay 22, 2017
  60. 6/6 clean: teach clean -d to skip dirs containing ignored filesSamuel Lijin, May 18, 2017
  61. Junio C HamanoMay 22, 2017
  62. Samuel LijinMay 22, 2017
  63. Junio C HamanoMay 22, 2017
  64. Samuel LijinMay 23, 2017
  65. Junio C HamanoMay 23, 2017
  66. 3/6 dir: recurse into untracked dirs for ignored filesSamuel Lijin, May 18, 2017
  67. 2/6 t7061: status --ignored should search untracked dirsSamuel Lijin, May 18, 2017
  68. 4/6 dir: hide untracked contents of untracked dirsSamuel Lijin, May 18, 2017
  69. Junio C HamanoMay 22, 2017
  70. 0/6 Fix clean -d and status --ignoredSamuel Lijin, May 23, 2017
  71. 1/6 t7300: clean -d should skip dirs with ignored filesSamuel Lijin, May 23, 2017
  72. 2/6 t7061: status --ignored should search untracked dirsSamuel Lijin, May 23, 2017
  73. 3/6 dir: recurse into untracked dirs for ignored filesSamuel Lijin, May 23, 2017
  74. 5/6 dir: expose cmp_name() and check_contains()Samuel Lijin, May 23, 2017
  75. 4/6 dir: hide untracked contents of untracked dirsSamuel Lijin, May 23, 2017
  76. 6/6 clean: teach clean -d to preserve ignored pathsSamuel Lijin, May 23, 2017
  77. Junio C HamanoMay 23, 2017
  78. Samuel LijinMay 23, 2017
  79. 0/6 Fix clean -d and status --ignoredSamuel Lijin, May 23, 2017
  80. 1/6 t7300: clean -d should skip dirs with ignored filesSamuel Lijin, May 23, 2017
  81. 2/6 t7061: status --ignored should search untracked dirsSamuel Lijin, May 23, 2017
  82. 3/6 dir: recurse into untracked dirs for ignored filesSamuel Lijin, May 23, 2017
  83. 5/6 dir: expose cmp_name() and check_contains()Samuel Lijin, May 23, 2017
  84. 4/6 dir: hide untracked contents of untracked dirsSamuel Lijin, May 23, 2017
  85. 6/6 clean: teach clean -d to preserve ignored pathsSamuel Lijin, May 23, 2017
  86. Junio C HamanoMay 23, 2017
  87. Torsten BögershausenMay 24, 2017
  88. Samuel LijinMay 25, 2017
  89. Junio C HamanoMay 26, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.