ref-filter: add --no-contains option to tag/branch/for-each-ref
authorÆvar Arnfjörð Bjarmason <avarab@gmail.com>
Fri, 24 Mar 2017 18:40:57 +0000 (18:40 +0000)
committerJunio C Hamano <gitster@pobox.com>
Fri, 24 Mar 2017 19:15:26 +0000 (12:15 -0700)
commitac3f5a346860b824e083c5d305757c3260565475
treeb1dfdaaf848507f24dbd84a17936da3482975819
parent1e0c3b680c6e7b37fc51bd69a410af01897a4f94
ref-filter: add --no-contains option to tag/branch/for-each-ref

Change the tag, branch & for-each-ref commands to have a --no-contains
option in addition to their longstanding --contains options.

This allows for finding the last-good rollout tag given a known-bad
<commit>. Given a hypothetically bad commit cf5c7253e0, the git
version to revert to can be found with this hacky two-liner:

    (git tag -l 'v[0-9]*'; git tag -l --contains cf5c7253e0 'v[0-9]*') |
        sort | uniq -c | grep -E '^ *1 ' | awk '{print $2}' | tail -n 10

With this new --no-contains option the same can be achieved with:

    git tag -l --no-contains cf5c7253e0 'v[0-9]*' | sort | tail -n 10

As the filtering machinery is shared between the tag, branch &
for-each-ref commands, implement this for those commands too. A
practical use for this with "branch" is e.g. finding branches which
were branched off between v2.8.0 and v2.10.0:

    git branch --contains v2.8.0 --no-contains v2.10.0

The "describe" command also has a --contains option, but its semantics
are unrelated to what tag/branch/for-each-ref use --contains for. A
--no-contains option for "describe" wouldn't make any sense, other
than being exactly equivalent to not supplying --contains at all,
which would be confusing at best.

Add a --without option to "tag" as an alias for --no-contains, for
consistency with --with and --contains.  The --with option is
undocumented, and possibly the only user of it is
Junio (<xmqqefy71iej.fsf@gitster.mtv.corp.google.com>). But it's
trivial to support, so let's do that.

The additions to the the test suite are inverse copies of the
corresponding --contains tests. With this change --no-contains for
tag, branch & for-each-ref is just as well tested as the existing
--contains option.

In addition to those tests, add a test for "tag" which asserts that
--no-contains won't find tree/blob tags, which is slightly
unintuitive, but consistent with how --contains works & is documented.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
13 files changed:
Documentation/git-branch.txt
Documentation/git-for-each-ref.txt
Documentation/git-tag.txt
builtin/branch.c
builtin/for-each-ref.c
builtin/tag.c
contrib/completion/git-completion.bash
parse-options.h
ref-filter.c
ref-filter.h
t/t3201-branch-contains.sh
t/t6302-for-each-ref-filter.sh
t/t7004-tag.sh