{"thread":{"id":"62918","subject":"git clean -Xdf affects parent and sibling directories","startedAt":"2025-02-07T20:40:04Z","lastAt":"2025-02-08T09:43:39Z","messageCount":3,"participants":["Jan Berges","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"512118","messageId":"7d2cf91f-c4ac-41de-966d-3681ac549ef0@uni-bremen.de","threadId":"62918","inReplyTo":null,"subject":"git clean -Xdf affects parent and sibling directories","fromName":"Jan Berges","fromEmail":"jan.berges@uni-bremen.de","sentAt":"2025-02-07T20:14:35Z","receivedAt":"2025-02-07T20:40:04Z","isPatch":false,"sender":{"key":"jan.berges@uni-bremen.de","avatar":null},"body":"Dear Git Developers,\n\nThis is probably not a bug, but a potentially dangerous behavior.\n\nWhat did you do before the bug happened? (Steps to reproduce your issue)\nRun git clean -Xdf in a subdirectory of a directory ignored by Git.\n\nWhat did you expect to happen? (Expected behavior)\nAll contents of this subdirectory are removed. From the man page:\n\"Cleans the working tree [...], starting from the current directory\"\n\nWhat happened instead? (Actual behavior)\nIgnored contents of parent and sibling directories are also removed.\n\nAnything else you want to add:\nThe behavior can be reproduced using the following lines.\n\nmkdir git_clean_test/\ncd git_clean_test/\n\ngit init -q\n\nmkdir -p dir1/sub1/\nmkdir -p dir1/sub2/\nmkdir -p dir2/sub1/\nmkdir -p dir2/sub2/\n\ntouch dir1/sub1/file\ntouch dir1/sub2/file\ntouch dir2/sub1/file\ntouch dir2/sub2/file\n\necho -e \"file\\ndir1\" > .gitignore\n\nfor dir in dir1/sub1/ dir2/sub1/\ndo\n     cd $dir\n     pwd\n     git clean -Xdn\n     cd ~-\ndone\n\nOutput of the above lines:\n\n/home/jan/git_clean_test/dir1/sub1\nWould refuse to remove current working directory\nWould remove ../sub1/file\nWould remove ../sub2\n/home/jan/git_clean_test/dir2/sub1\nWould refuse to remove current working directory\nWould remove ./file\n\nThanks and kind regards,\n\nJan\n\n[System Info]\ngit version:\ngit version 2.48.1.575.g74a3c43834\ncpu: x86_64\nbuilt from commit: 74a3c43834882219aa12aa1815d441a1762ba558\nsizeof-long: 8\nsizeof-size_t: 8\nshell-path: /bin/sh\nlibcurl: 7.88.1\nOpenSSL: OpenSSL 3.0.15 3 Sep 2024\nuname: Linux 6.1.0-30-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.124-1 \n(2025-01-12) x86_64\ncompiler info: gnuc: 12.2\nlibc info: glibc: 2.36\n$SHELL (typically, interactive shell): /bin/bash\n"},{"id":"512119","messageId":"xmqq4j15fnx1.fsf@gitster.g","threadId":"62918","inReplyTo":"7d2cf91f-c4ac-41de-966d-3681ac549ef0@uni-bremen.de","subject":"Re: git clean -Xdf affects parent and sibling directories","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-02-07T21:24:58Z","receivedAt":"2025-02-07T21:25:02Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jan Berges <jan.berges@uni-bremen.de> writes:\n\n> Run git clean -Xdf in a subdirectory of a directory ignored by Git.\n>\n> What did you expect to happen? (Expected behavior)\n> All contents of this subdirectory are removed. From the man page:\n> \"Cleans the working tree [...], starting from the current directory\"\n>\n> What happened instead? (Actual behavior)\n> Ignored contents of parent and sibling directories are also removed.\n\nInteresting observation.\n\nBehind Git as a whole, there is a philosophy to track the entire\nworking tree as a single unit, so touching a file at the top-level\nor in one subdirectory, going into a different subdirectory and\nrunning \"git status\" and \"git diff\" would show changes, in line with\nthe spirit of tracking the whole tree as a single unit, made to that\nfile outside your current directory.  Of course, if you add changes\nto a file at the top-level or a subdirectory, chdir to a different\nsubdirectory, touch some other files there, and say \"git commit -a\",\nthese changes outside your current directory would also be recorded.\n\nThe behaviour comes from the same principle.\n\nI think \"git grep\" is a notable oddball.  Its UI is build around the\nguess that end users would expect a similarity with vanilla \"grep\"\nrun with the \"-r\" option, so it only looks at the current directory\nor below.\n\nIn hindsight, some may argue that \"git clean\" should also be an\nexception, but I doubt that would have been a good UI even back\nthen, forcing end-users to remember which ones are always full-tree\noperation and which ones are current-directory-and-below.\n\nTo limit the extent of potential damage, I'd always do a dry run\nwith \"git clean -n\" first, giving other arguments I intend to give\nfor the real run, and then swap \"-n\" with \"-f\".  The command should\ntake the usual pathspec, so \"git clean .\" should work as expected.\n\nHTH.\n\n\n"},{"id":"512131","messageId":"111052b2-b64e-4146-b8eb-45ee27402ddc@uni-bremen.de","threadId":"62918","inReplyTo":"xmqq4j15fnx1.fsf@gitster.g","subject":"Re: git clean -Xdf affects parent and sibling directories","fromName":"Jan Berges","fromEmail":"jan.berges@uni-bremen.de","sentAt":"2025-02-08T09:43:36Z","receivedAt":"2025-02-08T09:43:39Z","isPatch":false,"sender":{"key":"jan.berges@uni-bremen.de","avatar":null},"body":"On 2/7/25 22:24, Junio C Hamano wrote:\n> The command should take the usual pathspec, so \"git clean .\" should work as expected.\n\nThank you for the explanations! I tried again with \"git clean -Xf -- .\" \nand this command still removes parent and sibling content. This seems to \nbe at odds with the manual: \"If any optional <pathspec>... arguments are \ngiven, only those paths that match the pathspec are affected.\"\n\nAs far as I can see, if <pathspec> is untracked and ignored, the command \ngoes to the topmost ignored directory of the tree and cleans from there.\n\nIn the worst case, GIT_WORK_TREE=$HOME, GIT_DIR tracks dotfiles, and all \nother directories such as ~/Documents/ are ignored. Running the command \nin ~/Documents/path/to/another/repository/ would remove everything under \n~/Documents/. (This is not exactly what I did; I did not lose any files. \nIn any case, thanks for the advice to always do a dry run first!)\n\nJan\n"}]}