{"thread":{"id":"63389","subject":"[PATCH 0/1] New remote groups subcommand","startedAt":"2025-05-03T16:10:04Z","lastAt":"2025-05-05T16:32:22Z","messageCount":4,"participants":["Lazar Sumar","rsbecker@nexbridge.com","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":1},"messages":[{"id":"517175","messageId":"20250503160953.196329-1-bugzilla@lazar.co.nz","threadId":"63389","inReplyTo":null,"subject":"[PATCH 0/1] New remote groups subcommand","fromName":"Lazar Sumar","fromEmail":"sumar@lazar.co.nz","sentAt":"2025-05-03T16:09:51Z","receivedAt":"2025-05-03T16:10:04Z","isPatch":true,"sender":{"key":"sumar@lazar.co.nz","avatar":null},"body":"First submission, any guidance is appreciated.\n\nHaving recently started using remote groups I have found the feature to\nbe missing:\n\n  * bash completion\n  * easy listing functionality\n  * remote renames don't update group members with the rename (tricky)\n\nThis patch aims to fix the bash completion and simplify listing remote\ngroups by adding a `git remote group` subcommand.\n\nNote: the bash completion can be solved without the subcommand, using\nsomething like:\n\n    `git config --get-regexp 'remotes\\.' | awk ...\n\nbut if this feature is intended to be supported then giving it a subcommand\nfelt like the better approach.\n\nLastly, I wanted to at least add a test for the expected behavior of\nremote grups when a remote is renamed but found the current behavior\nsurprising, i.e.\n\n    $ git config --get-regexp 'remotes\\.'\n    file:.git/config        remotes.group1 upstream origin\n    $ git remote rename origin fork\n    Renaming remote references: 100% (8/8), done.\n    $ git config --get-regexp 'remotes\\.'\n    file:.git/config        remotes.group1 upstream origin\n\nThe remote group is defined in the local config file and I would expect\nthe rename to rename the group member here. However, should the group\nhave been defined in the global `~/.gitconfig` the current behavior\nmakes perfect sense.\n\nAs this was unclear, I decided not to include it in this patch series\nbut considering that the area I am touching is the same, any comments\nwould be appreciated. If we reach a conclusion I'm happy to create a new\npatch series to follow up on this.\n\nLazar Sumar (1):\n  Add git remote group sub-command\n\n Documentation/git-remote.adoc          |  6 ++++\n builtin/remote.c                       | 47 ++++++++++++++++++++++++++\n contrib/completion/git-completion.bash | 21 ++++++++++--\n t/t5506-remote-groups.sh               | 31 +++++++++++++++++\n 4 files changed, 103 insertions(+), 2 deletions(-)\n\n\nbase-commit: f65182a99e545d2f2bc22e6c1c2da192133b16a3\n-- \n2.49.0.460.g0390bdefd0.dirty\n\n"},{"id":"517176","messageId":"20250503160953.196329-2-bugzilla@lazar.co.nz","threadId":"63389","inReplyTo":"20250503160953.196329-1-bugzilla@lazar.co.nz","subject":"[PATCH 1/1] Add git remote group sub-command","fromName":"Lazar Sumar","fromEmail":"sumar@lazar.co.nz","sentAt":"2025-05-03T16:09:52Z","receivedAt":"2025-05-03T16:10:17Z","isPatch":true,"sender":{"key":"sumar@lazar.co.nz","avatar":null},"body":"Remote groups are an existing feature of git presently managed\nexclusively via the config. This patch gives them their own subcommand\nfor listing the existing groups with the intent of adding future\nsubcommands under it for adding/updating/removing groups.\n\nAs a side-effect this command can now be used in bash tab completion for\nthe fetch command which did not offer them as a completion option\npreviously. Note that the push command does not accept remote groups as\nan argument.\n\nSigned-off-by: Lazar Sumar <bugzilla@lazar.co.nz>\n---\n Documentation/git-remote.adoc          |  6 ++++\n builtin/remote.c                       | 47 ++++++++++++++++++++++++++\n contrib/completion/git-completion.bash | 21 ++++++++++--\n t/t5506-remote-groups.sh               | 31 +++++++++++++++++\n 4 files changed, 103 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-remote.adoc b/Documentation/git-remote.adoc\nindex 932a5c3ea4..87ddda8d58 100644\n--- a/Documentation/git-remote.adoc\n+++ b/Documentation/git-remote.adoc\n@@ -22,6 +22,7 @@ SYNOPSIS\n 'git remote' [-v | --verbose] 'show' [-n] <name>...\n 'git remote prune' [-n | --dry-run] <name>...\n 'git remote' [-v | --verbose] 'update' [-p | --prune] [(<group> | <remote>)...]\n+'git remote group'\n \n DESCRIPTION\n -----------\n@@ -197,6 +198,11 @@ be updated.  (See linkgit:git-config[1]).\n +\n With `--prune` option, run pruning against all the remotes that are updated.\n \n+'group'::\n+\n+List all configured remote groups. The remote groups configuration is achieved\n+using the `remotes.<group>` configuration variables.  (See\n+linkgit:git-config[1]).\n \n DISCUSSION\n ----------\ndiff --git a/builtin/remote.c b/builtin/remote.c\nindex b4baa34e66..2217447230 100644\n--- a/builtin/remote.c\n+++ b/builtin/remote.c\n@@ -28,6 +28,7 @@ static const char * const builtin_remote_usage[] = {\n \tN_(\"git remote [-v | --verbose] show [-n] <name>\"),\n \tN_(\"git remote prune [-n | --dry-run] <name>\"),\n \tN_(\"git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]\"),\n+\tN_(\"git remote group\"),\n \tN_(\"git remote set-branches [--add] <name> <branch>...\"),\n \tN_(\"git remote get-url [--push] [--all] <name>\"),\n \tN_(\"git remote set-url [--push] <name> <newurl> [<oldurl>]\"),\n@@ -77,6 +78,11 @@ static const char * const builtin_remote_update_usage[] = {\n \tNULL\n };\n \n+static const char * const builtin_remote_group_usage[] = {\n+\tN_(\"git remote group\"),\n+\tNULL\n+};\n+\n static const char * const builtin_remote_geturl_usage[] = {\n \tN_(\"git remote get-url [--push] [--all] <name>\"),\n \tNULL\n@@ -1633,6 +1639,46 @@ static int update(int argc, const char **argv, const char *prefix,\n \treturn run_command(&cmd);\n }\n \n+static int get_remote_group(const char *key, const char *value UNUSED,\n+\t\t\t    const struct config_context *ctx UNUSED,\n+\t\t\t    void *priv)\n+{\n+\tstruct string_list *remote_group_list = priv;\n+\n+\tif (skip_prefix(key, \"remotes.\", &key)) {\n+\t\tsize_t wordlen = strlen(key);\n+\t\tif (wordlen >= 1)\n+\t\t\tstring_list_append_nodup(remote_group_list,\n+\t\t\t\t\t\txstrndup(key, wordlen));\n+\t}\n+\tstring_list_remove_duplicates(remote_group_list, 0);\n+\n+\treturn 0;\n+}\n+\n+static int group(int argc, const char **argv, const char *prefix,\n+\tstruct repository *repo UNUSED)\n+{\n+\tstruct string_list remote_group_list = STRING_LIST_INIT_DUP;\n+\tstruct option options[] = {\n+\t\tOPT_END()\n+\t};\n+\n+\targc = parse_options(argc, argv, prefix, options,\n+\t\tbuiltin_remote_group_usage, 0);\n+\tif (argc != 0)\n+\t\tusage_with_options(builtin_remote_group_usage, options);\n+\n+\tgit_config(get_remote_group, &remote_group_list);\n+\tfor (int i = 0; i < remote_group_list.nr; i++) {\n+\t\tconst char *name = remote_group_list.items[i].string;\n+\t\tprintf_ln(_(\"%s\"), name);\n+\t}\n+\tstring_list_clear(&remote_group_list, 0);\n+\n+\treturn 0;\n+}\n+\n static int remove_all_fetch_refspecs(const char *key)\n {\n \treturn git_config_set_multivar_gently(key, NULL, NULL,\n@@ -1844,6 +1890,7 @@ int cmd_remote(int argc,\n \t\tOPT_SUBCOMMAND(\"show\", &fn, show),\n \t\tOPT_SUBCOMMAND(\"prune\", &fn, prune),\n \t\tOPT_SUBCOMMAND(\"update\", &fn, update),\n+\t\tOPT_SUBCOMMAND(\"group\", &fn, group),\n \t\tOPT_END()\n \t};\n \ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex e3d88b0672..658bea9d96 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1050,6 +1050,17 @@ __git_remotes ()\n \t__git remote\n }\n \n+__git_remote_groups ()\n+{\n+\t__git remote group\n+}\n+\n+__git_remotes_or_groups ()\n+{\n+\t__git_remotes\n+\t__git_remote_groups\n+}\n+\n # Returns true if $1 matches the name of a configured remote, false otherwise.\n __git_is_configured_remote ()\n {\n@@ -1181,7 +1192,10 @@ __git_complete_remote_or_refspec ()\n \t\t((c++))\n \tdone\n \tif [ -z \"$remote\" ]; then\n-\t\t__gitcomp_nl \"$(__git_remotes)\"\n+\t\tcase \"$cmd\" in\n+\t\tpush) __gitcomp_nl \"$(__git_remotes)\" ;;\n+\t\t*) __gitcomp_nl \"$(__git_remotes_or_groups)\" ;;\n+\t\tesac\n \t\treturn\n \tfi\n \tif [ $no_complete_refspec = 1 ]; then\n@@ -3073,7 +3087,7 @@ _git_remote ()\n {\n \tlocal subcommands=\"\n \t\tadd rename remove set-head set-branches\n-\t\tget-url set-url show prune update\n+\t\tget-url set-url show prune update group\n \t\t\"\n \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n \tif [ -z \"$subcommand\" ]; then\n@@ -3109,6 +3123,9 @@ _git_remote ()\n \tupdate,*)\n \t\t__gitcomp \"$(__git_remotes) $(__git_get_config_variables \"remotes\")\"\n \t\t;;\n+\tgroup,--*)\n+\t\t__gitcomp_builtin remote_group\n+\t\t;;\n \tset-url,--*)\n \t\t__gitcomp_builtin remote_set-url\n \t\t;;\ndiff --git a/t/t5506-remote-groups.sh b/t/t5506-remote-groups.sh\nindex 16e9a1bc2f..7859e6805b 100755\n--- a/t/t5506-remote-groups.sh\n+++ b/t/t5506-remote-groups.sh\n@@ -31,6 +31,12 @@ repo_fetched() {\n \treturn 1\n }\n \n+check_groups() {\n+\techo $@ | sort >expected_groups;\n+\tgit remote group | sort >listed_groups;\n+\tgit diff --no-index --quiet expected_groups listed_groups\n+}\n+\n test_expect_success 'setup' '\n \tmkdir one && (cd one && git init) &&\n \tmkdir two && (cd two && git init) &&\n@@ -64,6 +70,12 @@ test_expect_success 'updating group updates all members (remote update)' '\n \trepo_fetched two\n '\n \n+test_expect_success 'prints the configured group \"all\" once (remote group)' '\n+\techo \"all\" >expect &&\n+\ttest_expect_code 0 git remote group 1>actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'updating group updates all members (fetch)' '\n \tmark fetch-group-all &&\n \tupdate_repos &&\n@@ -81,6 +93,15 @@ test_expect_success 'updating group does not update non-members (remote update)'\n \t! repo_fetched two\n '\n \n+test_expect_success 'prints configured groups \"all\" and \"some\" (remote group)' '\n+\tcat >expect <<-EOF &&\n+\tall\n+\tsome\n+\tEOF\n+\ttest_expect_code 0 git remote group 1>actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'updating group does not update non-members (fetch)' '\n \tmark fetch-group-some &&\n \tupdate_repos &&\n@@ -107,4 +128,14 @@ test_expect_success 'updating group in parallel with a duplicate remote does not\n \trepo_fetched one\n '\n \n+test_expect_success 'groups are printed in order of configuration (remote group)' '\n+\tcat >expect <<-EOF &&\n+\tall\n+\tsome\n+\tduplicate\n+\tEOF\n+\ttest_expect_code 0 git remote group 1>actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_done\n-- \n2.49.0.460.g0390bdefd0.dirty\n\n"},{"id":"517177","messageId":"001401dbbc4f$98c8db20$ca5a9160$@nexbridge.com","threadId":"63389","inReplyTo":"20250503160953.196329-2-bugzilla@lazar.co.nz","subject":"RE: [PATCH 1/1] Add git remote group sub-command","fromName":"","fromEmail":"rsbecker@nexbridge.com","sentAt":"2025-05-03T17:19:52Z","receivedAt":"2025-05-03T17:21:46Z","isPatch":true,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On May 3, 2025 12:10 PM, Lazar Sumar wrote:\n>Remote groups are an existing feature of git presently managed exclusively via the\n>config. This patch gives them their own subcommand for listing the existing groups\n>with the intent of adding future subcommands under it for\n>adding/updating/removing groups.\n\nCan you expand on the primary use case, please? Specifically the implications of what\nThe group subcommand not only does but the side effects of using it.\n\nThanks.\n\n>As a side-effect this command can now be used in bash tab completion for the fetch\n>command which did not offer them as a completion option previously. Note that\n>the push command does not accept remote groups as an argument.\n>\n>Signed-off-by: Lazar Sumar <bugzilla@lazar.co.nz>\n>---\n> Documentation/git-remote.adoc          |  6 ++++\n> builtin/remote.c                       | 47 ++++++++++++++++++++++++++\n> contrib/completion/git-completion.bash | 21 ++++++++++--\n> t/t5506-remote-groups.sh               | 31 +++++++++++++++++\n> 4 files changed, 103 insertions(+), 2 deletions(-)\n>\n>diff --git a/Documentation/git-remote.adoc b/Documentation/git-remote.adoc\n>index 932a5c3ea4..87ddda8d58 100644\n>--- a/Documentation/git-remote.adoc\n>+++ b/Documentation/git-remote.adoc\n>@@ -22,6 +22,7 @@ SYNOPSIS\n> 'git remote' [-v | --verbose] 'show' [-n] <name>...\n> 'git remote prune' [-n | --dry-run] <name>...\n> 'git remote' [-v | --verbose] 'update' [-p | --prune] [(<group> | <remote>)...]\n>+'git remote group'\n>\n> DESCRIPTION\n> -----------\n>@@ -197,6 +198,11 @@ be updated.  (See linkgit:git-config[1]).\n> +\n> With `--prune` option, run pruning against all the remotes that are updated.\n>\n>+'group'::\n>+\n>+List all configured remote groups. The remote groups configuration is\n>+achieved using the `remotes.<group>` configuration variables.  (See\n>+linkgit:git-config[1]).\n>\n> DISCUSSION\n> ----------\n>diff --git a/builtin/remote.c b/builtin/remote.c index b4baa34e66..2217447230\n>100644\n>--- a/builtin/remote.c\n>+++ b/builtin/remote.c\n>@@ -28,6 +28,7 @@ static const char * const builtin_remote_usage[] = {\n> \tN_(\"git remote [-v | --verbose] show [-n] <name>\"),\n> \tN_(\"git remote prune [-n | --dry-run] <name>\"),\n> \tN_(\"git remote [-v | --verbose] update [-p | --prune] [(<group> |\n><remote>)...]\"),\n>+\tN_(\"git remote group\"),\n> \tN_(\"git remote set-branches [--add] <name> <branch>...\"),\n> \tN_(\"git remote get-url [--push] [--all] <name>\"),\n> \tN_(\"git remote set-url [--push] <name> <newurl> [<oldurl>]\"), @@ -77,6\n>+78,11 @@ static const char * const builtin_remote_update_usage[] = {\n> \tNULL\n> };\n>\n>+static const char * const builtin_remote_group_usage[] = {\n>+\tN_(\"git remote group\"),\n>+\tNULL\n>+};\n>+\n> static const char * const builtin_remote_geturl_usage[] = {\n> \tN_(\"git remote get-url [--push] [--all] <name>\"),\n> \tNULL\n>@@ -1633,6 +1639,46 @@ static int update(int argc, const char **argv, const char\n>*prefix,\n> \treturn run_command(&cmd);\n> }\n>\n>+static int get_remote_group(const char *key, const char *value UNUSED,\n>+\t\t\t    const struct config_context *ctx UNUSED,\n>+\t\t\t    void *priv)\n>+{\n>+\tstruct string_list *remote_group_list = priv;\n>+\n>+\tif (skip_prefix(key, \"remotes.\", &key)) {\n>+\t\tsize_t wordlen = strlen(key);\n>+\t\tif (wordlen >= 1)\n>+\t\t\tstring_list_append_nodup(remote_group_list,\n>+\t\t\t\t\t\txstrndup(key, wordlen));\n>+\t}\n>+\tstring_list_remove_duplicates(remote_group_list, 0);\n>+\n>+\treturn 0;\n>+}\n>+\n>+static int group(int argc, const char **argv, const char *prefix,\n>+\tstruct repository *repo UNUSED)\n>+{\n>+\tstruct string_list remote_group_list = STRING_LIST_INIT_DUP;\n>+\tstruct option options[] = {\n>+\t\tOPT_END()\n>+\t};\n>+\n>+\targc = parse_options(argc, argv, prefix, options,\n>+\t\tbuiltin_remote_group_usage, 0);\n>+\tif (argc != 0)\n>+\t\tusage_with_options(builtin_remote_group_usage, options);\n>+\n>+\tgit_config(get_remote_group, &remote_group_list);\n>+\tfor (int i = 0; i < remote_group_list.nr; i++) {\n>+\t\tconst char *name = remote_group_list.items[i].string;\n>+\t\tprintf_ln(_(\"%s\"), name);\n>+\t}\n>+\tstring_list_clear(&remote_group_list, 0);\n>+\n>+\treturn 0;\n>+}\n>+\n> static int remove_all_fetch_refspecs(const char *key)  {\n> \treturn git_config_set_multivar_gently(key, NULL, NULL, @@ -1844,6\n>+1890,7 @@ int cmd_remote(int argc,\n> \t\tOPT_SUBCOMMAND(\"show\", &fn, show),\n> \t\tOPT_SUBCOMMAND(\"prune\", &fn, prune),\n> \t\tOPT_SUBCOMMAND(\"update\", &fn, update),\n>+\t\tOPT_SUBCOMMAND(\"group\", &fn, group),\n> \t\tOPT_END()\n> \t};\n>\n>diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-\n>completion.bash\n>index e3d88b0672..658bea9d96 100644\n>--- a/contrib/completion/git-completion.bash\n>+++ b/contrib/completion/git-completion.bash\n>@@ -1050,6 +1050,17 @@ __git_remotes ()\n> \t__git remote\n> }\n>\n>+__git_remote_groups ()\n>+{\n>+\t__git remote group\n>+}\n>+\n>+__git_remotes_or_groups ()\n>+{\n>+\t__git_remotes\n>+\t__git_remote_groups\n>+}\n>+\n> # Returns true if $1 matches the name of a configured remote, false otherwise.\n> __git_is_configured_remote ()\n> {\n>@@ -1181,7 +1192,10 @@ __git_complete_remote_or_refspec ()\n> \t\t((c++))\n> \tdone\n> \tif [ -z \"$remote\" ]; then\n>-\t\t__gitcomp_nl \"$(__git_remotes)\"\n>+\t\tcase \"$cmd\" in\n>+\t\tpush) __gitcomp_nl \"$(__git_remotes)\" ;;\n>+\t\t*) __gitcomp_nl \"$(__git_remotes_or_groups)\" ;;\n>+\t\tesac\n> \t\treturn\n> \tfi\n> \tif [ $no_complete_refspec = 1 ]; then\n>@@ -3073,7 +3087,7 @@ _git_remote ()\n> {\n> \tlocal subcommands=\"\n> \t\tadd rename remove set-head set-branches\n>-\t\tget-url set-url show prune update\n>+\t\tget-url set-url show prune update group\n> \t\t\"\n> \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n> \tif [ -z \"$subcommand\" ]; then\n>@@ -3109,6 +3123,9 @@ _git_remote ()\n> \tupdate,*)\n> \t\t__gitcomp \"$(__git_remotes) $(__git_get_config_variables\n>\"remotes\")\"\n> \t\t;;\n>+\tgroup,--*)\n>+\t\t__gitcomp_builtin remote_group\n>+\t\t;;\n> \tset-url,--*)\n> \t\t__gitcomp_builtin remote_set-url\n> \t\t;;\n>diff --git a/t/t5506-remote-groups.sh b/t/t5506-remote-groups.sh index\n>16e9a1bc2f..7859e6805b 100755\n>--- a/t/t5506-remote-groups.sh\n>+++ b/t/t5506-remote-groups.sh\n>@@ -31,6 +31,12 @@ repo_fetched() {\n> \treturn 1\n> }\n>\n>+check_groups() {\n>+\techo $@ | sort >expected_groups;\n>+\tgit remote group | sort >listed_groups;\n>+\tgit diff --no-index --quiet expected_groups listed_groups }\n>+\n> test_expect_success 'setup' '\n> \tmkdir one && (cd one && git init) &&\n> \tmkdir two && (cd two && git init) &&\n>@@ -64,6 +70,12 @@ test_expect_success 'updating group updates all members\n>(remote update)' '\n> \trepo_fetched two\n> '\n>\n>+test_expect_success 'prints the configured group \"all\" once (remote group)' '\n>+\techo \"all\" >expect &&\n>+\ttest_expect_code 0 git remote group 1>actual &&\n>+\ttest_cmp expect actual\n>+'\n>+\n> test_expect_success 'updating group updates all members (fetch)' '\n> \tmark fetch-group-all &&\n> \tupdate_repos &&\n>@@ -81,6 +93,15 @@ test_expect_success 'updating group does not update non-\n>members (remote update)'\n> \t! repo_fetched two\n> '\n>\n>+test_expect_success 'prints configured groups \"all\" and \"some\" (remote group)' '\n>+\tcat >expect <<-EOF &&\n>+\tall\n>+\tsome\n>+\tEOF\n>+\ttest_expect_code 0 git remote group 1>actual &&\n>+\ttest_cmp expect actual\n>+'\n>+\n> test_expect_success 'updating group does not update non-members (fetch)' '\n> \tmark fetch-group-some &&\n> \tupdate_repos &&\n>@@ -107,4 +128,14 @@ test_expect_success 'updating group in parallel with a\n>duplicate remote does not\n> \trepo_fetched one\n> '\n>\n>+test_expect_success 'groups are printed in order of configuration (remote group)' '\n>+\tcat >expect <<-EOF &&\n>+\tall\n>+\tsome\n>+\tduplicate\n>+\tEOF\n>+\ttest_expect_code 0 git remote group 1>actual &&\n>+\ttest_cmp expect actual\n>+'\n>+\n> test_done\n>--\n>2.49.0.460.g0390bdefd0.dirty\n\n"},{"id":"517267","messageId":"xmqqecx3ow6u.fsf@gitster.g","threadId":"63389","inReplyTo":"20250503160953.196329-1-bugzilla@lazar.co.nz","subject":"Re: [PATCH 0/1] New remote groups subcommand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2025-05-05T16:32:09Z","receivedAt":"2025-05-05T16:32:22Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Lazar Sumar <sumar@lazar.co.nz> writes:\n\n> Lastly, I wanted to at least add a test for the expected behavior of\n> remote grups when a remote is renamed but found the current behavior\n> surprising, i.e.\n>\n>     $ git config --get-regexp 'remotes\\.'\n>     file:.git/config        remotes.group1 upstream origin\n>     $ git remote rename origin fork\n>     Renaming remote references: 100% (8/8), done.\n>     $ git config --get-regexp 'remotes\\.'\n>     file:.git/config        remotes.group1 upstream origin\n>\n> The remote group is defined in the local config file and I would expect\n> the rename to rename the group member here.\n\nEven for a single same person, depending on the reason why the\nrenaming of the underlying individual remote nickname is done, I\nthink the expectation is different.  Perhaps they have a set of\nremotes that they use for CI use (i.e., they push there to trigger\nmultiple CI platforms), that are named ci-alfa ci-beta etc. to make\nit easier for them to identify these remotes, and grouped under \"ci\"\ngroup, and they have another group they use for publishing (i.e.,\nthey push there and the latest history becomes available to their\ndevelopers), as \"publish\" group.  Suppose they decide to retire the\nCI infrastructure from the ci-alfa remote and use the repository\nonly for publishing.  Then the config setting that may have looked\nlike this\n\n\t[remotes]\n\t\tci = ci-alfa ci-beta ...\n\t\tpublish = north-america europe ...\n\nwould want to become\n\n\t[remotes]\n\t\tci = ci-beta ...\n\t\tpublish = asia north-america europe ...\n\nwhen they rename \"ci-alfa\" to \"asia\" because they no longer have\nCI infrastructure attached to the repository to trigger, and instead\nthey want to use the repository to serve asian customers.\n\nIf \"git remote rename ci-alfa asia\" automatically rewrote the first\none to\n\n\t[remotes]\n\t\tci = asia ci-beta ...\n\t\tpublish = north-america europe ...\n\nit would not help anybody.\n\nOf course, if the renaming is done to fix typo in the name of a\nremote, e.g., \"git remote rename ci-alfa ci-alpha\", it would be\nuseful if the rename also rewrote the config into\n\n\t[remotes]\n\t\tci = ci-alpha ci-beta ...\n\t\tpublish = north-america europe ...\n\nbut we cannot guess the intentions.  So I am not sure if always\nautomatically rewriting is a good idea.\n\nBefore thinking about \"rename\" doing random things that the user may\nor may not want to see perform automatically, I think it is better\nto give users a way to exactly do what they want first.  Perhaps a\nsession with those tools would look like this?\n\n    $ git remote group --list\n    ci\n    publish\n    $ git remote group --list --verbose\n    ci\t\tci-alfa ci-beta\n    publish\tnorth-america europe\n    $ git remote group --get ci\n    ci-alfa\n    ci-beta\n    $ git remote group --set ci ci-alfa ci-beta\n    $ git remote group --get ci\n    ci-alpha\n    ci-beta\n    $ git remote group --list\n    ci\n    publish\n    $ git remote group --rename publish pub\n    $ git remote group --list\n    ci\n    pub\n\n"}]}