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

[PATCH v4 2/3] branch: description for orphan branch errors

From
Rubén Justo <rjusto@gmail.com>
Date
Feb 22, 2023, 22:55 UTC
Message-ID
<76bac570-147e-7c74-c18c-1da88bc3d342@gmail.com>
In-Reply-To
<139555f1-21ab-d987-a58e-c7f04ce222d3@gmail.com>

In bcfc82bd48 (branch: description for non-existent branch errors, 2022-10-08) we checked the current HEAD to detect if the branch to operate with is an orphan branch, so as to avoid the confusing error: "No branch named...".

If we are asked to operate with an orphan branch in a different working tree than the current one, we need to check the HEAD in that different working tree.

Let's extend the check we did in bcfc82bd48, to all HEADs in the repository, using the helper introduced in 31ad6b61bd (branch: add branch_checked_out() helper, 2022-06-15)

We are already traversing all worktrees in "copy_or_rename_branch()" checking if the branch to be copied or renamed is being bisected or rebased. Let's include also a check for being HEAD, and use this information within the function rather than the helper. This implies doing the worktrees iteration earlier in the function; to keep the user-visible behavior unchanged lets maintain the die("Branch foo is being rebased/bisected...") in the same position within the function.

Signed-off-by: Rubén Justo <rjusto@gmail.com>
---
 builtin/branch.c       | 53 ++++++++++++++++++++++++++++--------------
 t/t3202-show-branch.sh | 18 ++++++++++++++
 2 files changed, 53 insertions(+), 18 deletions(-)
diff --git a/builtin/branch.c b/builtin/branch.c
index a32ae64006..aecf009993 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -486,6 +486,9 @@ static void print_current_branch_name(void)
 		die(_("HEAD (%s) points outside of refs/heads/"), refname);
 }
 
