Subject: Re: [RFC/PATCH] tag: make list exclude !<pattern>

From: Junio C Hamano <[email-masked]>
Date: Mon, 13 Feb 2012 12:29:58 -0800

Michael Haggerty <[email-masked]> writes:

>> Having said all that, if your argument against using "^" as negation for
>> for-each-ref *were* with something like this from the beginning:
>> 
>>     git rev-list --all --exclude-refs=refs/tags/v\*
>> 
>> it would have been very different. I would wholeheartedly buy the
>> consistency argument that says
>> 
>>     git for-each-ref --exclude-refs=refs/tags/v\*
>> 
>> ought to give all refs (only because for-each-ref "all" is implied) except
>> for the tagged tips, and
>> 
>>     git log --all --exclude-refs=refs/tags/v\*
>> 
>> should be the notation to produce consistently the same result as
>> 
>>     git log $(git for-each-ref --format='%(objectname)' --exclude-refs=refs/tags/v\*)
>> 
>> but if we used "^" as negated match in for-each-ref argument, we would
>> close the door to give such consistency to log family of commands later.
>
> That *has* been exactly my argument from the beginning [1].

Well, if the only thing you say is "rev-list A B ^C" and you are expecting
that your reader to substitute A with any dashed option like --all, --not
or --stdin, I would have to say you are expecting too much.  I wouldn't
even think of substituting A with $(git for-each-ref refs/heads/) in such
an example.

> I cautiously hope that we are now talking about the same thing, even if it
> is not yet clear whether we agree on a conclusion.

I think we are on the same page now.  Given that we seem to have settled
for the recent "find in the paths that pathspec matches, but exclude
matches from paths that match these patterns" topic by Albert Yale to
tentatively use separate --exclude [*1*] command line option instead of
mixing the negatives to the usual list of positives at the UI level, it
appears to me that the most sensible way forward would be to expose the
negative match to the UI level is to introduce a similar --exclude-refs on
the command line.

That would eventually allow us to say something like [*2*]:

	git log --all \
            --exclude-refs=refs/heads/experimental/* \
            --exclude-paths=compat/ \
	    --since=30.days \
            -- '*.c'

to ask for recent changes to all C sources outside the compat/ area for
everything except for the experimental topics.

[Footnote]

*1* It might be better to spell this as --exclude-paths, though, if we are
going to call this other exclude-refs-by-pattern --exclude-refs.  The
longer names would not bother us with the help of parse-options, and the
commands that need to support both, namely the commands in the log family,
need to allow users to be explicit which exclusion they want anyway, and
having --exclude vs --exclude-refs as options that work on different
dimensions look asymmetric.

*2* "something like" includes using a convenience short-hand on this
command line such as "--branches --exclude-branches=experimental/*"
instead of "--all --exclude-refs=...", but I consider that is icing on the
cake after the first step to define the overall structure settles, so I
would prefer not to go into the tangential details.