{"thread":{"id":"65496","subject":"[PATCH 1/3] worktree: add --recurse-submodules flag to worktree add","startedAt":"2026-04-16T16:34:19Z","lastAt":"2026-04-16T16:34:19Z","messageCount":1,"participants":["Jimmy Aguilar Mena"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"541752","messageId":"aeEPGNJ0Ge72l94j@RTX","threadId":"65496","inReplyTo":null,"subject":"[PATCH 1/3] worktree: add --recurse-submodules flag to worktree add","fromName":"Jimmy Aguilar Mena","fromEmail":"kratsbinovish@gmail.com","sentAt":"2026-04-16T16:34:14Z","receivedAt":"2026-04-16T16:34:19Z","isPatch":true,"body":"git worktree add leaves submodules untouched: the linked worktree is\nchecked out but its submodule working trees are empty.  Users must run\n\"git submodule update --init\" by hand afterwards.\n\nAdd a --recurse-submodules flag that does this automatically.  After\ncheckout_worktree() succeeds, a child \"git submodule update --init\n--recursive\" is run with its working directory set to the new worktree\npath so that $GIT_DIR is resolved correctly.\n\nThe flag is incompatible with --no-checkout (nothing is checked out, so\nthere is nowhere to put submodule working trees) and --orphan (the\nbranch has no commits and therefore no submodule configuration to\nfollow).\n\nSigned-off-by: Jimmy Aguilar Mena <kratsbinovish@gmail.com>\n---\n  builtin/worktree.c | 23 +++++++++++++++++++++++\n  1 file changed, 23 insertions(+)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 4fd6f7575f..f3dacb0e5c 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -123,6 +123,7 @@ struct add_opts {\n  \tint checkout;\n  \tint orphan;\n  \tint relative_paths;\n+\tint recurse_submodules;\n  \tconst char *keep_locked;\n  };\n  \n@@ -593,6 +594,20 @@ static int add_worktree(const char *path, const char *refname,\n  \t    (ret = checkout_worktree(opts, &child_env)))\n  \t\tgoto done;\n  \n+\tif (!ret && opts->checkout && opts->recurse_submodules) {\n+\t\tstruct child_process cp = CHILD_PROCESS_INIT;\n+\t\tcp.git_cmd = 1;\n+\t\tcp.dir = path;\n+\t\tstrvec_pushl(&cp.args, \"submodule\", \"update\",\n+\t\t\t     \"--init\", \"--recursive\", NULL);\n+\t\tif (opts->quiet)\n+\t\t\tstrvec_push(&cp.args, \"--quiet\");\n+\t\tstrvec_pushv(&cp.env, child_env.v);\n+\t\tret = run_command(&cp);\n+\t\tif (ret)\n+\t\t\tgoto done;\n+\t}\n+\n  \tis_junk = 0;\n  \tFREE_AND_NULL(junk_work_tree);\n  \tFREE_AND_NULL(junk_git_dir);\n@@ -823,6 +838,8 @@ static int add(int ac, const char **av, const char *prefix,\n  \t\t\t N_(\"try to match the new branch name with a remote-tracking branch\")),\n  \t\tOPT_BOOL(0, \"relative-paths\", &opts.relative_paths,\n  \t\t\t N_(\"use relative paths for worktrees\")),\n+\t\tOPT_BOOL(0, \"recurse-submodules\", &opts.recurse_submodules,\n+\t\t\t N_(\"initialize submodules in the new worktree\")),\n  \t\tOPT_END()\n  \t};\n  \tint ret;\n@@ -842,6 +859,12 @@ static int add(int ac, const char **av, const char *prefix,\n  \tif (opts.orphan && !opts.checkout)\n  \t\tdie(_(\"options '%s' and '%s' cannot be used together\"),\n  \t\t    \"--orphan\", \"--no-checkout\");\n+\tif (opts.recurse_submodules && !opts.checkout)\n+\t\tdie(_(\"options '%s' and '%s' cannot be used together\"),\n+\t\t    \"--recurse-submodules\", \"--no-checkout\");\n+\tif (opts.recurse_submodules && opts.orphan)\n+\t\tdie(_(\"options '%s' and '%s' cannot be used together\"),\n+\t\t    \"--recurse-submodules\", \"--orphan\");\n  \tif (opts.orphan && ac == 2)\n  \t\tdie(_(\"option '%s' and commit-ish cannot be used together\"),\n  \t\t    \"--orphan\");\n\n"}]}