Skip to contentSkip to conversation

worktree: add --recurse-submodules flag to worktree add

PATCH In review Jimmy Aguilar Mena 1 participant 1 message Apr 16

lore
Share & tools
lore
#0 lore raw

PATCH 1/3 worktree: add --recurse-submodules flag to worktree add

git worktree add leaves submodules untouched: the linked worktree is checked out but its submodule working trees are empty. Users must run "git submodule update --init" by hand afterwards.

Add a --recurse-submodules flag that does this automatically. After checkout_worktree() succeeds, a child "git submodule update --init --recursive" is run with its working directory set to the new worktree path so that $GIT_DIR is resolved correctly.

The flag is incompatible with --no-checkout (nothing is checked out, so there is nowhere to put submodule working trees) and --orphan (the branch has no commits and therefore no submodule configuration to follow).

---
 builtin/worktree.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
builtin/worktree.c +23 -0
index 4fd6f7575f..f3dacb0e5c 100644
@@ -123,6 +123,7 @@ struct add_opts {
 	int checkout;
 	int orphan;
 	int relative_paths;
+	int recurse_submodules;
 	const char *keep_locked;
 };
 
@@ -593,6 +594,20 @@ static int add_worktree(const char *path, const char *refname,
 	    (ret = checkout_worktree(opts, &child_env)))
 		goto done;
 
+	if (!ret && opts->checkout && opts->recurse_submodules) {
+		struct child_process cp = CHILD_PROCESS_INIT;
+		cp.git_cmd = 1;
+		cp.dir = path;
+		strvec_pushl(&cp.args, "submodule", "update",
+			     "--init", "--recursive", NULL);
+		if (opts->quiet)
+			strvec_push(&cp.args, "--quiet");
+		strvec_pushv(&cp.env, child_env.v);
+		ret = run_command(&cp);
+		if (ret)
+			goto done;
+	}
+
 	is_junk = 0;
 	FREE_AND_NULL(junk_work_tree);
 	FREE_AND_NULL(junk_git_dir);
@@ -823,6 +838,8 @@ static int add(int ac, const char **av, const char *prefix,
 			 N_("try to match the new branch name with a remote-tracking branch")),
 		OPT_BOOL(0, "relative-paths", &opts.relative_paths,
 			 N_("use relative paths for worktrees")),
+		OPT_BOOL(0, "recurse-submodules", &opts.recurse_submodules,
+			 N_("initialize submodules in the new worktree")),
 		OPT_END()
 	};
 	int ret;
@@ -842,6 +859,12 @@ static int add(int ac, const char **av, const char *prefix,
 	if (opts.orphan && !opts.checkout)
 		die(_("options '%s' and '%s' cannot be used together"),
 		    "--orphan", "--no-checkout");
+	if (opts.recurse_submodules && !opts.checkout)
+		die(_("options '%s' and '%s' cannot be used together"),
+		    "--recurse-submodules", "--no-checkout");
+	if (opts.recurse_submodules && opts.orphan)
+		die(_("options '%s' and '%s' cannot be used together"),
+		    "--recurse-submodules", "--orphan");
 	if (opts.orphan && ac == 2)
 		die(_("option '%s' and commit-ish cannot be used together"),
 		    "--orphan");