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

[PATCH v9 8/8] worktree add: emit warn when there is a bad HEAD

From
Jacob Abel <jacobabel@nullpo.dev>
Date
Apr 17, 2023, 09:34 UTC
Message-ID
<20230417093255.31079-9-jacobabel@nullpo.dev>
In-Reply-To
<20230417093255.31079-1-jacobabel@nullpo.dev>

Add a warning to `worktree add` when the command tries to reference HEAD, there exist valid local branches, and the HEAD points to a non-existent reference.

Current Behavior: % git -C foo worktree list /path/to/repo/foo dadc8e6dac [main] /path/to/repo/foo_wt 0000000000 [badref] % git -C foo worktree add ../wt1 Preparing worktree (new branch 'wt1') HEAD is now at dadc8e6dac dummy commit % git -C foo_wt worktree add ../wt2 hint: If you meant to create a worktree containing a new orphan branch [...] hint: Disable this message with "git config advice.worktreeAddOrphan false" fatal: invalid reference: HEAD %

New Behavior: % git -C foo worktree list /path/to/repo/foo dadc8e6dac [main] /path/to/repo/foo_wt 0000000000 [badref] % git -C foo worktree add ../wt1 Preparing worktree (new branch 'wt1') HEAD is now at dadc8e6dac dummy commit % git -C foo_wt worktree add ../wt2 warning: HEAD points to an invalid (or orphaned) reference. HEAD path: '/path/to/repo/foo/.git/worktrees/foo_wt/HEAD' HEAD contents: 'ref: refs/heads/badref' hint: If you meant to create a worktree containing a new orphan branch [...] hint: Disable this message with "git config advice.worktreeAddOrphan false" fatal: invalid reference: HEAD %

Signed-off-by: Jacob Abel <jacobabel@nullpo.dev>
---
 builtin/worktree.c      | 34 +++++++++++++++++++++++++++++-----
 t/t2400-worktree-add.sh | 18 +++++++++++++++++-
 2 files changed, 46 insertions(+), 6 deletions(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 95b5bbb1d2..0fba4cfdf8 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -637,6 +637,9 @@ static int first_valid_ref(const char *refname,
  *
  * - Checks whether any valid local branches exist.
  *
+ * - Emits a warning if there exist any valid branches but HEAD does not point
+ *   to a valid reference.
+ *
  * Returns 1 if any of the previous checks are true, otherwise returns 0.
  */
 static int can_use_local_refs(const struct add_opts *opts)
@@ -644,6 +647,23 @@ static int can_use_local_refs(const struct add_opts *opts)
 	if (head_ref(first_valid_ref, NULL)) {
 		return 1;
 	} else if (for_each_branch_ref(first_valid_ref, NULL)) {
+		if (!opts->quiet) {
+			struct strbuf path = STRBUF_INIT;
+			struct strbuf contents = STRBUF_INIT;
+
+			strbuf_add_real_path(&path, get_worktree_git_dir(NULL));
+			strbuf_addstr(&path, "/HEAD");
+			strbuf_read_file(&contents, path.buf, 64);
+			strbuf_stripspace(&contents, 0);
+			strbuf_strip_suffix(&contents, "\n");
+
+			warning(_("HEAD points to an invalid (or orphaned) reference.\n"
+				  "HEAD path: '%s'\n"
+				  "HEAD contents: '%s'"),
+				  path.buf, contents.buf);
+			strbuf_release(&path);
+			strbuf_release(&contents);
+		}
 		return 1;
 	}
 	return 0;
@@ -665,16 +685,12 @@ static int can_use_local_refs(const struct add_opts *opts)
 static int can_use_remote_refs(const struct add_opts *opts)
 {
 	if (!guess_remote) {
-		if (!opts->quiet)
-			fprintf_ln(stderr, WORKTREE_ADD_DWIM_ORPHAN_INFER_TEXT);
 		return 0;
 	} else if (for_each_remote_ref(first_valid_ref, NULL)) {
 		return 1;
 	} else if (!opts->force && remote_get(NULL)) {
 		die(_("No local or remote refs exist despite at least one remote\n"
 		      "present, stopping; use 'add -f' to overide or fetch a remote first"));
-	} else if (!opts->quiet) {
-		fprintf_ln(stderr, WORKTREE_ADD_DWIM_ORPHAN_INFER_TEXT);
 	}
 	return 0;
 }
@@ -827,8 +843,12 @@ static int add(int ac, const char **av, const char *prefix)
 		int n;
 		const char *s = worktree_basename(path, &n);
 		new_branch = xstrndup(s, n);
-	} else if (opts.orphan || opts.detach) {
+	} else if (opts.orphan) {
 		// No-op
+	} else if (opts.detach) {
+		// Check HEAD
+		if (!strcmp(branch, "HEAD"))
+			can_use_local_refs(&opts);
 	} else if (ac < 2 && new_branch) {
 		// DWIM: Infer --orphan when repo has no refs.
 		opts.orphan = dwim_orphan(&opts, !!opt_track, 0);
@@ -853,6 +873,10 @@ static int add(int ac, const char **av, const char *prefix)
 				branch = remote;
 			}
 		}
