threads / bug / 28978

clean bug on ignored subdirectories with no tracked files?

Subject: clean bug on ignored subdirectories with no tracked files?

## tl;dr

7 messages between Nov 19, 2011 and Dec 1, 2011.

replies: 6people: 3as markdown or json

Jay Soffian· Nov 19, 2011, 05:38 UTC · lore

git init test_repo && cd test_repo && mkdir -p foo/bar && echo baz > foo/bar/baz && echo /foo/bar > .gitignore && git add .gitignore && git clean -n -d

Initialized empty Git repository in .../test_repo/.git/ Would remove foo/

Seems surprising. The work-around is either using '/foo' in the top-level .gitignore or adding a tracked file to the 'foo' directory.

j.
Junio C Hamano· Nov 19, 2011, 19:23 UTC · re: Jay Soffian · lore

Re: clean bug on ignored subdirectories with no tracked files?

Jay Soffian <jaysoffian@gmail.com> writes:
Show 12 quoted lines
> git init test_repo &&
> cd test_repo &&
> mkdir -p foo/bar &&
> echo baz > foo/bar/baz &&
> echo /foo/bar > .gitignore &&
> git add .gitignore &&
> git clean -n -d
>
> Initialized empty Git repository in .../test_repo/.git/
> Would remove foo/
>
> Seems surprising.

You said "everythingthing in foo/bar is uninteresting and can be cleaned", you have one untracked file in "foo/bar" hierarchy, and you have nothing else in "foo/" hierarchy.

Removing the uninteresting cruft as your .gitignore instructs Git makes the entire "foo/" hierarchy devoid of any contents. I would *expect* Git to clean "foo" in this case.

I've seen some "surprising" behaviour in "git clean" (which I do not use myself, I do not consider part of "my code", and I am not surprised if it has many bugs), but I fail to see what is surprising in your transcript.

It would be a different issue if you had ">foo/other" before your "clean". Then "foo/" has "foo/clean" that is not declared to be uninteresting.

Jay Soffian· Nov 21, 2011, 18:51 UTC · re: Junio C Hamano · lore

Re: clean bug on ignored subdirectories with no tracked files?

On Sat, Nov 19, 2011 at 2:23 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 18 quoted lines
> Jay Soffian <jaysoffian@gmail.com> writes:
>
>> git init test_repo &&
>> cd test_repo &&
>> mkdir -p foo/bar &&
>> echo baz > foo/bar/baz &&
>> echo /foo/bar > .gitignore &&
>> git add .gitignore &&
>> git clean -n -d
>>
>> Initialized empty Git repository in .../test_repo/.git/
>> Would remove foo/
>>
>> Seems surprising.
>
> You said "everythingthing in foo/bar is uninteresting and can be cleaned",
> you have one untracked file in "foo/bar" hierarchy, and you have nothing
> else in "foo/" hierarchy.

Just because it is uninteresting to git does not mean that it isn't precious. In this case the ignored files are from svn and checked out via another tool (gclient).

> Removing the uninteresting cruft as your .gitignore instructs Git makes
> the entire "foo/" hierarchy devoid of any contents. I would *expect* Git
> to clean "foo" in this case.

But .gitignore is not for indicating "this is cruft", it is for indicating "this is not under git's purview." You must admit that git clean's behavior above, if not surprising to you, is at least inconsistent with:

$ git init test_repo && cd test_repo && mkdir foo && touch foo/bar && echo /foo > .gitignore && git add .gitignore && git clean -n -d

which does protect foo (and its contents) from being cleaned.

git clean specifically has an option for "remove only the stuff which is ignored" which implies that it should not be removing ignored stuff w/o that option.

Show 6 quoted lines
> I've seen some "surprising" behaviour in "git clean" (which I do not use
> myself, I do not consider part of "my code", and I am not surprised if it
> has many bugs), but I fail to see what is surprising in your transcript.
>
> It would be a different issue if you had ">foo/other" before your "clean".
> Then "foo/" has "foo/clean" that is not declared to be uninteresting.

Huh? clean is designed to remove untracked unignored files, so I'd expect it to remove foo/other in that case. And what is this foo/clean to which you refer?

j.
Junio C Hamano· Nov 21, 2011, 19:02 UTC · re: Jay Soffian · lore

Re: clean bug on ignored subdirectories with no tracked files?

Jay Soffian <jaysoffian@gmail.com> writes:
> Just because it is uninteresting to git does not mean that it isn't
> precious.

That statement is false with the versions of Git so far. See the other thread for the current status and possible future directions.

