{"thread":{"id":"50412","subject":"[PATCH 0/3] Teach submodule set-branch subcommand","startedAt":"2019-02-06T10:59:54Z","lastAt":"2019-02-08T23:52:21Z","messageCount":25,"participants":["Denton Liu","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"368576","messageId":"cover.1549450636.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":null,"subject":"[PATCH 0/3] Teach submodule set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-06T10:59:48Z","receivedAt":"2019-02-06T10:59:54Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there is no way to set the branch of a submodule without\nmanually manipulating the .gitmodules file. This patchset introduces a\nporcelain command that enables this.\n\n\nDenton Liu (3):\n  git-submodule.txt: document default behavior without --branch\n  submodule--helper: teach config subcommand --unset\n  submodule: teach set-branch subcommand\n\n Documentation/git-submodule.txt        | 10 ++-\n builtin/submodule--helper.c            | 15 +++--\n contrib/completion/git-completion.bash |  5 +-\n git-submodule.sh                       | 75 +++++++++++++++++++--\n t/t7411-submodule-config.sh            |  9 +++\n t/t7419-submodule-set-branch.sh        | 93 ++++++++++++++++++++++++++\n 6 files changed, 197 insertions(+), 10 deletions(-)\n create mode 100755 t/t7419-submodule-set-branch.sh\n\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368577","messageId":"cf6e0d16ac0c0d521da98f5d9a53532b923a621c.1549450636.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549450636.git.liu.denton@gmail.com","subject":"[PATCH 1/3] git-submodule.txt: document default behavior without --branch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-06T10:59:52Z","receivedAt":"2019-02-06T10:59:56Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This behavior is mentioned in gitmodules.txt but not in\ngit-submodule.txt so we copy the information over so that it is not\nmissed.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-submodule.txt | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex ba3c4df550..9951c68744 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -261,7 +261,8 @@ OPTIONS\n \tThe name of the branch is recorded as `submodule.<name>.branch` in\n \t`.gitmodules` for `update --remote`.  A special value of `.` is used to\n \tindicate that the name of the branch in the submodule should be the\n-\tsame name as the current branch in the current repository.\n+\tsame name as the current branch in the current repository.  If the\n+\toption is not specified, it defaults to 'master'.\n \n -f::\n --force::\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368578","messageId":"f24f20b024f4d41f106ed014a31508fab4fa5eb2.1549450636.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549450636.git.liu.denton@gmail.com","subject":"[PATCH 2/3] submodule--helper: teach config subcommand --unset","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-06T10:59:54Z","receivedAt":"2019-02-06T10:59:59Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This teaches submodule--helper config the --unset option, which removes\nthe specified configuration key from the .gitmodule file.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n builtin/submodule--helper.c | 15 +++++++++++----\n t/t7411-submodule-config.sh |  9 +++++++++\n 2 files changed, 20 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 0e140f176c..336e4429e6 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2149,15 +2149,21 @@ static int module_config(int argc, const char **argv, const char *prefix)\n \tenum {\n \t\tCHECK_WRITEABLE = 1\n \t} command = 0;\n+\tenum {\n+\t\tDO_UNSET = 1\n+\t} unset = 0;\n \n \tstruct option module_config_options[] = {\n \t\tOPT_CMDMODE(0, \"check-writeable\", &command,\n \t\t\t    N_(\"check if it is safe to write to the .gitmodules file\"),\n \t\t\t    CHECK_WRITEABLE),\n+\t\tOPT_CMDMODE(0, \"unset\", &unset,\n+\t\t\t    N_(\"unset the config in the .gitmodules file\"),\n+\t\t\t    DO_UNSET),\n \t\tOPT_END()\n \t};\n \tconst char *const git_submodule_helper_usage[] = {\n-\t\tN_(\"git submodule--helper config name [value]\"),\n+\t\tN_(\"git submodule--helper config name [--unset] [value]\"),\n \t\tN_(\"git submodule--helper config --check-writeable\"),\n \t\tNULL\n \t};\n@@ -2169,15 +2175,16 @@ static int module_config(int argc, const char **argv, const char *prefix)\n \t\treturn is_writing_gitmodules_ok() ? 0 : -1;\n \n \t/* Equivalent to ACTION_GET in builtin/config.c */\n-\tif (argc == 2)\n+\tif (argc == 2 && unset != DO_UNSET)\n \t\treturn print_config_from_gitmodules(the_repository, argv[1]);\n \n \t/* Equivalent to ACTION_SET in builtin/config.c */\n-\tif (argc == 3) {\n+\tif (argc == 3 || (argc == 2 && unset == DO_UNSET)) {\n \t\tif (!is_writing_gitmodules_ok())\n \t\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n \n-\t\treturn config_set_in_gitmodules_file_gently(argv[1], argv[2]);\n+\t\tconst char *value = (argc == 3) ? argv[2] : NULL;\n+\t\treturn config_set_in_gitmodules_file_gently(argv[1], value);\n \t}\n \n \tusage_with_options(git_submodule_helper_usage, module_config_options);\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex 89690b7adb..fcc0fb82d8 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -142,6 +142,15 @@ test_expect_success 'reading submodules config from the working tree with \"submo\n \t)\n '\n \n+test_expect_success 'unsetting submodules config from the working tree with \"submodule--helper config --unset\"' '\n+\t(cd super &&\n+\t\tgit submodule--helper config --unset submodule.submodule.url &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_must_be_empty actual\n+\t)\n+'\n+\n+\n test_expect_success 'writing submodules config with \"submodule--helper config\"' '\n \t(cd super &&\n \t\techo \"new_url\" >expect &&\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368579","messageId":"b0a314725c0943f60e381f2cd6054769288a269b.1549450636.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549450636.git.liu.denton@gmail.com","subject":"[PATCH 3/3] submodule: teach set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-06T10:59:57Z","receivedAt":"2019-02-06T11:00:02Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This teaches git-submodule the set-branch subcommand which allows the\nbranch of a submodule to be set through a porcelain command without\nhaving to manually manipulate the .gitmodules file.\n---\n Documentation/git-submodule.txt        |  7 ++\n contrib/completion/git-completion.bash |  5 +-\n git-submodule.sh                       | 75 +++++++++++++++++++--\n t/t7419-submodule-set-branch.sh        | 93 ++++++++++++++++++++++++++\n 4 files changed, 175 insertions(+), 5 deletions(-)\n create mode 100755 t/t7419-submodule-set-branch.sh\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 9951c68744..cb838ee556 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -14,6 +14,7 @@ SYNOPSIS\n 'git submodule' [--quiet] init [--] [<path>...]\n 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)\n 'git submodule' [--quiet] update [<options>] [--] [<path>...]\n+'git submodule' [--quiet] set-branch [<options>] [--] <path>\n 'git submodule' [--quiet] summary [<options>] [--] [<path>...]\n 'git submodule' [--quiet] foreach [--recursive] <command>\n 'git submodule' [--quiet] sync [--recursive] [--] [<path>...]\n@@ -168,6 +169,12 @@ submodule with the `--init` option.\n If `--recursive` is specified, this command will recurse into the\n registered submodules, and update any nested submodules within.\n --\n+set-branch ((-d|--default)|(-b|--branch <branch>)) [--] <path>::\n+\tSets the default remote tracking branch for the submodule. The\n+\t`--branch` option allows the remote branch to be specified. The\n+\t`--default` option removes the submodule.<name>.branch configuration\n+\tkey, which causes the tracking branch to default to 'master'.\n+--\n summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]::\n \tShow commit summary between the given commit (defaults to HEAD) and\n \tworking tree/index. For a submodule in question, a series of commits\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 499e56f83d..8b3b5a9d34 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -2573,7 +2573,7 @@ _git_submodule ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal subcommands=\"add status init deinit update summary foreach sync\"\n+\tlocal subcommands=\"add status init deinit update set-branch summary foreach sync\"\n \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n \tif [ -z \"$subcommand\" ]; then\n \t\tcase \"$cur\" in\n@@ -2604,6 +2604,9 @@ _git_submodule ()\n \t\t\t--force --rebase --merge --reference --depth --recursive --jobs\n \t\t\"\n \t\t;;\n+\tset-branch,--*)\n+\t\t__gitcomp \"--default --branch\"\n+\t\t;;\n \tsummary,--*)\n \t\t__gitcomp \"--cached --files --summary-limit\"\n \t\t;;\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 5e608f8bad..43ec756602 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -10,6 +10,7 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)\n    or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path>\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\n@@ -684,6 +685,72 @@ cmd_update()\n \t}\n }\n \n+#\n+# Configures a submodule's default branch\n+#\n+# $@ = requested path\n+#\n+cmd_set_branch() {\n+\tunset_branch=false\n+\tbranch=\n+\n+\twhile test $# -ne 0\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-q|--quiet)\n+\t\t\t# we don't do anything with this but we need to accept it\n+\t\t\t;;\n+\t\t-d|--default)\n+\t\t\tunset_branch=true\n+\t\t\t;;\n+\t\t-b|--branch)\n+\t\t\tcase \"$2\" in '') usage ;; esac\n+\t\t\tbranch=$2\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tusage\n+\t\t\t;;\n+\t\t*)\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\tdone\n+\n+\tif test $# -ne 1\n+\tthen\n+\t\tusage\n+\tfi\n+\n+\t# we can't use `git submodule--helper name` here because internally, it\n+\t# hashes the path so a trailing slash could lead to an unintentional no match\n+\tname=\"$(git submodule--helper list \"$1\" | cut -f2)\"\n+\tif test -z \"$name\"\n+\tthen\n+\t\texit 1\n+\tfi\n+\n+\ttest -n \"$branch\"; has_branch=$?\n+\ttest \"$unset_branch\" = true; has_unset_branch=$?\n+\n+\tif test $((!$has_branch != !$has_unset_branch)) -eq 0\n+\tthen\n+\t\tusage\n+\tfi\n+\n+\tif test $has_branch -eq 0\n+\tthen\n+\t\tgit submodule--helper config submodule.\"$name\".branch \"$branch\"\n+\telse\n+\t\tgit submodule--helper config --unset submodule.\"$name\".branch\n+\tfi\n+}\n+\n #\n # Show commit summary for submodules in index or working tree\n #\n@@ -980,7 +1047,7 @@ cmd_absorbgitdirs()\n while test $# != 0 && test -z \"$command\"\n do\n \tcase \"$1\" in\n-\tadd | foreach | init | deinit | update | status | summary | sync | absorbgitdirs)\n+\tadd | foreach | init | deinit | update | set-branch | status | summary | sync | absorbgitdirs)\n \t\tcommand=$1\n \t\t;;\n \t-q|--quiet)\n@@ -1021,8 +1088,8 @@ then\n     fi\n fi\n \n-# \"-b branch\" is accepted only by \"add\"\n-if test -n \"$branch\" && test \"$command\" != add\n+# \"-b branch\" is accepted only by \"add\" and \"set-branch\"\n+if test -n \"$branch\" && (test \"$command\" != add || test \"$command\" != set-branch)\n then\n \tusage\n fi\n@@ -1033,4 +1100,4 @@ then\n \tusage\n fi\n \n-\"cmd_$command\" \"$@\"\n+\"cmd_$(echo $command | sed -e s/-/_/g)\" \"$@\"\ndiff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh\nnew file mode 100755\nindex 0000000000..c4b370ea85\n--- /dev/null\n+++ b/t/t7419-submodule-set-branch.sh\n@@ -0,0 +1,93 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Denton Liu\n+#\n+\n+test_description='Test submodules set-branch subcommand\n+\n+This test verifies that the set-branch subcommand of git-submodule is working\n+as expected.\n+'\n+\n+TEST_NO_CREATE_REPO=1\n+. ./test-lib.sh\n+\n+test_expect_success 'submodule config cache setup' '\n+\tmkdir submodule &&\n+\t(cd submodule &&\n+\t\tgit init &&\n+\t\techo a >a &&\n+\t\tgit add . &&\n+\t\tgit commit -ma &&\n+\t\tgit checkout -b topic &&\n+\t\techo b >a &&\n+\t\tgit add . &&\n+\t\tgit commit -mb\n+\t) &&\n+\tmkdir super &&\n+\t(cd super &&\n+\t\tgit init &&\n+\t\tgit submodule add ../submodule &&\n+\t\tgit commit -m \"add submodule\"\n+\t)\n+'\n+\n+test_expect_success 'ensure submodule branch is unset' '\n+\t(cd super &&\n+\t\ttest_must_fail grep branch .gitmodules\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch --branch' '\n+\t(cd super &&\n+\t\tgit submodule set-branch --branch topic submodule &&\n+\t\tgrep \"branch = topic\" .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\tb\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch --default' '\n+\t(cd super &&\n+\t\tgit submodule set-branch --default submodule &&\n+\t\ttest_must_fail grep branch .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\ta\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch -b' '\n+\t(cd super &&\n+\t\tgit submodule set-branch -b topic submodule &&\n+\t\tgrep \"branch = topic\" .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\tb\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch -d' '\n+\t(cd super &&\n+\t\tgit submodule set-branch -d submodule &&\n+\t\ttest_must_fail grep branch .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\ta\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_done\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368626","messageId":"xmqqftt0rc0g.fsf@gitster-ct.c.googlers.com","threadId":"50412","inReplyTo":"cf6e0d16ac0c0d521da98f5d9a53532b923a621c.1549450636.git.liu.denton@gmail.com","subject":"Re: [PATCH 1/3] git-submodule.txt: document default behavior without --branch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-06T18:46:07Z","receivedAt":"2019-02-06T18:46:12Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> This behavior is mentioned in gitmodules.txt but not in\n> git-submodule.txt so we copy the information over so that it is not\n> missed.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n>  Documentation/git-submodule.txt | 3 ++-\n>  1 file changed, 2 insertions(+), 1 deletion(-)\n>\n> diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\n> index ba3c4df550..9951c68744 100644\n> --- a/Documentation/git-submodule.txt\n> +++ b/Documentation/git-submodule.txt\n> @@ -261,7 +261,8 @@ OPTIONS\n>  \tThe name of the branch is recorded as `submodule.<name>.branch` in\n>  \t`.gitmodules` for `update --remote`.  A special value of `.` is used to\n>  \tindicate that the name of the branch in the submodule should be the\n> -\tsame name as the current branch in the current repository.\n> +\tsame name as the current branch in the current repository.  If the\n> +\toption is not specified, it defaults to 'master'.\n\nOK.  Thanks.\n\nI read the whole page and there are a few other things I noticed,\nwhich I'll write down here so that somebody else can think about\nthem (and that somebody else does not have to be you) as a tangent.\n\n1. The description of \"--branch <branch>\" option here is missing the\n   \"<branch>\", a mandatory argument to the option.  Options in the\n   OPTIONS list like \"--jobs <n>\", \"--repository <repo>\" do show the\n   argument, and the description for this option should be updated\n   to match.\n\n2. Some options are mentioned in the description of each subcommand\n   it can appear (e.g. \"sync --recursive\"), while many others are\n   not and shown only in the OPTIONS section (e.g. \"--remote\" which\n   can be used only with \"update\" subcommand).\n\nThese may want to be cleaned up.  Actually it may not be a bad idea\nto do #1 as part of this change (i.e. retitle it to \"git-submodule:\n\"--branch <branch>\" option defaults to 'master'\" or something).\n\n"},{"id":"368629","messageId":"xmqqbm3orb1n.fsf@gitster-ct.c.googlers.com","threadId":"50412","inReplyTo":"f24f20b024f4d41f106ed014a31508fab4fa5eb2.1549450636.git.liu.denton@gmail.com","subject":"Re: [PATCH 2/3] submodule--helper: teach config subcommand --unset","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-06T19:07:00Z","receivedAt":"2019-02-06T19:07:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> This teaches submodule--helper config the --unset option, which removes\n> the specified configuration key from the .gitmodule file.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n>  builtin/submodule--helper.c | 15 +++++++++++----\n>  t/t7411-submodule-config.sh |  9 +++++++++\n>  2 files changed, 20 insertions(+), 4 deletions(-)\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index 0e140f176c..336e4429e6 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -2149,15 +2149,21 @@ static int module_config(int argc, const char **argv, const char *prefix)\n>  \tenum {\n>  \t\tCHECK_WRITEABLE = 1\n>  \t} command = 0;\n> +\tenum {\n> +\t\tDO_UNSET = 1\n> +\t} unset = 0;\n>  \n>  \tstruct option module_config_options[] = {\n>  \t\tOPT_CMDMODE(0, \"check-writeable\", &command,\n>  \t\t\t    N_(\"check if it is safe to write to the .gitmodules file\"),\n>  \t\t\t    CHECK_WRITEABLE),\n> +\t\tOPT_CMDMODE(0, \"unset\", &unset,\n> +\t\t\t    N_(\"unset the config in the .gitmodules file\"),\n> +\t\t\t    DO_UNSET),\n>  \t\tOPT_END()\n>  \t};\n\nThe way this patch uses OPT_CMDMODE() is wrong.\n\nThe situation in which CMDMODE is meant to be used is that there are\nmultiple (that's two or more) choices the end user can make, and the\nend user can choose only one of them at a time, iow, giving more\nthan one is an error.  \n\nIn such a case, the programmer would\n\n - prepare a single variable to store the single choice the end user\n   makes the choice in and initialize it to zero.\n\n - have one OPT_CMDMODE() element for each valid choice, all\n   pointing at the same variable, but with different value that is\n   not zero.\n\nThe parse_options() call would then make sure that the variable is\nset to non-zero value only once, to detect conflicting command modes\ngiven from the command line.  The program then can read from the\nsingle variable to see if the end user made any choice (or left it\n0).\n\nAn example of typical and good use of OPT_CMDMODE() mechanism can be\nseen in builtin/tag.c; the 'l(ist)', 'd(elete)' and 'v(erify)' are\nthe distinct operating modes of the \"git tag\" command (i.e. you do\nnot delete a tag while listing them), so the &cmdmode variable is\nused to ensure only one of them (or none of them) is given.\n\nThe existing use of OPT_CMDMODE we see in this function anticipates\nthat there would be new operating modes added other than the\ncheck-writable mode, so if you are making a new command mode that\ncannot be used with the existing check-writable, then the right way\nto use the OPT_CMDMODE() is to add to the command enum a new\nnon-zero value distinct from CHECK_WRITABLE, without introducing a\nnew \"unset\" variable.\n\nIf this --unset thing is truly independent from --check-writable,\ni.e. if all four possible combinations of having and not having\nthese two options are valid, then you would not want to muck with\nthe &command variable, but in that case, wouldn't it make more sense\nfor the new --unset thing to simply be using OPT_BOOL()?  After all,\nit is not like you are planning to add new oprating modes in the\n\"unset\" family that is not \"--unset\" in the future, no?\n"},{"id":"368663","messageId":"cf6e0d16ac0c0d521da98f5d9a53532b923a621c.1549521103.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549521103.git.liu.denton@gmail.com","subject":"[PATCH v2 1/3] git-submodule.txt: document default behavior without --branch","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-07T06:32:56Z","receivedAt":"2019-02-07T06:33:02Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This behavior is mentioned in gitmodules.txt but not in\ngit-submodule.txt so we copy the information over so that it is not\nmissed.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-submodule.txt | 3 ++-\n 1 file changed, 2 insertions(+), 1 deletion(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex ba3c4df550..9951c68744 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -261,7 +261,8 @@ OPTIONS\n \tThe name of the branch is recorded as `submodule.<name>.branch` in\n \t`.gitmodules` for `update --remote`.  A special value of `.` is used to\n \tindicate that the name of the branch in the submodule should be the\n-\tsame name as the current branch in the current repository.\n+\tsame name as the current branch in the current repository.  If the\n+\toption is not specified, it defaults to 'master'.\n \n -f::\n --force::\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368664","messageId":"cover.1549521103.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549450636.git.liu.denton@gmail.com","subject":"[PATCH v2 0/3] Teach submodule set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-07T06:32:53Z","receivedAt":"2019-02-07T06:33:03Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Currently, there is no way to set the branch of a submodule without\nmanually manipulating the .gitmodules file. This patchset introduces a\nporcelain command that enables this.\n\nChanges since v1:\n\t* Fixed incorrect usage of OPT_CMDMODE\n\n\nDenton Liu (3):\n  git-submodule.txt: document default behavior without --branch\n  submodule--helper: teach config subcommand --unset\n  submodule: teach set-branch subcommand\n\n Documentation/git-submodule.txt        | 10 ++-\n builtin/submodule--helper.c            | 18 +++--\n contrib/completion/git-completion.bash |  5 +-\n git-submodule.sh                       | 75 +++++++++++++++++++--\n t/t7411-submodule-config.sh            |  9 +++\n t/t7419-submodule-set-branch.sh        | 93 ++++++++++++++++++++++++++\n 6 files changed, 198 insertions(+), 12 deletions(-)\n create mode 100755 t/t7419-submodule-set-branch.sh\n\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368665","messageId":"c562ca0c252da88cba8806e20e0803068616e80c.1549521103.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549521103.git.liu.denton@gmail.com","subject":"[PATCH v2 2/3] submodule--helper: teach config subcommand --unset","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-07T06:32:59Z","receivedAt":"2019-02-07T06:33:07Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This teaches submodule--helper config the --unset option, which removes\nthe specified configuration key from the .gitmodule file.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n builtin/submodule--helper.c | 18 ++++++++++++------\n t/t7411-submodule-config.sh |  9 +++++++++\n 2 files changed, 21 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 0e140f176c..5a4a7b1993 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2147,17 +2147,22 @@ static int check_name(int argc, const char **argv, const char *prefix)\n static int module_config(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n-\t\tCHECK_WRITEABLE = 1\n-\t} command = 0;\n+\t\tNONE,\n+\t\tCHECK_WRITEABLE,\n+\t\tDO_UNSET\n+\t} command = NONE;\n \n \tstruct option module_config_options[] = {\n \t\tOPT_CMDMODE(0, \"check-writeable\", &command,\n \t\t\t    N_(\"check if it is safe to write to the .gitmodules file\"),\n \t\t\t    CHECK_WRITEABLE),\n+\t\tOPT_CMDMODE(0, \"unset\", &command,\n+\t\t\t    N_(\"unset the config in the .gitmodules file\"),\n+\t\t\t    DO_UNSET),\n \t\tOPT_END()\n \t};\n \tconst char *const git_submodule_helper_usage[] = {\n-\t\tN_(\"git submodule--helper config name [value]\"),\n+\t\tN_(\"git submodule--helper config name [--unset] [value]\"),\n \t\tN_(\"git submodule--helper config --check-writeable\"),\n \t\tNULL\n \t};\n@@ -2169,15 +2174,16 @@ static int module_config(int argc, const char **argv, const char *prefix)\n \t\treturn is_writing_gitmodules_ok() ? 0 : -1;\n \n \t/* Equivalent to ACTION_GET in builtin/config.c */\n-\tif (argc == 2)\n+\tif (argc == 2 && command != DO_UNSET)\n \t\treturn print_config_from_gitmodules(the_repository, argv[1]);\n \n \t/* Equivalent to ACTION_SET in builtin/config.c */\n-\tif (argc == 3) {\n+\tif (argc == 3 || (argc == 2 && command == DO_UNSET)) {\n \t\tif (!is_writing_gitmodules_ok())\n \t\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n \n-\t\treturn config_set_in_gitmodules_file_gently(argv[1], argv[2]);\n+\t\tconst char *value = (argc == 3) ? argv[2] : NULL;\n+\t\treturn config_set_in_gitmodules_file_gently(argv[1], value);\n \t}\n \n \tusage_with_options(git_submodule_helper_usage, module_config_options);\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex 89690b7adb..fcc0fb82d8 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -142,6 +142,15 @@ test_expect_success 'reading submodules config from the working tree with \"submo\n \t)\n '\n \n+test_expect_success 'unsetting submodules config from the working tree with \"submodule--helper config --unset\"' '\n+\t(cd super &&\n+\t\tgit submodule--helper config --unset submodule.submodule.url &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_must_be_empty actual\n+\t)\n+'\n+\n+\n test_expect_success 'writing submodules config with \"submodule--helper config\"' '\n \t(cd super &&\n \t\techo \"new_url\" >expect &&\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368666","messageId":"a4ad6ca21f89967d77f7c22a275e6f0af61227cb.1549521103.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549521103.git.liu.denton@gmail.com","subject":"[PATCH v2 3/3] submodule: teach set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-07T06:33:02Z","receivedAt":"2019-02-07T06:33:08Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This teaches git-submodule the set-branch subcommand which allows the\nbranch of a submodule to be set through a porcelain command without\nhaving to manually manipulate the .gitmodules file.\n---\n Documentation/git-submodule.txt        |  7 ++\n contrib/completion/git-completion.bash |  5 +-\n git-submodule.sh                       | 75 +++++++++++++++++++--\n t/t7419-submodule-set-branch.sh        | 93 ++++++++++++++++++++++++++\n 4 files changed, 175 insertions(+), 5 deletions(-)\n create mode 100755 t/t7419-submodule-set-branch.sh\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 9951c68744..cb838ee556 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -14,6 +14,7 @@ SYNOPSIS\n 'git submodule' [--quiet] init [--] [<path>...]\n 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)\n 'git submodule' [--quiet] update [<options>] [--] [<path>...]\n+'git submodule' [--quiet] set-branch [<options>] [--] <path>\n 'git submodule' [--quiet] summary [<options>] [--] [<path>...]\n 'git submodule' [--quiet] foreach [--recursive] <command>\n 'git submodule' [--quiet] sync [--recursive] [--] [<path>...]\n@@ -168,6 +169,12 @@ submodule with the `--init` option.\n If `--recursive` is specified, this command will recurse into the\n registered submodules, and update any nested submodules within.\n --\n+set-branch ((-d|--default)|(-b|--branch <branch>)) [--] <path>::\n+\tSets the default remote tracking branch for the submodule. The\n+\t`--branch` option allows the remote branch to be specified. The\n+\t`--default` option removes the submodule.<name>.branch configuration\n+\tkey, which causes the tracking branch to default to 'master'.\n+--\n summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]::\n \tShow commit summary between the given commit (defaults to HEAD) and\n \tworking tree/index. For a submodule in question, a series of commits\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 499e56f83d..8b3b5a9d34 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -2573,7 +2573,7 @@ _git_submodule ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal subcommands=\"add status init deinit update summary foreach sync\"\n+\tlocal subcommands=\"add status init deinit update set-branch summary foreach sync\"\n \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n \tif [ -z \"$subcommand\" ]; then\n \t\tcase \"$cur\" in\n@@ -2604,6 +2604,9 @@ _git_submodule ()\n \t\t\t--force --rebase --merge --reference --depth --recursive --jobs\n \t\t\"\n \t\t;;\n+\tset-branch,--*)\n+\t\t__gitcomp \"--default --branch\"\n+\t\t;;\n \tsummary,--*)\n \t\t__gitcomp \"--cached --files --summary-limit\"\n \t\t;;\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 5e608f8bad..43ec756602 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -10,6 +10,7 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)\n    or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path>\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\n@@ -684,6 +685,72 @@ cmd_update()\n \t}\n }\n \n+#\n+# Configures a submodule's default branch\n+#\n+# $@ = requested path\n+#\n+cmd_set_branch() {\n+\tunset_branch=false\n+\tbranch=\n+\n+\twhile test $# -ne 0\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-q|--quiet)\n+\t\t\t# we don't do anything with this but we need to accept it\n+\t\t\t;;\n+\t\t-d|--default)\n+\t\t\tunset_branch=true\n+\t\t\t;;\n+\t\t-b|--branch)\n+\t\t\tcase \"$2\" in '') usage ;; esac\n+\t\t\tbranch=$2\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tusage\n+\t\t\t;;\n+\t\t*)\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\tdone\n+\n+\tif test $# -ne 1\n+\tthen\n+\t\tusage\n+\tfi\n+\n+\t# we can't use `git submodule--helper name` here because internally, it\n+\t# hashes the path so a trailing slash could lead to an unintentional no match\n+\tname=\"$(git submodule--helper list \"$1\" | cut -f2)\"\n+\tif test -z \"$name\"\n+\tthen\n+\t\texit 1\n+\tfi\n+\n+\ttest -n \"$branch\"; has_branch=$?\n+\ttest \"$unset_branch\" = true; has_unset_branch=$?\n+\n+\tif test $((!$has_branch != !$has_unset_branch)) -eq 0\n+\tthen\n+\t\tusage\n+\tfi\n+\n+\tif test $has_branch -eq 0\n+\tthen\n+\t\tgit submodule--helper config submodule.\"$name\".branch \"$branch\"\n+\telse\n+\t\tgit submodule--helper config --unset submodule.\"$name\".branch\n+\tfi\n+}\n+\n #\n # Show commit summary for submodules in index or working tree\n #\n@@ -980,7 +1047,7 @@ cmd_absorbgitdirs()\n while test $# != 0 && test -z \"$command\"\n do\n \tcase \"$1\" in\n-\tadd | foreach | init | deinit | update | status | summary | sync | absorbgitdirs)\n+\tadd | foreach | init | deinit | update | set-branch | status | summary | sync | absorbgitdirs)\n \t\tcommand=$1\n \t\t;;\n \t-q|--quiet)\n@@ -1021,8 +1088,8 @@ then\n     fi\n fi\n \n-# \"-b branch\" is accepted only by \"add\"\n-if test -n \"$branch\" && test \"$command\" != add\n+# \"-b branch\" is accepted only by \"add\" and \"set-branch\"\n+if test -n \"$branch\" && (test \"$command\" != add || test \"$command\" != set-branch)\n then\n \tusage\n fi\n@@ -1033,4 +1100,4 @@ then\n \tusage\n fi\n \n-\"cmd_$command\" \"$@\"\n+\"cmd_$(echo $command | sed -e s/-/_/g)\" \"$@\"\ndiff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh\nnew file mode 100755\nindex 0000000000..c4b370ea85\n--- /dev/null\n+++ b/t/t7419-submodule-set-branch.sh\n@@ -0,0 +1,93 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Denton Liu\n+#\n+\n+test_description='Test submodules set-branch subcommand\n+\n+This test verifies that the set-branch subcommand of git-submodule is working\n+as expected.\n+'\n+\n+TEST_NO_CREATE_REPO=1\n+. ./test-lib.sh\n+\n+test_expect_success 'submodule config cache setup' '\n+\tmkdir submodule &&\n+\t(cd submodule &&\n+\t\tgit init &&\n+\t\techo a >a &&\n+\t\tgit add . &&\n+\t\tgit commit -ma &&\n+\t\tgit checkout -b topic &&\n+\t\techo b >a &&\n+\t\tgit add . &&\n+\t\tgit commit -mb\n+\t) &&\n+\tmkdir super &&\n+\t(cd super &&\n+\t\tgit init &&\n+\t\tgit submodule add ../submodule &&\n+\t\tgit commit -m \"add submodule\"\n+\t)\n+'\n+\n+test_expect_success 'ensure submodule branch is unset' '\n+\t(cd super &&\n+\t\ttest_must_fail grep branch .gitmodules\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch --branch' '\n+\t(cd super &&\n+\t\tgit submodule set-branch --branch topic submodule &&\n+\t\tgrep \"branch = topic\" .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\tb\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch --default' '\n+\t(cd super &&\n+\t\tgit submodule set-branch --default submodule &&\n+\t\ttest_must_fail grep branch .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\ta\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch -b' '\n+\t(cd super &&\n+\t\tgit submodule set-branch -b topic submodule &&\n+\t\tgrep \"branch = topic\" .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\tb\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch -d' '\n+\t(cd super &&\n+\t\tgit submodule set-branch -d submodule &&\n+\t\ttest_must_fail grep branch .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\ta\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_done\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368673","messageId":"cover.1549534460.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549521103.git.liu.denton@gmail.com","subject":"[PATCH v3 0/3] Teach submodule set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-07T10:18:52Z","receivedAt":"2019-02-07T10:18:57Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"I rebased the changes onto the latest 'next' because if this branch gets\nmerged into 'next', there'll be merge conflicts from\n'dl/complete-submodule-absorbgitdirs'.\n\nCurrently, there is no way to set the branch of a submodule without\nmanually manipulating the .gitmodules file. This patchset introduces a\nporcelain command that enables this.\n\nChanges since v1:\n\t* Fixed incorrect usage of OPT_CMDMODE\n\nChanges since v2:\n\t* Corrected missing argument for -b/--branch in git-submodule.txt\n\t* Rebased onto latest next\n\n\nDenton Liu (3):\n  git-submodule.txt: \"--branch <branch>\" option defaults to 'master'\n  submodule--helper: teach config subcommand --unset\n  submodule: teach set-branch subcommand\n\n Documentation/git-submodule.txt        | 14 +++-\n builtin/submodule--helper.c            | 18 +++--\n contrib/completion/git-completion.bash |  5 +-\n git-submodule.sh                       | 75 +++++++++++++++++++--\n t/t7411-submodule-config.sh            |  9 +++\n t/t7419-submodule-set-branch.sh        | 93 ++++++++++++++++++++++++++\n 6 files changed, 200 insertions(+), 14 deletions(-)\n create mode 100755 t/t7419-submodule-set-branch.sh\n\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368674","messageId":"b7c65622eb1dd64a4252e441910809d3c66ed49f.1549534460.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549534460.git.liu.denton@gmail.com","subject":"[PATCH v3 1/3] git-submodule.txt: \"--branch <branch>\" option defaults to 'master'","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-07T10:18:55Z","receivedAt":"2019-02-07T10:19:00Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This behavior is mentioned in gitmodules.txt but not in\ngit-submodule.txt so we copy the information over so that it is not\nmissed.\n\nAlso, add the missed argument to the -b/--branch option.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-submodule.txt | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex ba3c4df550..4150148fa3 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -255,13 +255,14 @@ OPTIONS\n \tThis option is only valid for the deinit command. Unregister all\n \tsubmodules in the working tree.\n \n--b::\n---branch::\n+-b <branch>::\n+--branch <branch>::\n \tBranch of repository to add as submodule.\n \tThe name of the branch is recorded as `submodule.<name>.branch` in\n \t`.gitmodules` for `update --remote`.  A special value of `.` is used to\n \tindicate that the name of the branch in the submodule should be the\n-\tsame name as the current branch in the current repository.\n+\tsame name as the current branch in the current repository.  If the\n+\toption is not specified, it defaults to 'master'.\n \n -f::\n --force::\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368675","messageId":"e90dfe992e96b33f167d08fe51df49ab1d10ef23.1549534460.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549534460.git.liu.denton@gmail.com","subject":"[PATCH v3 2/3] submodule--helper: teach config subcommand --unset","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-07T10:18:57Z","receivedAt":"2019-02-07T10:19:02Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This teaches submodule--helper config the --unset option, which removes\nthe specified configuration key from the .gitmodule file.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n builtin/submodule--helper.c | 18 ++++++++++++------\n t/t7411-submodule-config.sh |  9 +++++++++\n 2 files changed, 21 insertions(+), 6 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex b80fc4ba3d..a86eacf167 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2148,17 +2148,22 @@ static int check_name(int argc, const char **argv, const char *prefix)\n static int module_config(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n-\t\tCHECK_WRITEABLE = 1\n-\t} command = 0;\n+\t\tNONE,\n+\t\tCHECK_WRITEABLE,\n+\t\tDO_UNSET\n+\t} command = NONE;\n \n \tstruct option module_config_options[] = {\n \t\tOPT_CMDMODE(0, \"check-writeable\", &command,\n \t\t\t    N_(\"check if it is safe to write to the .gitmodules file\"),\n \t\t\t    CHECK_WRITEABLE),\n+\t\tOPT_CMDMODE(0, \"unset\", &command,\n+\t\t\t    N_(\"unset the config in the .gitmodules file\"),\n+\t\t\t    DO_UNSET),\n \t\tOPT_END()\n \t};\n \tconst char *const git_submodule_helper_usage[] = {\n-\t\tN_(\"git submodule--helper config name [value]\"),\n+\t\tN_(\"git submodule--helper config name [--unset] [value]\"),\n \t\tN_(\"git submodule--helper config --check-writeable\"),\n \t\tNULL\n \t};\n@@ -2170,15 +2175,16 @@ static int module_config(int argc, const char **argv, const char *prefix)\n \t\treturn is_writing_gitmodules_ok() ? 0 : -1;\n \n \t/* Equivalent to ACTION_GET in builtin/config.c */\n-\tif (argc == 2)\n+\tif (argc == 2 && command != DO_UNSET)\n \t\treturn print_config_from_gitmodules(the_repository, argv[1]);\n \n \t/* Equivalent to ACTION_SET in builtin/config.c */\n-\tif (argc == 3) {\n+\tif (argc == 3 || (argc == 2 && command == DO_UNSET)) {\n \t\tif (!is_writing_gitmodules_ok())\n \t\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n \n-\t\treturn config_set_in_gitmodules_file_gently(argv[1], argv[2]);\n+\t\tconst char *value = (argc == 3) ? argv[2] : NULL;\n+\t\treturn config_set_in_gitmodules_file_gently(argv[1], value);\n \t}\n \n \tusage_with_options(git_submodule_helper_usage, module_config_options);\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex 89690b7adb..fcc0fb82d8 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -142,6 +142,15 @@ test_expect_success 'reading submodules config from the working tree with \"submo\n \t)\n '\n \n+test_expect_success 'unsetting submodules config from the working tree with \"submodule--helper config --unset\"' '\n+\t(cd super &&\n+\t\tgit submodule--helper config --unset submodule.submodule.url &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_must_be_empty actual\n+\t)\n+'\n+\n+\n test_expect_success 'writing submodules config with \"submodule--helper config\"' '\n \t(cd super &&\n \t\techo \"new_url\" >expect &&\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368676","messageId":"91bb634dfad7f6a17bbed9eaf27f668326fca54e.1549534460.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549534460.git.liu.denton@gmail.com","subject":"[PATCH v3 3/3] submodule: teach set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-07T10:19:00Z","receivedAt":"2019-02-07T10:19:05Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This teaches git-submodule the set-branch subcommand which allows the\nbranch of a submodule to be set through a porcelain command without\nhaving to manually manipulate the .gitmodules file.\n---\n Documentation/git-submodule.txt        |  7 ++\n contrib/completion/git-completion.bash |  5 +-\n git-submodule.sh                       | 75 +++++++++++++++++++--\n t/t7419-submodule-set-branch.sh        | 93 ++++++++++++++++++++++++++\n 4 files changed, 175 insertions(+), 5 deletions(-)\n create mode 100755 t/t7419-submodule-set-branch.sh\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 4150148fa3..6c608b3b8c 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -14,6 +14,7 @@ SYNOPSIS\n 'git submodule' [--quiet] init [--] [<path>...]\n 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)\n 'git submodule' [--quiet] update [<options>] [--] [<path>...]\n+'git submodule' [--quiet] set-branch [<options>] [--] <path>\n 'git submodule' [--quiet] summary [<options>] [--] [<path>...]\n 'git submodule' [--quiet] foreach [--recursive] <command>\n 'git submodule' [--quiet] sync [--recursive] [--] [<path>...]\n@@ -168,6 +169,12 @@ submodule with the `--init` option.\n If `--recursive` is specified, this command will recurse into the\n registered submodules, and update any nested submodules within.\n --\n+set-branch ((-d|--default)|(-b|--branch <branch>)) [--] <path>::\n+\tSets the default remote tracking branch for the submodule. The\n+\t`--branch` option allows the remote branch to be specified. The\n+\t`--default` option removes the submodule.<name>.branch configuration\n+\tkey, which causes the tracking branch to default to 'master'.\n+--\n summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]::\n \tShow commit summary between the given commit (defaults to HEAD) and\n \tworking tree/index. For a submodule in question, a series of commits\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex de56879960..0fccadfc97 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -2573,7 +2573,7 @@ _git_submodule ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal subcommands=\"add status init deinit update summary foreach sync absorbgitdirs\"\n+\tlocal subcommands=\"add status init deinit update set-branch summary foreach sync absorbgitdirs\"\n \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n \tif [ -z \"$subcommand\" ]; then\n \t\tcase \"$cur\" in\n@@ -2604,6 +2604,9 @@ _git_submodule ()\n \t\t\t--force --rebase --merge --reference --depth --recursive --jobs\n \t\t\"\n \t\t;;\n+\tset-branch,--*)\n+\t\t__gitcomp \"--default --branch\"\n+\t\t;;\n \tsummary,--*)\n \t\t__gitcomp \"--cached --files --summary-limit\"\n \t\t;;\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex b5f2beee60..470f681573 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -10,6 +10,7 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)\n    or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path>\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\n@@ -684,6 +685,72 @@ cmd_update()\n \t}\n }\n \n+#\n+# Configures a submodule's default branch\n+#\n+# $@ = requested path\n+#\n+cmd_set_branch() {\n+\tunset_branch=false\n+\tbranch=\n+\n+\twhile test $# -ne 0\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-q|--quiet)\n+\t\t\t# we don't do anything with this but we need to accept it\n+\t\t\t;;\n+\t\t-d|--default)\n+\t\t\tunset_branch=true\n+\t\t\t;;\n+\t\t-b|--branch)\n+\t\t\tcase \"$2\" in '') usage ;; esac\n+\t\t\tbranch=$2\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tusage\n+\t\t\t;;\n+\t\t*)\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\tdone\n+\n+\tif test $# -ne 1\n+\tthen\n+\t\tusage\n+\tfi\n+\n+\t# we can't use `git submodule--helper name` here because internally, it\n+\t# hashes the path so a trailing slash could lead to an unintentional no match\n+\tname=\"$(git submodule--helper list \"$1\" | cut -f2)\"\n+\tif test -z \"$name\"\n+\tthen\n+\t\texit 1\n+\tfi\n+\n+\ttest -n \"$branch\"; has_branch=$?\n+\ttest \"$unset_branch\" = true; has_unset_branch=$?\n+\n+\tif test $((!$has_branch != !$has_unset_branch)) -eq 0\n+\tthen\n+\t\tusage\n+\tfi\n+\n+\tif test $has_branch -eq 0\n+\tthen\n+\t\tgit submodule--helper config submodule.\"$name\".branch \"$branch\"\n+\telse\n+\t\tgit submodule--helper config --unset submodule.\"$name\".branch\n+\tfi\n+}\n+\n #\n # Show commit summary for submodules in index or working tree\n #\n@@ -983,7 +1050,7 @@ cmd_absorbgitdirs()\n while test $# != 0 && test -z \"$command\"\n do\n \tcase \"$1\" in\n-\tadd | foreach | init | deinit | update | status | summary | sync | absorbgitdirs)\n+\tadd | foreach | init | deinit | update | set-branch | status | summary | sync | absorbgitdirs)\n \t\tcommand=$1\n \t\t;;\n \t-q|--quiet)\n@@ -1024,8 +1091,8 @@ then\n     fi\n fi\n \n-# \"-b branch\" is accepted only by \"add\"\n-if test -n \"$branch\" && test \"$command\" != add\n+# \"-b branch\" is accepted only by \"add\" and \"set-branch\"\n+if test -n \"$branch\" && (test \"$command\" != add || test \"$command\" != set-branch)\n then\n \tusage\n fi\n@@ -1036,4 +1103,4 @@ then\n \tusage\n fi\n \n-\"cmd_$command\" \"$@\"\n+\"cmd_$(echo $command | sed -e s/-/_/g)\" \"$@\"\ndiff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh\nnew file mode 100755\nindex 0000000000..c4b370ea85\n--- /dev/null\n+++ b/t/t7419-submodule-set-branch.sh\n@@ -0,0 +1,93 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Denton Liu\n+#\n+\n+test_description='Test submodules set-branch subcommand\n+\n+This test verifies that the set-branch subcommand of git-submodule is working\n+as expected.\n+'\n+\n+TEST_NO_CREATE_REPO=1\n+. ./test-lib.sh\n+\n+test_expect_success 'submodule config cache setup' '\n+\tmkdir submodule &&\n+\t(cd submodule &&\n+\t\tgit init &&\n+\t\techo a >a &&\n+\t\tgit add . &&\n+\t\tgit commit -ma &&\n+\t\tgit checkout -b topic &&\n+\t\techo b >a &&\n+\t\tgit add . &&\n+\t\tgit commit -mb\n+\t) &&\n+\tmkdir super &&\n+\t(cd super &&\n+\t\tgit init &&\n+\t\tgit submodule add ../submodule &&\n+\t\tgit commit -m \"add submodule\"\n+\t)\n+'\n+\n+test_expect_success 'ensure submodule branch is unset' '\n+\t(cd super &&\n+\t\ttest_must_fail grep branch .gitmodules\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch --branch' '\n+\t(cd super &&\n+\t\tgit submodule set-branch --branch topic submodule &&\n+\t\tgrep \"branch = topic\" .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\tb\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch --default' '\n+\t(cd super &&\n+\t\tgit submodule set-branch --default submodule &&\n+\t\ttest_must_fail grep branch .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\ta\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch -b' '\n+\t(cd super &&\n+\t\tgit submodule set-branch -b topic submodule &&\n+\t\tgrep \"branch = topic\" .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\tb\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch -d' '\n+\t(cd super &&\n+\t\tgit submodule set-branch -d submodule &&\n+\t\ttest_must_fail grep branch .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\ta\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_done\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368714","messageId":"xmqqo97npjej.fsf@gitster-ct.c.googlers.com","threadId":"50412","inReplyTo":"cover.1549534460.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 0/3] Teach submodule set-branch subcommand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-07T18:01:40Z","receivedAt":"2019-02-07T18:01:45Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> I rebased the changes onto the latest 'next' because if this branch gets\n> merged into 'next', there'll be merge conflicts from\n> 'dl/complete-submodule-absorbgitdirs'.\n\nPlease don't do that.\n\nA topic that depends on everything in 'next' cannot graduate to\n'master' until everything that is cooking in 'next' does.\n\nWhen\n\n - the \"conflict\" that would arise is so trivial to resolve,\n\n - there is no semantic crashes between the new topic and existing\n    ones, and\n\n - the topic is usable even before other topics graduate (or even\n   when they get discarded)\n\nplease make it a habit to avoid making your topic (i.e. this one)\nhostage to another topic (i.e. the absorbgitdirs one), and certainly\nnot hostage to the whole of 'next'.  A trivial conflict resolution\nin this case, if you revert the rebasing and then attempt to merge\nthe result to 'next', would look like this.\n\ndiff --cc contrib/completion/git-completion.bash\nindex 8b3b5a9d34,de56879960..0000000000\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@@ -2573,7 -2573,7 +2573,7 @@@ _git_submodule (\n  {\n  \t__git_has_doubledash && return\n  \n- \tlocal subcommands=\"add status init deinit update set-branch summary foreach sync\"\n -\tlocal subcommands=\"add status init deinit update summary foreach sync absorbgitdirs\"\n++\tlocal subcommands=\"add status init deinit update set-branch summary foreach sync absorbgitdirs\"\n  \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n  \tif [ -z \"$subcommand\" ]; then\n  \t\tcase \"$cur\" in\n\n\nBy the way, if conflicts worry you so much, one thing you could do\nis this.  Instead of maintaining the ever-growing list of\nsubcommands and having to worry about textual conflicts, the\ncompletion script could use a clean-up to reduce the need of textual\nconflict resolution, when it is quiescent, perhaps like this (I am\nassuming that in some future, there is a quiescent period _after_\nboth of these two topics landed, and this illustration patch is to\nbe used in such a future).\n\nMerging two topics, each of which adds a new element by inserting a\nnew line with the element (and the element alone) is on it, is\ncertainly a lot easier and simpler than having to see what word is\ngetting inserted by each topic on a single long string on a line.\n\n\n contrib/completion/git-completion.bash | 13 ++++++++++++-\n 1 file changed, 12 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 0fccadfc97..5d7d4ebacc 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -2573,7 +2573,18 @@ _git_submodule ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal subcommands=\"add status init deinit update set-branch summary foreach sync absorbgitdirs\"\n+\tlocal subcommands=\"\n+\t\tadd\n+\t\tstatus\n+\t\tinit\n+\t\tdeinit\n+\t\tupdate\n+\t\tset-branch\n+\t\tsummary\n+\t\tforeach\n+\t\tsync\n+\t\tabsorbgitdirs\n+\t\"\n \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n \tif [ -z \"$subcommand\" ]; then\n \t\tcase \"$cur\" in\n\n\n\n"},{"id":"368729","messageId":"xmqqmun7nz3d.fsf@gitster-ct.c.googlers.com","threadId":"50412","inReplyTo":"e90dfe992e96b33f167d08fe51df49ab1d10ef23.1549534460.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 2/3] submodule--helper: teach config subcommand --unset","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-07T20:05:42Z","receivedAt":"2019-02-07T20:05:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> This teaches submodule--helper config the --unset option, which removes\n> the specified configuration key from the .gitmodule file.\n>\n> Signed-off-by: Denton Liu <liu.denton@gmail.com>\n> ---\n>  builtin/submodule--helper.c | 18 ++++++++++++------\n>  t/t7411-submodule-config.sh |  9 +++++++++\n>  2 files changed, 21 insertions(+), 6 deletions(-)\n>\n> diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\n> index b80fc4ba3d..a86eacf167 100644\n> --- a/builtin/submodule--helper.c\n> +++ b/builtin/submodule--helper.c\n> @@ -2148,17 +2148,22 @@ static int check_name(int argc, const char **argv, const char *prefix)\n>  static int module_config(int argc, const char **argv, const char *prefix)\n>  {\n>  \tenum {\n> -\t\tCHECK_WRITEABLE = 1\n> -\t} command = 0;\n> +\t\tNONE,\n> +\t\tCHECK_WRITEABLE,\n> +\t\tDO_UNSET\n> +\t} command = NONE;\n\nI do not think the above, except for addition of DO_UNSET, is a good\nchange.  The language spec may guarantee that NONE is 0, but in the\nway the original is written, it is much more obvious that integer\nzero is a special value and the variable is initialized to that\nspecial value, and that is important.  The above rewrite makes it\nlook as if there are a bunch of symbolic constants defined by this\nparticular caller and one random value NONE, whose only significance\nis that it is different from any other value, is picked as its\ninitial value---but that is a wrong impression to give to the\nreaders.  parse-options.c::get_value() special cases integer zero as\n\"unset\" for any CMDMODE, so inventing a symbolic constant used by\nthis particular user is counter-productive.  Needless to say, it is\nnot such a great idea to use such an overly generic word NONE here.\n\nThe way the original did to make sure all enum values are non-zero\n(by explicitly documenting that its first value is 1) and used\nliteral 0 as \"not specified\" is much better aligned to the way how\nOPT_CMDMODE() is to be used, I think.\n\n>  \n>  \tstruct option module_config_options[] = {\n>  \t\tOPT_CMDMODE(0, \"check-writeable\", &command,\n>  \t\t\t    N_(\"check if it is safe to write to the .gitmodules file\"),\n>  \t\t\t    CHECK_WRITEABLE),\n> +\t\tOPT_CMDMODE(0, \"unset\", &command,\n> +\t\t\t    N_(\"unset the config in the .gitmodules file\"),\n> +\t\t\t    DO_UNSET),\n>  \t\tOPT_END()\n>  \t};\n>  \tconst char *const git_submodule_helper_usage[] = {\n> -\t\tN_(\"git submodule--helper config name [value]\"),\n> +\t\tN_(\"git submodule--helper config name [--unset] [value]\"),\n\nThat gives an impression that \"config name --unset value\" is a valid\ninput; isn't it more like \"you can unset, or you can set to a\nvalue\"?  The way to spell it would be \"... config name [--unset | value]\"\nbut it raises a larger question.  What if you want to set to a value\nthat is a string \"--unset\"?  Actually, allowing an option that comes\nafter \"name\" (which is an arbitrary end-user supplied thing) is one\nthing, but writing it in the documentation as if we are encouraging\nit is probably not a good idea.  Shouldn't it be \"config --unset name\"?\n\nIn any case, seeing the new test in 7411, I think the best way to\nwrite the above usage text would be to add one new line without\nmucking with the existing \"show it, or set it to the given value\"\nand add\n\n\tgit submodule--helper config --unset name\n\nas a separate item to the list.\n\n> diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\n> index 89690b7adb..fcc0fb82d8 100755\n> --- a/t/t7411-submodule-config.sh\n> +++ b/t/t7411-submodule-config.sh\n> @@ -142,6 +142,15 @@ test_expect_success 'reading submodules config from the working tree with \"submo\n>  \t)\n>  '\n>  \n> +test_expect_success 'unsetting submodules config from the working tree with \"submodule--helper config --unset\"' '\n> +\t(cd super &&\n> +\t\tgit submodule--helper config --unset submodule.submodule.url &&\n> +\t\tgit submodule--helper config submodule.submodule.url >actual &&\n"},{"id":"368746","messageId":"xmqqy36rme0k.fsf@gitster-ct.c.googlers.com","threadId":"50412","inReplyTo":"91bb634dfad7f6a17bbed9eaf27f668326fca54e.1549534460.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 3/3] submodule: teach set-branch subcommand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-07T22:26:19Z","receivedAt":"2019-02-07T22:26:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> @@ -168,6 +169,12 @@ submodule with the `--init` option.\n>  If `--recursive` is specified, this command will recurse into the\n>  registered submodules, and update any nested submodules within.\n>  --\n> +set-branch ((-d|--default)|(-b|--branch <branch>)) [--] <path>::\n> +\tSets the default remote tracking branch for the submodule. The\n> +\t`--branch` option allows the remote branch to be specified. The\n> +\t`--default` option removes the submodule.<name>.branch configuration\n> +\tkey, which causes the tracking branch to default to 'master'.\n> +--\n>  summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]::\n>  \tShow commit summary between the given commit (defaults to HEAD) and\n>  \tworking tree/index. For a submodule in question, a series of commits\n\nThe double-dash line you added must be replaced with an empty line.\nThe existing double-dash is *not* a separator between the previous\nentry (i.e. update) and the next entry (i.e. summary).  Rather, the\nbody for 'update' is enclosed in a pair of double-dash lines as it\nhas many paragraphs.\n"},{"id":"368748","messageId":"xmqqpns3mdvh.fsf@gitster-ct.c.googlers.com","threadId":"50412","inReplyTo":"e90dfe992e96b33f167d08fe51df49ab1d10ef23.1549534460.git.liu.denton@gmail.com","subject":"Re: [PATCH v3 2/3] submodule--helper: teach config subcommand --unset","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-07T22:29:22Z","receivedAt":"2019-02-07T22:29:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> +\tif (argc == 3 || (argc == 2 && command == DO_UNSET)) {\n>  \t\tif (!is_writing_gitmodules_ok())\n>  \t\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n>  \n> -\t\treturn config_set_in_gitmodules_file_gently(argv[1], argv[2]);\n> +\t\tconst char *value = (argc == 3) ? argv[2] : NULL;\n\nThis introduces decl-after-stmt.  Move it before the \"is it OK to\nwrite?\" check.\n\n> +\t\treturn config_set_in_gitmodules_file_gently(argv[1], value);\n>  \t}\n"},{"id":"368777","messageId":"20190208053152.GA3378@archbookpro.localdomain","threadId":"50412","inReplyTo":"xmqqo97npjej.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH v3 0/3] Teach submodule set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-08T05:31:52Z","receivedAt":"2019-02-08T05:33:06Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Thu, Feb 07, 2019 at 10:01:40AM -0800, Junio C Hamano wrote:\n> Denton Liu <liu.denton@gmail.com> writes:\n> \n> > I rebased the changes onto the latest 'next' because if this branch gets\n> > merged into 'next', there'll be merge conflicts from\n> > 'dl/complete-submodule-absorbgitdirs'.\n> \n> Please don't do that.\n> \n> A topic that depends on everything in 'next' cannot graduate to\n> 'master' until everything that is cooking in 'next' does.\n> \n> When\n> \n>  - the \"conflict\" that would arise is so trivial to resolve,\n> \n>  - there is no semantic crashes between the new topic and existing\n>     ones, and\n> \n>  - the topic is usable even before other topics graduate (or even\n>    when they get discarded)\n> \n> please make it a habit to avoid making your topic (i.e. this one)\n> hostage to another topic (i.e. the absorbgitdirs one), and certainly\n> not hostage to the whole of 'next'.  A trivial conflict resolution\n> in this case, if you revert the rebasing and then attempt to merge\n> the result to 'next', would look like this.\n\nMy mistake, even though I've made a few contributions already, I'm still\ngetting used to the git.git workflow.\n\nThanks so much for helping me out and please don't hesitate to let me\nknow if I'm doing anything else wrong.\n\nBy the way, just for the record, how would you like me to handle\npatchsets that cause merge conflicts?\n\nThanks,\n\nDenton\n"},{"id":"368823","messageId":"cover.1549624679.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549534460.git.liu.denton@gmail.com","subject":"[PATCH v4 0/3] Teach submodule set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-08T11:21:25Z","receivedAt":"2019-02-08T11:21:30Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Thanks so much for the feedback, Junio. I've updated the patchset based\non your comments.\n\nCurrently, there is no way to set the branch of a submodule without\nmanually manipulating the .gitmodules file. This patchset introduces a\nporcelain command that enables this.\n\nChanges since v1:\n\t* Fixed incorrect usage of OPT_CMDMODE\n\nChanges since v2:\n\t* Corrected missing argument for -b/--branch in git-submodule.txt\n\t* Rebased onto latest next\n\nChanges since v3:\n\t* Rebased back onto master\n\t* Address Junio's comments and improve clarity of submodule--helper patch\n\t* Fix incorrect documentation formatting in git-submodule.txt\n\n\nDenton Liu (3):\n  git-submodule.txt: \"--branch <branch>\" option defaults to 'master'\n  submodule--helper: teach config subcommand --unset\n  submodule: teach set-branch subcommand\n\n Documentation/git-submodule.txt        | 14 +++-\n builtin/submodule--helper.c            | 17 +++--\n contrib/completion/git-completion.bash |  5 +-\n git-submodule.sh                       | 75 +++++++++++++++++++--\n t/t7411-submodule-config.sh            |  9 +++\n t/t7419-submodule-set-branch.sh        | 93 ++++++++++++++++++++++++++\n 6 files changed, 200 insertions(+), 13 deletions(-)\n create mode 100755 t/t7419-submodule-set-branch.sh\n\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368824","messageId":"2ba8751212b634dd18e16011b1714588e43502e1.1549624679.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549624679.git.liu.denton@gmail.com","subject":"[PATCH v4 1/3] git-submodule.txt: \"--branch <branch>\" option defaults to 'master'","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-08T11:21:28Z","receivedAt":"2019-02-08T11:21:36Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This behavior is mentioned in gitmodules.txt but not in\ngit-submodule.txt so we copy the information over so that it is not\nmissed.\n\nAlso, add the missed argument to the -b/--branch option.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n Documentation/git-submodule.txt | 7 ++++---\n 1 file changed, 4 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex ba3c4df550..4150148fa3 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -255,13 +255,14 @@ OPTIONS\n \tThis option is only valid for the deinit command. Unregister all\n \tsubmodules in the working tree.\n \n--b::\n---branch::\n+-b <branch>::\n+--branch <branch>::\n \tBranch of repository to add as submodule.\n \tThe name of the branch is recorded as `submodule.<name>.branch` in\n \t`.gitmodules` for `update --remote`.  A special value of `.` is used to\n \tindicate that the name of the branch in the submodule should be the\n-\tsame name as the current branch in the current repository.\n+\tsame name as the current branch in the current repository.  If the\n+\toption is not specified, it defaults to 'master'.\n \n -f::\n --force::\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368825","messageId":"e204c58f0fd702a9bbd09fcc033ca1a9f99cd362.1549624679.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549624679.git.liu.denton@gmail.com","subject":"[PATCH v4 2/3] submodule--helper: teach config subcommand --unset","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-08T11:21:31Z","receivedAt":"2019-02-08T11:21:36Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This teaches submodule--helper config the --unset option, which removes\nthe specified configuration key from the .gitmodule file.\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n---\n builtin/submodule--helper.c | 17 ++++++++++++-----\n t/t7411-submodule-config.sh |  9 +++++++++\n 2 files changed, 21 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex 0e140f176c..449e56f30c 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -2147,17 +2147,22 @@ static int check_name(int argc, const char **argv, const char *prefix)\n static int module_config(int argc, const char **argv, const char *prefix)\n {\n \tenum {\n-\t\tCHECK_WRITEABLE = 1\n+\t\tCHECK_WRITEABLE = 1,\n+\t\tDO_UNSET = 2\n \t} command = 0;\n \n \tstruct option module_config_options[] = {\n \t\tOPT_CMDMODE(0, \"check-writeable\", &command,\n \t\t\t    N_(\"check if it is safe to write to the .gitmodules file\"),\n \t\t\t    CHECK_WRITEABLE),\n+\t\tOPT_CMDMODE(0, \"unset\", &command,\n+\t\t\t    N_(\"unset the config in the .gitmodules file\"),\n+\t\t\t    DO_UNSET),\n \t\tOPT_END()\n \t};\n \tconst char *const git_submodule_helper_usage[] = {\n-\t\tN_(\"git submodule--helper config name [value]\"),\n+\t\tN_(\"git submodule--helper config <name> [<value>]\"),\n+\t\tN_(\"git submodule--helper config --unset <name>\"),\n \t\tN_(\"git submodule--helper config --check-writeable\"),\n \t\tNULL\n \t};\n@@ -2169,15 +2174,17 @@ static int module_config(int argc, const char **argv, const char *prefix)\n \t\treturn is_writing_gitmodules_ok() ? 0 : -1;\n \n \t/* Equivalent to ACTION_GET in builtin/config.c */\n-\tif (argc == 2)\n+\tif (argc == 2 && command != DO_UNSET)\n \t\treturn print_config_from_gitmodules(the_repository, argv[1]);\n \n \t/* Equivalent to ACTION_SET in builtin/config.c */\n-\tif (argc == 3) {\n+\tif (argc == 3 || (argc == 2 && command == DO_UNSET)) {\n+\t\tconst char *value = (argc == 3) ? argv[2] : NULL;\n+\n \t\tif (!is_writing_gitmodules_ok())\n \t\t\tdie(_(\"please make sure that the .gitmodules file is in the working tree\"));\n \n-\t\treturn config_set_in_gitmodules_file_gently(argv[1], argv[2]);\n+\t\treturn config_set_in_gitmodules_file_gently(argv[1], value);\n \t}\n \n \tusage_with_options(git_submodule_helper_usage, module_config_options);\ndiff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh\nindex 89690b7adb..fcc0fb82d8 100755\n--- a/t/t7411-submodule-config.sh\n+++ b/t/t7411-submodule-config.sh\n@@ -142,6 +142,15 @@ test_expect_success 'reading submodules config from the working tree with \"submo\n \t)\n '\n \n+test_expect_success 'unsetting submodules config from the working tree with \"submodule--helper config --unset\"' '\n+\t(cd super &&\n+\t\tgit submodule--helper config --unset submodule.submodule.url &&\n+\t\tgit submodule--helper config submodule.submodule.url >actual &&\n+\t\ttest_must_be_empty actual\n+\t)\n+'\n+\n+\n test_expect_success 'writing submodules config with \"submodule--helper config\"' '\n \t(cd super &&\n \t\techo \"new_url\" >expect &&\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368826","messageId":"77af7e4b2fc094d8cd31164625ef3339e97e1cd5.1549624679.git.liu.denton@gmail.com","threadId":"50412","inReplyTo":"cover.1549624679.git.liu.denton@gmail.com","subject":"[PATCH v4 3/3] submodule: teach set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-08T11:21:34Z","receivedAt":"2019-02-08T11:21:39Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"This teaches git-submodule the set-branch subcommand which allows the\nbranch of a submodule to be set through a porcelain command without\nhaving to manually manipulate the .gitmodules file.\n---\n Documentation/git-submodule.txt        |  7 ++\n contrib/completion/git-completion.bash |  5 +-\n git-submodule.sh                       | 75 +++++++++++++++++++--\n t/t7419-submodule-set-branch.sh        | 93 ++++++++++++++++++++++++++\n 4 files changed, 175 insertions(+), 5 deletions(-)\n create mode 100755 t/t7419-submodule-set-branch.sh\n\ndiff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt\nindex 4150148fa3..4daf144180 100644\n--- a/Documentation/git-submodule.txt\n+++ b/Documentation/git-submodule.txt\n@@ -14,6 +14,7 @@ SYNOPSIS\n 'git submodule' [--quiet] init [--] [<path>...]\n 'git submodule' [--quiet] deinit [-f|--force] (--all|[--] <path>...)\n 'git submodule' [--quiet] update [<options>] [--] [<path>...]\n+'git submodule' [--quiet] set-branch [<options>] [--] <path>\n 'git submodule' [--quiet] summary [<options>] [--] [<path>...]\n 'git submodule' [--quiet] foreach [--recursive] <command>\n 'git submodule' [--quiet] sync [--recursive] [--] [<path>...]\n@@ -168,6 +169,12 @@ submodule with the `--init` option.\n If `--recursive` is specified, this command will recurse into the\n registered submodules, and update any nested submodules within.\n --\n+set-branch ((-d|--default)|(-b|--branch <branch>)) [--] <path>::\n+\tSets the default remote tracking branch for the submodule. The\n+\t`--branch` option allows the remote branch to be specified. The\n+\t`--default` option removes the submodule.<name>.branch configuration\n+\tkey, which causes the tracking branch to default to 'master'.\n+\n summary [--cached|--files] [(-n|--summary-limit) <n>] [commit] [--] [<path>...]::\n \tShow commit summary between the given commit (defaults to HEAD) and\n \tworking tree/index. For a submodule in question, a series of commits\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 499e56f83d..8b3b5a9d34 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -2573,7 +2573,7 @@ _git_submodule ()\n {\n \t__git_has_doubledash && return\n \n-\tlocal subcommands=\"add status init deinit update summary foreach sync\"\n+\tlocal subcommands=\"add status init deinit update set-branch summary foreach sync\"\n \tlocal subcommand=\"$(__git_find_on_cmdline \"$subcommands\")\"\n \tif [ -z \"$subcommand\" ]; then\n \t\tcase \"$cur\" in\n@@ -2604,6 +2604,9 @@ _git_submodule ()\n \t\t\t--force --rebase --merge --reference --depth --recursive --jobs\n \t\t\"\n \t\t;;\n+\tset-branch,--*)\n+\t\t__gitcomp \"--default --branch\"\n+\t\t;;\n \tsummary,--*)\n \t\t__gitcomp \"--cached --files --summary-limit\"\n \t\t;;\ndiff --git a/git-submodule.sh b/git-submodule.sh\nindex 5e608f8bad..43ec756602 100755\n--- a/git-submodule.sh\n+++ b/git-submodule.sh\n@@ -10,6 +10,7 @@ USAGE=\"[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <re\n    or: $dashless [--quiet] init [--] [<path>...]\n    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)\n    or: $dashless [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]\n+   or: $dashless [--quiet] set-branch (--default|--branch <branch>) [--] <path>\n    or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]\n    or: $dashless [--quiet] foreach [--recursive] <command>\n    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]\n@@ -684,6 +685,72 @@ cmd_update()\n \t}\n }\n \n+#\n+# Configures a submodule's default branch\n+#\n+# $@ = requested path\n+#\n+cmd_set_branch() {\n+\tunset_branch=false\n+\tbranch=\n+\n+\twhile test $# -ne 0\n+\tdo\n+\t\tcase \"$1\" in\n+\t\t-q|--quiet)\n+\t\t\t# we don't do anything with this but we need to accept it\n+\t\t\t;;\n+\t\t-d|--default)\n+\t\t\tunset_branch=true\n+\t\t\t;;\n+\t\t-b|--branch)\n+\t\t\tcase \"$2\" in '') usage ;; esac\n+\t\t\tbranch=$2\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--)\n+\t\t\tshift\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t-*)\n+\t\t\tusage\n+\t\t\t;;\n+\t\t*)\n+\t\t\tbreak\n+\t\t\t;;\n+\t\tesac\n+\t\tshift\n+\tdone\n+\n+\tif test $# -ne 1\n+\tthen\n+\t\tusage\n+\tfi\n+\n+\t# we can't use `git submodule--helper name` here because internally, it\n+\t# hashes the path so a trailing slash could lead to an unintentional no match\n+\tname=\"$(git submodule--helper list \"$1\" | cut -f2)\"\n+\tif test -z \"$name\"\n+\tthen\n+\t\texit 1\n+\tfi\n+\n+\ttest -n \"$branch\"; has_branch=$?\n+\ttest \"$unset_branch\" = true; has_unset_branch=$?\n+\n+\tif test $((!$has_branch != !$has_unset_branch)) -eq 0\n+\tthen\n+\t\tusage\n+\tfi\n+\n+\tif test $has_branch -eq 0\n+\tthen\n+\t\tgit submodule--helper config submodule.\"$name\".branch \"$branch\"\n+\telse\n+\t\tgit submodule--helper config --unset submodule.\"$name\".branch\n+\tfi\n+}\n+\n #\n # Show commit summary for submodules in index or working tree\n #\n@@ -980,7 +1047,7 @@ cmd_absorbgitdirs()\n while test $# != 0 && test -z \"$command\"\n do\n \tcase \"$1\" in\n-\tadd | foreach | init | deinit | update | status | summary | sync | absorbgitdirs)\n+\tadd | foreach | init | deinit | update | set-branch | status | summary | sync | absorbgitdirs)\n \t\tcommand=$1\n \t\t;;\n \t-q|--quiet)\n@@ -1021,8 +1088,8 @@ then\n     fi\n fi\n \n-# \"-b branch\" is accepted only by \"add\"\n-if test -n \"$branch\" && test \"$command\" != add\n+# \"-b branch\" is accepted only by \"add\" and \"set-branch\"\n+if test -n \"$branch\" && (test \"$command\" != add || test \"$command\" != set-branch)\n then\n \tusage\n fi\n@@ -1033,4 +1100,4 @@ then\n \tusage\n fi\n \n-\"cmd_$command\" \"$@\"\n+\"cmd_$(echo $command | sed -e s/-/_/g)\" \"$@\"\ndiff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh\nnew file mode 100755\nindex 0000000000..c4b370ea85\n--- /dev/null\n+++ b/t/t7419-submodule-set-branch.sh\n@@ -0,0 +1,93 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2019 Denton Liu\n+#\n+\n+test_description='Test submodules set-branch subcommand\n+\n+This test verifies that the set-branch subcommand of git-submodule is working\n+as expected.\n+'\n+\n+TEST_NO_CREATE_REPO=1\n+. ./test-lib.sh\n+\n+test_expect_success 'submodule config cache setup' '\n+\tmkdir submodule &&\n+\t(cd submodule &&\n+\t\tgit init &&\n+\t\techo a >a &&\n+\t\tgit add . &&\n+\t\tgit commit -ma &&\n+\t\tgit checkout -b topic &&\n+\t\techo b >a &&\n+\t\tgit add . &&\n+\t\tgit commit -mb\n+\t) &&\n+\tmkdir super &&\n+\t(cd super &&\n+\t\tgit init &&\n+\t\tgit submodule add ../submodule &&\n+\t\tgit commit -m \"add submodule\"\n+\t)\n+'\n+\n+test_expect_success 'ensure submodule branch is unset' '\n+\t(cd super &&\n+\t\ttest_must_fail grep branch .gitmodules\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch --branch' '\n+\t(cd super &&\n+\t\tgit submodule set-branch --branch topic submodule &&\n+\t\tgrep \"branch = topic\" .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\tb\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch --default' '\n+\t(cd super &&\n+\t\tgit submodule set-branch --default submodule &&\n+\t\ttest_must_fail grep branch .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\ta\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch -b' '\n+\t(cd super &&\n+\t\tgit submodule set-branch -b topic submodule &&\n+\t\tgrep \"branch = topic\" .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\tb\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_expect_success 'test submodule set-branch -d' '\n+\t(cd super &&\n+\t\tgit submodule set-branch -d submodule &&\n+\t\ttest_must_fail grep branch .gitmodules &&\n+\t\tgit submodule update --remote &&\n+\t\tcat <<-\\EOF >expect &&\n+\t\ta\n+\t\tEOF\n+\t\tgit -C submodule show -s --pretty=%s >actual &&\n+\t\ttest_cmp expect actual\n+\t)\n+'\n+\n+test_done\n-- \n2.20.1.522.g5f42c252e9\n\n"},{"id":"368855","messageId":"xmqqwomajf2z.fsf@gitster-ct.c.googlers.com","threadId":"50412","inReplyTo":"20190208053152.GA3378@archbookpro.localdomain","subject":"Re: [PATCH v3 0/3] Teach submodule set-branch subcommand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-02-08T18:43:48Z","receivedAt":"2019-02-08T18:43:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Denton Liu <liu.denton@gmail.com> writes:\n\n> By the way, just for the record, how would you like me to handle\n> patchsets that cause merge conflicts?\n\nWhen it happens, I may ask you to rebase onto a specific commit.\nhttps://public-inbox.org/git/xmqq5ztxstkh.fsf@gitster-ct.c.googlers.com/\nis a recent example.\n\nMy preference (read: I'd be grateful if contributors tried to stick\nto it, but it won't be the reason for patch rejection if they don't)\nis:\n\n 1. Choose the right base:\n\n   a) For a fix to a bug that already exists in the last feature\n      release (i.e. v2.20.0), build on 'maint' and make sure it\n      merges cleanly to 'master', and the merge result builds and\n      passes tests.  Depending on the severity of the bug, we might\n      want to make sure that the fix applies maintenance track even\n      older, but it would be something you would be sending patches\n      to git-security mailing list---over there we'll figure out the\n      right base on case-by-case basis.\n\n   b) For a new feature, build on 'master', if you can.\n\n   c) If you need to use something (i.e. a new helper function,\n      updated type, etc.) in 'next' that is not yet in 'master',\n      identify the topic(s) that introduces these things you need,\n      merge them to 'master' and build on top of it.  If you did so,\n      please note in the cover letter what topics you depend on.\n\n   d) When updating a topic that is already in my tree\n      (i.e. rerolling), stick to the same base as the previous\n      round, if possible.  You can find out the commit the previous\n      round was applied on top by fetching from me.  Your reroll may\n      start using something the previous round did not use from\n      'next', in which case you may end up doing c) above, which is\n      OK.  Just make a note in the cover letter to let reviewers\n      know.\n\n 2. Make sure the result builds and passes tests.\n\n 3. Make sure the result merges cleanly to 'next', and the merge\n    result builds and passes tests.\n\n 4. In any of the above steps where you are asked to \"make sure it\n    merges cleanly\", you may see merge conflicts.\n\n   a) If they are too much to resolve for you, for a change that is\n      not a bugfix, you may have to depend on the other topic(s).\n      Identify the topic(s) that touches these lines that heavily\n      conflict with your changes, merge them to 'master' and base\n      your topic on top of it (i.e. going back to step 1.c).\n\n   b) If they are easy to resolve for you, do not worry too much\n      about them.  It may be helpful to note in the cover letter\n      \"this may have minor textual conflict with these other\n      topics\".\n   \n   c) If you are left with huge conflict while working on a bugfix\n      change, we need to resolve it on case-by-case basis, so send\n      it out with the chosen base.  Noting that it conflicts heavily\n      with 'master' or 'next' would be very much appreciated when\n      this happens.\n\nThanks.\n"},{"id":"368901","messageId":"CA+eFxx4DWiFY5aqbggQWCLQE0AnWhOvYMjgyPhui1WGSNqQtZQ@mail.gmail.com","threadId":"50412","inReplyTo":"77af7e4b2fc094d8cd31164625ef3339e97e1cd5.1549624679.git.liu.denton@gmail.com","subject":"Re: [PATCH v4 3/3] submodule: teach set-branch subcommand","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-02-08T23:51:41Z","receivedAt":"2019-02-08T23:52:21Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"On Fri, 8 Feb 2019 at 03:21, Denton Liu <liu.denton@gmail.com> wrote:\n> This teaches git-submodule the set-branch subcommand which allows the\n> branch of a submodule to be set through a porcelain command without\n> having to manually manipulate the .gitmodules file.\n> ---\n\nSorry Junio, I forgot to attach my sign-off to this patch. Would it be possible\nfor you to tack it on for me please?\n\nSigned-off-by: Denton Liu <liu.denton@gmail.com>\n\nThanks,\n\nDenton\n"}]}