git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v1 2/2] worktree: make add dwim

From
Thomas Gummerer <t.gummerer@gmail.com>
Date
Nov 12, 2017, 13:43 UTC
Message-ID
<20171112134305.3949-2-t.gummerer@gmail.com>
In-Reply-To
<20171112134305.3949-1-t.gummerer@gmail.com>

Currently git worktree add creates a new branch, that matches the HEAD of whichever worktree we were on when calling "git worktree add".

Add a --guess flag to git worktree add, that makes it behave like the dwim machinery in 'git checkout <new-branch>', i.e. check if the new branch name uniquely matches the branch name of a remote tracking branch, and if so check out that branch, and set the upstream to the remote tracking branch.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---

I'm a bit torn about hiding his behind an additional flag in git worktree add or not. I would like to have the feature without the additional flag, but it might break some peoples expectations, so dunno.

 builtin/worktree.c      | 14 +++++++++-
 t/t2025-worktree-add.sh | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 7b9307aa58..5740d1f8a3 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "checkout.h"
 #include "config.h"
 #include "builtin.h"
 #include "dir.h"
@@ -341,6 +342,7 @@ static int add(int ac, const char **av, const char *prefix)
 	const char *new_branch_force = NULL;
 	char *path;
 	const char *branch;
+	int dwim_new_branch = 0;
 	struct option options[] = {
 		OPT__FORCE(&opts.force, N_("checkout <branch> even if already checked out in other worktree")),
 		OPT_STRING('b', NULL, &opts.new_branch, N_("branch"),
@@ -350,6 +352,7 @@ static int add(int ac, const char **av, const char *prefix)
 		OPT_BOOL(0, "detach", &opts.detach, N_("detach HEAD at named commit")),
 		OPT_BOOL(0, "checkout", &opts.checkout, N_("populate the new working tree")),
 		OPT_BOOL(0, "lock", &opts.keep_locked, N_("keep the new working tree locked")),
+		OPT_BOOL(0, "guess", &dwim_new_branch, N_("checkout upstream branch if there's a unique match")),
 		OPT_END()
 	};
 
@@ -363,6 +366,7 @@ static int add(int ac, const char **av, const char *prefix)
 
 	path = prefix_filename(prefix, av[0]);
 	branch = ac < 2 ? "HEAD" : av[1];
+	dwim_new_branch = ac < 2 ? dwim_new_branch : 0;
 
 	if (!strcmp(branch, "-"))
 		branch = "@{-1}";
@@ -387,13 +391,21 @@ static int add(int ac, const char **av, const char *prefix)
 	}
 
 	if (opts.new_branch) {
+		struct object_id oid;
+		const char *remote;
 		struct child_process cp = CHILD_PROCESS_INIT;
+
+		remote = unique_tracking_name(opts.new_branch, &oid);
+
 		cp.git_cmd = 1;
 		argv_array_push(&cp.args, "branch");
 		if (opts.force_new_branch)
 			argv_array_push(&cp.args, "--force");
 		argv_array_push(&cp.args, opts.new_branch);
-		argv_array_push(&cp.args, branch);
+		if (dwim_new_branch && remote)
+			argv_array_push(&cp.args, remote);
+		else
+			argv_array_push(&cp.args, branch);
 		if (run_command(&cp))
 			return -1;
 		branch = opts.new_branch;
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index b5c47ac602..b37c279787 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -6,6 +6,16 @@ test_description='test git worktree add'
 
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
+# Is branch "refs/heads/$1" set to pull from "$2/$3"?
+test_branch_upstream () {
+	printf "%s\n" "$2" "refs/heads/$3" >expect.upstream &&
+	{
+		git config "branch.$1.remote" &&
+		git config "branch.$1.merge"
+	} >actual.upstream &&
+	test_cmp expect.upstream actual.upstream
+}
+
 test_expect_success 'setup' '
 	test_commit init
 '
@@ -314,4 +324,64 @@ test_expect_success 'rename a branch under bisect not allowed' '
 	test_must_fail git branch -M under-bisect bisect-with-new-name
 '
 
+test_expect_success 'git worktree add does not dwim' '
+	test_when_finished rm -rf repo_a &&
+	test_when_finished rm -rf repo_b &&
+	test_when_finished rm -rf foo &&
+	git init repo_a &&
+	(
+		cd repo_a &&
+		test_commit a_master &&
+		git checkout -b foo &&
+		test_commit a_foo
+	) &&
+	git init repo_b &&
+	(
+		cd repo_b &&
+		test_commit b_master &&
+		git remote add repo_a ../repo_a &&
+		git config remote.repo_a.fetch \
+			"+refs/heads/*:refs/remotes/other_a/*" &&
+		git fetch --all &&
+		git worktree add ../foo
+	) &&
+	(
+		cd foo &&
+		! test_branch_upstream foo repo_a foo &&
+		git rev-parse other_a/foo >expect &&
+		git rev-parse foo >actual &&
+		! test_cmp expect actual
+	)
+'
+
+test_expect_success 'git worktree add --guess dwims' '
+	test_when_finished rm -rf repo_a &&
+	test_when_finished rm -rf repo_b &&
+	test_when_finished rm -rf foo &&
+	git init repo_a &&
+	(
+		cd repo_a &&
+		test_commit a_master &&
+		git checkout -b foo &&
+		test_commit a_foo
+	) &&
+	git init repo_b &&
+	(
+		cd repo_b &&
+		test_commit b_master &&
+		git remote add repo_a ../repo_a &&
+		git config remote.repo_a.fetch \
+			"+refs/heads/*:refs/remotes/other_a/*" &&
+		git fetch --all &&
+		git worktree add --guess ../foo
+	) &&
+	(
+		cd foo &&
+		test_branch_upstream foo repo_a foo &&
+		git rev-parse other_a/foo >expect &&
+		git rev-parse foo >actual &&
+		test_cmp expect actual
+	)
+'
+
 test_done
-- 
2.15.0.403.gc27cc4dac6
Previous: Thomas GummererNext: Junio C Hamano
Message 2 of 28 in “checkout: factor out functions to new lib file”
  1. 1/2 checkout: factor out functions to new lib fileThomas Gummerer, Nov 12, 2017
  2. 2/2 worktree: make add dwimThomas Gummerer, Nov 12, 2017
  3. Junio C HamanoNov 13, 2017
  4. Thomas GummererNov 14, 2017
  5. Eric SunshineNov 14, 2017
  6. Eric SunshineNov 14, 2017
  7. Thomas GummererNov 15, 2017
  8. Thomas GummererNov 18, 2017
  9. Thomas GummererNov 15, 2017
  10. Eric SunshineNov 15, 2017
  11. Junio C HamanoNov 13, 2017
  12. Thomas GummererNov 14, 2017
  13. 1/3 checkout: factor out functions to new lib fileThomas Gummerer, Nov 18, 2017
  14. 2/3 worktree: make add <path> <branch> dwimThomas Gummerer, Nov 18, 2017
  15. Thomas GummererNov 18, 2017
  16. 3/3 worktree: make add <path> dwimThomas Gummerer, Nov 18, 2017
  17. 0/3 make git worktree add dwim moreThomas Gummerer, Nov 18, 2017
  18. 2/3 worktree: make add <path> <branch> dwimThomas Gummerer, Nov 18, 2017
  19. Eric SunshineNov 19, 2017
  20. Thomas GummererNov 19, 2017
  21. 1/3 checkout: factor out functions to new lib fileThomas Gummerer, Nov 18, 2017
  22. 3/3 worktree: make add <path> dwimThomas Gummerer, Nov 18, 2017
  23. Eric SunshineNov 19, 2017
  24. Eric SunshineNov 19, 2017
  25. Junio C HamanoNov 20, 2017
  26. Thomas GummererNov 21, 2017
  27. Junio C HamanoNov 22, 2017
  28. Thomas GummererNov 22, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.