Junio C Hamano· Nov 21, 2011, 19:28 UTC · re: Junio C Hamano · lore

Re: clean bug on ignored subdirectories with no tracked files?

Junio C Hamano <gitster@pobox.com> writes:
Show 7 quoted lines
> Jay Soffian <jaysoffian@gmail.com> writes:
>
>> Just because it is uninteresting to git does not mean that it isn't
>> precious.
>
> That statement is false with the versions of Git so far. See the other
> thread for the current status and possible future directions.

Oops, sorry, I was really confused. You are right that "ignored" for "clean" does not mean "they are not tracked and should be removed". That would result in removal of build artifacts '*.o' and unnecesary recompilation.

What "precious" means is a bit different, however. With verisons of Git so far, what "ignored" means is that they are not tracked, and _can_ be removed when needed to complete normal Git operations. When checking out another branch that has a tracked file at the same path as an untracked and ignored file in your current branch, removal of that ignored file is necessary to complete the checkout, and for that purpose, the ignored file is considered expendable. And we do not have a concept of "precious", unexpendable but untracked file, nor a way to specify that to gitignore mechanism (which is the topic of the other discussion thread).

"clean" without "-x" is meant to preserve untracked but expendable paths (e.g. build products), so if something is removed that is untracked but matches the ignore pattern, then that is a bug to be fixed. Care to roll a patch to fix it?

Sorry for the confusion, but as I said, I do not use (hence nor care much about) "clean" myself, so...

Jay Soffian· Nov 21, 2011, 20:03 UTC · re: Junio C Hamano · lore

Re: clean bug on ignored subdirectories with no tracked files?

On Mon, Nov 21, 2011 at 2:28 PM, Junio C Hamano <gitster@pobox.com> wrote:
> "clean" without "-x" is meant to preserve untracked but expendable paths
> (e.g. build products), so if something is removed that is untracked but
> matches the ignore pattern, then that is a bug to be fixed.  Care to roll
> a patch to fix it?

Okay, just confirming it is a bug. I'll add this e-mail to my todo list, but I don't have time for a patch anytime soon. :-(

> Sorry for the confusion, but as I said, I do not use (hence nor care much
> about) "clean" myself, so...
Okay.
j.
Phil Hord· Dec 1, 2011, 23:35 UTC · lore

Re: clean bug on ignored subdirectories with no tracked files?

On Mon, Nov 21, 2011 at 3:03 PM, Jay Soffian <jaysoffian@gmail.com> wrote:
Show 7 quoted lines
> On Mon, Nov 21, 2011 at 2:28 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> "clean" without "-x" is meant to preserve untracked but expendable paths
>> (e.g. build products), so if something is removed that is untracked but
>> matches the ignore pattern, then that is a bug to be fixed.  Care to roll
>> a patch to fix it?
> Okay, just confirming it is a bug. I'll add this e-mail to my todo
> list, but I don't have time for a patch anytime soon. 
I think the fix is in dir.c (treat_directory), but I'm not sure how yet.
How's this for starters?
-- >8 --
Subject: [PATCH] clean: Test known breakage of .gitignore and -d

git-clean -d is used to remove untracked directories. If the directory still contains .gitignored files it should not be removed. But git is broken here if neither the ignored files nor the directory are explicitly ignored.

Document this known breakage with a test for both cases.
Noticed-by: Jay Soffian <jaysoffian@gmail.com>
Signed-off-by: Phil Hord <hordp@cisco.com>
---
 t/t7300-clean.sh |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 800b536..e29e383 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -14,6 +14,7 @@ test_expect_success 'setup' '
 	mkdir -p src &&
 	touch src/part1.c Makefile &&
 	echo build >.gitignore &&
+	echo /foo/bar >>.gitignore &&
 	echo \*.o >>.gitignore &&
 	git add . &&
 	git commit -m setup &&
@@ -264,6 +265,20 @@ test_expect_success 'git clean -d src/ examples/' '
 
 '
 
+test_expect_failure 'git clean -d leaves .gitignored files alone' '
+
+	mkdir -p objs foo/bar &&
+	touch objs/foo.o &&
+	touch foo/gone &&
+	touch foo/bar/baz &&
+	git clean -nd &&
+	git clean -d &&
+	test ! -f foo/gone &&
+	test -f foo/bar/baz &&
+	test -f objs/foo.o
+
+'
+
 test_expect_success 'git clean -x' '
 
 	mkdir -p build docs &&
-- 
1.7.8.rc4

← back to recent threads