[PATCH] describe: fix --exclude, --match with --contains and --all
- From
Jacob Keller <jacob.e.keller@intel.com>
- Date
- May 28, 2026, 23:29 UTC
- Message-ID
- <20260528232950.187002-2-jacob.e.keller@intel.com>
From: Jacob Keller <jacob.keller@gmail.com>
git describe --contains acts as a wrapper around git name-rev. When operating with --contains and --all, the --match and --exclude patterns are not properly forwarded to name-rev as --exclude and --refs options.
This results in the command silently discarding match and exclude requests from the user when operating in --all mode.
We could check and die() if the user provides --contains, --all, and --match/--exclude. However, its also straight forward to just pass the filters down to git name-rev.
Notice that the documentation for --match and --exclude mention the --all mode. It explains that they operate on refs with the prefix refs/tags, and additionally refs/heads and refs/remotes when using --all.
Fix the describe logic to pass the patterns down with the appropriate prefixes when --all is provided. This fixes the support to match the documented behavior.
Add tests to check that this works as expected.
Reported-by: Tuomas Ahola <taahol@utu.fi> Signed-off-by: Jacob Keller <jacob.keller@gmail.com> ---
I was looking into reviving the patch that just added a simple die() and realized that its actually pretty straight forward to just fix the support instead. I'm open to either route, if we think this support isn't necessary... I'm not sure if there are any gotchas or other issues with how I implemented this.
builtin/describe.c | 18 +++++++++++++++--- t/t6120-describe.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/builtin/describe.c b/builtin/describe.c index 1c47d7c0b7c3..faaf44cec573 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -712,13 +712,25 @@ int cmd_describe(int argc, NULL); if (always) strvec_push(&args, "--always"); - if (!all) { + if (!all) strvec_push(&args, "--tags"); + + for_each_string_list_item(item, &patterns) + strvec_pushf(&args, "--refs=refs/tags/%s", item->string); + for_each_string_list_item(item, &exclude_patterns) + strvec_pushf(&args, "--exclude=refs/tags/%s", item->string); + + if (all) { for_each_string_list_item(item, &patterns) - strvec_pushf(&args, "--refs=refs/tags/%s", item->string); + strvec_pushf(&args, "--refs=refs/heads/%s", item->string); for_each_string_list_item(item, &exclude_patterns) - strvec_pushf(&args, "--exclude=refs/tags/%s", item->string); + strvec_pushf(&args, "--exclude=refs/heads/%s", item->string); + for_each_string_list_item(item, &patterns) + strvec_pushf(&args, "--refs=refs/remotes/%s", item->string); + for_each_string_list_item(item, &exclude_patterns) + strvec_pushf(&args, "--exclude=refs/remotes/%s", item->string); } + if (argc) strvec_pushv(&args, argv); else diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 8ee3d2c37d02..f46e628d6a1a 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -359,6 +359,35 @@ test_expect_success 'describe --contains and --no-match' ' test_cmp expect actual ' +test_expect_success 'describe --contains --all --match' ' + echo "tags/A^0" >expect && + tagged_commit=$(git rev-parse "refs/tags/A^0") && + test_must_fail git describe --contains --all --match="B" $tagged_commit >actual && + git describe --contains --all --match="A" $tagged_commit >actual && + test_cmp expect actual +' + +test_expect_success 'describe --contains --all --match branch' ' + echo "branch_A" >expect && + tagged_commit=$(git rev-parse "refs/tags/A^0") && + git describe --contains --all --match="branch*" $tagged_commit >actual && + test_cmp expect actual +' + +test_expect_success 'describe --contains --all --match and --exclude' ' + echo "branch_C~1" >expect && + tagged_commit=$(git rev-parse "refs/tags/A^0") && + git describe --contains --all --match="branch*" --exclude="branch_A" $tagged_commit >actual && + test_cmp expect actual +' + +test_expect_success 'describe --contains --all --exclude' ' + echo "branch_A" >expect && + tagged_commit=$(git rev-parse "refs/tags/A^0") && + git describe --contains --all --exclude="A" --exclude="c" --exclude="test*" $tagged_commit >actual && + test_cmp expect actual +' + test_expect_success 'setup and absorb a submodule' ' test_create_repo sub1 && test_commit -C sub1 initial &&
-- 2.54.0.633.g0ded84c31b89