+#define IS_BISECTED 1
+#define IS_REBASED 2
+#define IS_HEAD 4
 
 static void copy_or_rename_branch(const char *oldname, const char *newname, int copy, int force)
 {
@@ -493,8 +496,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 	struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
 	const char *interpreted_oldname = NULL;
 	const char *interpreted_newname = NULL;
-	int recovery = 0;
+	int recovery = 0, oldref_usage = 0;
 	struct worktree **worktrees = get_worktrees();
+	struct worktree *oldref_wt = NULL;
 
 	if (strbuf_check_branch_ref(&oldref, oldname)) {
 		/*
@@ -507,8 +511,28 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 			die(_("Invalid branch name: '%s'"), oldname);
 	}
 
-	if ((copy || strcmp(head, oldname)) && !ref_exists(oldref.buf)) {
-		if (copy && !strcmp(head, oldname))
+	for (int i = 0; worktrees[i]; i++) {
+		struct worktree *wt = worktrees[i];
+
+		if (wt->head_ref && !strcmp(oldref.buf, wt->head_ref))
+			oldref_usage |= IS_HEAD;
+
+		if (!wt->is_detached)
+			continue;
+
+		if (is_worktree_being_rebased(wt, oldref.buf)) {
+			oldref_usage |= IS_REBASED;
+			oldref_wt = wt;
+		}
+
+		if (is_worktree_being_bisected(wt, oldref.buf)) {
+			oldref_usage |= IS_BISECTED;
+			oldref_wt = wt;
+		}
+	}
+
+	if ((copy || !(oldref_usage & IS_HEAD)) && !ref_exists(oldref.buf)) {
+		if (oldref_usage & IS_HEAD)
 			die(_("No commit on branch '%s' yet."), oldname);
 		else
 			die(_("No branch named '%s'."), oldname);
@@ -523,20 +547,13 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
 	else
 		validate_new_branchname(newname, &newref, force);
 
-	for (int i = 0; worktrees[i]; i++) {
-		struct worktree *wt = worktrees[i];
+	if (oldref_usage & IS_BISECTED)
+		die(_("Branch %s is being rebased at %s"),
+		    oldref.buf, oldref_wt->path);
 
-		if (!wt->is_detached)
-			continue;
-
-		if (is_worktree_being_rebased(wt, oldref.buf))
-			die(_("Branch %s is being rebased at %s"),
-			    oldref.buf, wt->path);
-
-		if (is_worktree_being_bisected(wt, oldref.buf))
-			die(_("Branch %s is being bisected at %s"),
-			    oldref.buf, wt->path);
-	}
+	if (oldref_usage & IS_REBASED)
+		die(_("Branch %s is being bisected at %s"),
+		    oldref.buf, oldref_wt->path);
 
 	if (!skip_prefix(oldref.buf, "refs/heads/", &interpreted_oldname) ||
 	    !skip_prefix(newref.buf, "refs/heads/", &interpreted_newname)) {
@@ -818,7 +835,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
 		strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
 		if (!ref_exists(branch_ref.buf))
-			error((!argc || !strcmp(head, branch_name))
+			error((!argc || branch_checked_out(branch_ref.buf))
 			      ? _("No commit on branch '%s' yet.")
 			      : _("No branch named '%s'."),
 			      branch_name);
@@ -863,7 +880,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		}
 
 		if (!ref_exists(branch->refname)) {
-			if (!argc || !strcmp(head, branch->name))
+			if (!argc || branch_checked_out(branch->refname))
 				die(_("No commit on branch '%s' yet."), branch->name);
 			die(_("branch '%s' does not exist"), branch->name);
 		}
diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh
index ea7cfd1951..be20ebe1d5 100755
--- a/t/t3202-show-branch.sh
+++ b/t/t3202-show-branch.sh
@@ -221,4 +221,22 @@ test_expect_success 'fatal descriptions on non-existent branch' '
 	test_cmp expect actual
 '
 
+test_expect_success 'error descriptions on orphan branch' '
+	test_when_finished git worktree remove -f wt &&
+	git worktree add wt --detach &&
+	git -C wt checkout --orphan orphan-branch &&
+	test_branch_op_in_wt() {
+		test_orphan_error() {
+			test_must_fail git $* 2>actual &&
+			test_i18ngrep "No commit on branch .orphan-branch. yet.$" actual
+		} &&
+		test_orphan_error -C wt branch $1 $2 &&                # implicit branch
+		test_orphan_error -C wt branch $1 orphan-branch $2 &&  # explicit branch
+		test_orphan_error branch $1 orphan-branch $2           # different worktree
+	} &&
+	test_branch_op_in_wt --edit-description &&
+	test_branch_op_in_wt --set-upstream-to=ne &&
+	test_branch_op_in_wt -c new-branch
+'
+
 test_done
-- 
2.34.1
Previous: Rubén JustoNext: Jonathan Tan
Message 35 of 49 in “branch: operations on orphan branches”
  1. 0/2 branch: operations on orphan branchesRubén Justo, Dec 30, 2022
  2. 1/2 branch: description for orphan branch errorsRubén Justo, Dec 30, 2022
  3. Junio C HamanoJan 1, 2023
  4. Rubén JustoJan 3, 2023
  5. Junio C HamanoJan 4, 2023
  6. Rubén JustoJan 6, 2023
  7. Junio C HamanoJan 6, 2023
  8. Rubén JustoJan 7, 2023
  9. Junio C HamanoJan 7, 2023
  10. 2/2 branch: rename orphan branches in any worktreeRubén Justo, Dec 30, 2022
  11. 0/3 branch: operations on orphan branchesRubén Justo, Jan 15, 2023
  12. 1/3 avoid unnecessary worktrees traversingRubén Justo, Jan 16, 2023
  13. Junio C HamanoJan 19, 2023
  14. Rubén JustoJan 19, 2023
  15. 2/3 branch: description for orphan branch errorsRubén Justo, Jan 16, 2023
  16. 3/3 branch: rename orphan branches in any worktreeRubén Justo, Jan 16, 2023
  17. Junio C HamanoJan 19, 2023
  18. Rubén JustoJan 19, 2023
  19. 3/3 branch: rename orphan branches in any worktreeRubén Justo, Jan 16, 2023
  20. 0/3 branch: operations on orphan branchesRubén Justo, Feb 6, 2023
  21. 1/3 branch: avoid unnecessary worktrees traversalsRubén Justo, Feb 6, 2023
  22. Jonathan TanFeb 11, 2023
  23. Rubén JustoFeb 15, 2023
  24. 2/3 branch: description for orphan branch errorsRubén Justo, Feb 6, 2023
  25. 3/3 branch: rename orphan branches in any worktreeRubén Justo, Feb 6, 2023
  26. Junio C HamanoFeb 7, 2023
  27. Ævar Arnfjörð BjarmasonFeb 7, 2023
  28. Rubén JustoFeb 8, 2023
  29. Junio C HamanoFeb 8, 2023
  30. 0/3 branch: operations on orphan branchesRubén Justo, Feb 22, 2023
  31. 1/3 branch: avoid unnecessary worktrees traversalsRubén Justo, Feb 22, 2023
  32. Rubén JustoFeb 25, 2023
  33. Jonathan TanFeb 27, 2023
  34. Rubén JustoFeb 28, 2023
  35. 2/3 branch: description for orphan branch errorsRubén Justo, Feb 22, 2023
  36. Jonathan TanFeb 27, 2023
  37. Junio C HamanoFeb 27, 2023
  38. Rubén JustoFeb 28, 2023
  39. 3/3 branch: rename orphan branches in any worktreeRubén Justo, Feb 22, 2023
  40. Jonathan TanFeb 27, 2023
  41. Rubén JustoFeb 28, 2023
  42. 0/5 branch: operations on orphan branchesRubén Justo, Mar 26, 2023
  43. 1/5 branch: test for failures while renaming branchesRubén Justo, Mar 26, 2023
  44. 2/5 branch: use get_worktrees() in copy_or_rename_branch()Rubén Justo, Mar 26, 2023
  45. 3/5 branch: description for orphan branch errorsRubén Justo, Mar 26, 2023
  46. 4/5 branch: rename orphan branches in any worktreeRubén Justo, Mar 26, 2023
  47. 5/5 branch: avoid unnecessary worktrees traversalsRubén Justo, Mar 26, 2023
  48. Junio C HamanoMar 27, 2023
  49. Junio C HamanoMay 1, 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.