]> git.ipfire.org Git - thirdparty/git.git/commitdiff
hook: allow event = "" to overwrite previous values
authorAdrian Ratiu <adrian.ratiu@collabora.com>
Wed, 18 Feb 2026 22:23:50 +0000 (00:23 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 19 Feb 2026 21:23:41 +0000 (13:23 -0800)
Add the ability for empty events to clear previously set multivalue
variables, so the newly added "hook.*.event" behave like the other
multivalued keys.

Suggested-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config/hook.adoc
hook.c
t/t1800-hook.sh

index 0cda4745a6474e63dfe0506e1c6c140a49da9f6b..64e845a260380d29a6b85275f64bda631e0e6fd6 100644 (file)
@@ -12,7 +12,9 @@ hook.<name>.event::
        linkgit:githooks[5] for a complete list of hook events.) On the
        specified event, the associated `hook.<name>.command` is executed.
        This is a multi-valued key. To run `hook.<name>` on multiple
-       events, specify the key more than once. See linkgit:git-hook[1].
+       events, specify the key more than once. An empty value resets
+       the list of events, clearing any previously defined events for
+       `hook.<name>`. See linkgit:git-hook[1].
 
 hook.<name>.enabled::
        Whether the hook `hook.<name>` is enabled. Defaults to `true`.
diff --git a/hook.c b/hook.c
index 35c24bf33d73c99a2de5a644090999832e64e8d9..fee0a7ab4fcb4d6438744723fade1e12cb5502bf 100644 (file)
--- a/hook.c
+++ b/hook.c
@@ -147,18 +147,27 @@ static int hook_config_lookup_all(const char *key, const char *value,
        hook_name = xmemdupz(name, name_len);
 
        if (!strcmp(subkey, "event")) {
-               struct string_list *hooks =
-                       strmap_get(&data->event_hooks, value);
+               if (!*value) {
+                       /* Empty values reset previous events for this hook. */
+                       struct hashmap_iter iter;
+                       struct strmap_entry *e;
+
+                       strmap_for_each_entry(&data->event_hooks, &iter, e)
+                               unsorted_string_list_remove(e->value, hook_name);
+               } else {
+                       struct string_list *hooks =
+                               strmap_get(&data->event_hooks, value);
+
+                       if (!hooks) {
+                               hooks = xcalloc(1, sizeof(*hooks));
+                               string_list_init_dup(hooks);
+                               strmap_put(&data->event_hooks, value, hooks);
+                       }
 
-               if (!hooks) {
-                       hooks = xcalloc(1, sizeof(*hooks));
-                       string_list_init_dup(hooks);
-                       strmap_put(&data->event_hooks, value, hooks);
+                       /* Re-insert if necessary to preserve last-seen order. */
+                       unsorted_string_list_remove(hooks, hook_name);
+                       string_list_append(hooks, hook_name);
                }
-
-               /* Re-insert if necessary to preserve last-seen order. */
-               unsorted_string_list_remove(hooks, hook_name);
-               string_list_append(hooks, hook_name);
        } else if (!strcmp(subkey, "command")) {
                /* Store command overwriting the old value */
                char *old = strmap_put(&data->commands, hook_name,
index 9797802735e848368d35d9ebed13b3854da13f36..fb6bc554b9677e21ef91e903c97b8a5066d11f75 100755 (executable)
@@ -226,6 +226,18 @@ test_expect_success 'git hook list reorders on duplicate event declarations' '
        test_cmp expected actual
 '
 
+test_expect_success 'git hook list: empty event value resets events' '
+       setup_hooks &&
+
+       # ghi is configured for pre-commit; reset it with an empty value
+       test_config hook.ghi.event "" --add &&
+
+       # only def should remain for pre-commit
+       echo "def" >expected &&
+       git hook list pre-commit >actual &&
+       test_cmp expected actual
+'
+
 test_expect_success 'hook can be configured for multiple events' '
        setup_hooks &&