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

Re: git clean --exclude broken?

From
Junio C Hamano <gitster@pobox.com>
Date
Aug 25, 2011, 01:38 UTC
Message-ID
<7vfwkqmfsh.fsf@alter.siamese.dyndns.org>
In-Reply-To
<7vliuio65w.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
Show 15 quoted lines
> Todd Rinaldo <toddr@cpanel.net> writes:
>
>> I think I have found a new bug in 1.7.5:
>
> My quick check indicates 1.7.3 behaves the same way, and 1.7.2.5 didn't
> have --exclude option, so this does not seem to be anything particularly
> new in the 1.7.5 release.
>
>> # The problem (Why is foo/ removed?)
>> $>git clean -dXf --exclude=/foo
>> Removing bar/
>> Removing foo/
>
> Why is this command line giving -X that tells us not to use the ignore
> rules, and --exclude option at the same time?

The documentation and the implementation of "git clean" is quite confused. Here is what is said about "-e":

    -e <pattern>::
    --exclude=<pattern>::
            Specify special exceptions to not be cleaned.  Each <pattern> is
            the same form as in $GIT_DIR/info/excludes and this option can be
            given multiple times.

But in reality, it is not about "not be cleaned" at all. A better description to reflect what the implementation actually does is probably this:

	In addition to what are found in usual places like .gitignore (per
	directory) and $GIT_DIR/info/exclude, consider these patterns to
	be in the ignore rules.
This mirrors what --exclude parameter to "ls-files" does [*1*].

I can however see a use case where the user wants to say something like this which is quite different:

	I know "git clean" (or "git clean -x" or "git clean -X") will try
	to remove paths A, B and C. I want it remove them except for this
	particular path C by adding --except=C option to the command line.

And the current documentation does look like it is describing such an option. But that is not what --exclude option is about.

One solution might be to say "I know the usual rules stored in .gitignore and the like tell us to that 'foo' is ignored (and to be cleaned), but for this invocation only, please treat 'foo' is _not_ ignored.", and there indeed is a way to do so:

    $ git clean -d -X -e \!foo
(the backslash before '!' is to avoid history substitution in some shells).
[Footnote]
*1* This part in builtin/clean.c looks a bit distasteful:
	for (i = 0; i < exclude_list.nr; i++)
		add_exclude(exclude_list.items[i].string, "", 0, dir.exclude_list);

The last parameter should be &dir.exclude_list[EXC_CMDL] because we are adding exclude patterns from the command line. It works by accident only because EXC_CMDL happens to be defined as 0.

Previous: Todd RinaldoNext: Junio C Hamano
Message 4 of 11 in “git clean --exclude broken?”
  1. Todd RinaldoAug 24, 2011
  2. Junio C HamanoAug 24, 2011
  3. Todd RinaldoAug 24, 2011
  4. Junio C HamanoAug 25, 2011
  5. Re* git clean --exclude broken?Junio C Hamano, Aug 25, 2011
  6. Michael SchubertAug 25, 2011
  7. Junio C HamanoAug 25, 2011
  8. Thomas RastAug 26, 2011
  9. Pete WyckoffAug 27, 2011
  10. Junio C HamanoAug 28, 2011
  11. Pete WyckoffAug 28, 2011

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.