+
+		if (!strcmp(branch, "HEAD"))
+			can_use_local_refs(&opts);
+
 	}

 	if (!opts.orphan && !lookup_commit_reference_by_name(branch)) {
diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh
index e5cca1d11b..09bf506155 100755
--- a/t/t2400-worktree-add.sh
+++ b/t/t2400-worktree-add.sh
@@ -729,6 +729,7 @@ test_dwim_orphan () {
 	local use_quiet=0 &&
 	local remote=0 &&
 	local remote_ref=0 &&
+	local use_detach=0 &&
 	local use_new_branch=0 &&

 	local outcome="$1" &&
@@ -754,6 +755,10 @@ test_dwim_orphan () {
 		success=0 &&
 		outcome_text='"add" error inferred "--orphan" gives illegal opts combo'
 		;;
+	"warn_bad_head")
+		success=0 &&
+		outcome_text='"add" error, warn on bad HEAD, hint use orphan'
+		;;
 	*)
 		echo "test_dwim_orphan(): invalid outcome: '$outcome'" >&2 &&
 		return 1
@@ -825,7 +830,7 @@ test_dwim_orphan () {
 			context="$context, invalid (or orphan) HEAD"
 			;;

-		# Whether the code path is tested with the base add command or -b
+		# Whether the code path is tested with the base add command, -b, or --detach
 		"no_-b")
 			use_new_branch=0 &&
 			context="$context, no --branch"
@@ -834,6 +839,10 @@ test_dwim_orphan () {
 			use_new_branch=1 &&
 			context="$context, --branch"
 			;;
+		"detach")
+			use_detach=1 &&
+			context="$context, --detach"
+			;;

 		# Whether to check that all output is suppressed (except errors)
 		# or that the output is as expected
@@ -894,6 +903,9 @@ test_dwim_orphan () {
 	if [ $use_new_branch -eq 1 ]
 	then
 		args="$args -b foo"
+	elif [ $use_detach -eq 1 ]
+	then
+		args="$args --detach"
 	else
 		context="DWIM (no --branch), $context"
 	fi &&
@@ -1036,6 +1048,10 @@ do
 		test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote no_remote_ref no_guess_remote
 		test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote no_remote_ref guess_remote
 		test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote remote_ref guess_remote
+
+		test_dwim_orphan 'warn_bad_head' $dwim_test_args no_-b local_ref bad_head
+		test_dwim_orphan 'warn_bad_head' $dwim_test_args -b local_ref bad_head
+		test_dwim_orphan 'warn_bad_head' $dwim_test_args detach local_ref bad_head
 	done

 	test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode no_-b no_checkout
--
2.39.2
Previous: Jacob AbelNext: Jacob Abel
Message 20 of 34 in “worktree: Support `--orphan` when creating new worktrees”
  1. 0/8 worktree: Support `--orphan` when creating new worktreesJacob Abel, Apr 17, 2023
  2. 1/8 worktree add: include -B in usage docsJacob Abel, Apr 17, 2023
  3. 2/8 t2400: print captured git output when finishedJacob Abel, Apr 17, 2023
  4. Junio C HamanoApr 17, 2023
  5. Jacob AbelApr 18, 2023
  6. Junio C HamanoApr 18, 2023
  7. Jacob AbelApr 19, 2023
  8. Jacob AbelApr 19, 2023
  9. Junio C HamanoApr 19, 2023
  10. Jacob AbelApr 19, 2023
  11. 4/8 t2400: add tests to verify --quietJacob Abel, Apr 17, 2023
  12. Junio C HamanoApr 17, 2023
  13. Jacob AbelApr 20, 2023
  14. 5/8 worktree add: add --orphan flagJacob Abel, Apr 17, 2023
  15. 7/8 worktree add: extend DWIM to infer --orphanJacob Abel, Apr 17, 2023
  16. 3/8 t2400: refactor "worktree add" opt exclusion testsJacob Abel, Apr 17, 2023
  17. Junio C HamanoApr 17, 2023
  18. Jacob AbelApr 20, 2023
  19. 6/8 worktree add: introduce "try --orphan" hintJacob Abel, Apr 17, 2023
  20. 8/8 worktree add: emit warn when there is a bad HEADJacob Abel, Apr 17, 2023
  21. Jacob AbelApr 20, 2023
  22. Junio C HamanoMay 1, 2023
  23. Jacob AbelMay 2, 2023
  24. 0/8 worktree: Support `--orphan` when creating new worktreesJacob Abel, May 17, 2023
  25. 1/8 worktree add: include -B in usage docsJacob Abel, May 17, 2023
  26. 2/8 t2400: cleanup created worktree in testJacob Abel, May 17, 2023
  27. 3/8 t2400: refactor "worktree add" opt exclusion testsJacob Abel, May 17, 2023
  28. 4/8 t2400: add tests to verify --quietJacob Abel, May 17, 2023
  29. 6/8 worktree add: introduce "try --orphan" hintJacob Abel, May 17, 2023
  30. 5/8 worktree add: add --orphan flagJacob Abel, May 17, 2023
  31. 7/8 worktree add: extend DWIM to infer --orphanJacob Abel, May 17, 2023
  32. RESEND [PATCH v10 7/8] worktree add: extend DWIM to infer --orphanTeng Long, Aug 9, 2023
  33. Jacob AbelAug 11, 2023
  34. 8/8 worktree add: emit warn when there is a bad HEADJacob Abel, May 17, 2023

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.