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

[PATCH v6] branch: support for shortcuts like @{-1}, completed

From
Rubén Justo <rjusto@gmail.com>
Date
Oct 10, 2022, 23:24 UTC
Message-ID
<fbf84e26-4306-c8df-0e2c-45dc94129e3a@gmail.com>
In-Reply-To
<de200fa0-379d-c1ce-8446-9e4292d0b66a@gmail.com>

branch command with options "edit-description", "set-upstream-to" and "unset-upstream" expects a branch name. Since ae5a6c3684 (checkout: implement "@{-N}" shortcut name for N-th last branch, 2009-01-17) a branch can be specified using shortcuts like @{-1}. Those shortcuts need to be resolved when considering the arguments.

We can modify the description of the previously checked out branch with:
$ git branch --edit--description @{-1}
We can modify the upstream of the previously checked out branch with:

$ git branch --set-upstream-to upstream @{-1} $ git branch --unset-upstream @{-1}

Signed-off-by: Rubén Justo <rjusto@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

This is the v5 with your fix squashed, but with one change to maintain the -1 on error.

    -			error(!argc
    +			ret = error(!argc
    			      ? _("No commit on branch '%s' yet.")
    			      : _("No branch named '%s'."),
    			      branch_name);

We discussed to keep this and other things like the capitalized error messages, to be sorted out in next series, when the dust settles after this and the other patch about errors on unborn branches.

ref: <xmqqlepp8smc.fsf@gitster.g> <xmqqmtajosek.fsf@gitster.g>

Range-diff:
1:  00ca255874 ! 1:  11650c6340 branch: support for shortcuts like @{-1}, completed
    @@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix
      		const char *branch_name;
      		struct strbuf branch_ref = STRBUF_INIT;
     +		struct strbuf buf = STRBUF_INIT;
    ++		int ret = 1; /* assume failure */
      
      		if (!argc) {
      			if (filter.detached)
    @@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix
      			branch_name = head;
     -		} else if (argc == 1)
     -			branch_name = argv[0];
    +-		else
     +		} else if (argc == 1) {
     +			strbuf_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL);
     +			branch_name = buf.buf;
    -+		}
    - 		else
    ++		} else {
      			die(_("cannot edit description of more than one branch"));
    ++		}
      
      		strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
    - 		if (!ref_exists(branch_ref.buf)) {
    - 			strbuf_release(&branch_ref);
    -+			strbuf_release(&buf);
    - 
    - 			if (!argc)
    - 				return error(_("No commit on branch '%s' yet."),
    -@@ builtin/branch.c: int cmd_branch(int argc, const char **argv, const char *prefix)
    - 		}
    +-		if (!ref_exists(branch_ref.buf)) {
    +-			strbuf_release(&branch_ref);
    +-
    +-			if (!argc)
    +-				return error(_("No commit on branch '%s' yet."),
    +-					     branch_name);
    +-			else
    +-				return error(_("No branch named '%s'."),
    +-					     branch_name);
    +-		}
    ++		if (!ref_exists(branch_ref.buf))
    ++			ret = error(!argc
    ++			      ? _("No commit on branch '%s' yet.")
    ++			      : _("No branch named '%s'."),
    ++			      branch_name);
    ++		else if (!edit_branch_description(branch_name))
    ++			ret = 0; /* happy */
    ++
      		strbuf_release(&branch_ref);
    ++		strbuf_release(&buf);
      
     -		if (edit_branch_description(branch_name))
    -+		if (edit_branch_description(branch_name)) {
    -+			strbuf_release(&buf);
    - 			return 1;
    -+		}
    -+		strbuf_release(&buf);
    +-			return 1;
    ++		return ret;
      	} else if (copy) {
      		if (!argc)
      			die(_("branch name required"));
 builtin/branch.c                      | 53 +++++++++++++++++----------
 t/t3204-branch-name-interpretation.sh | 24 ++++++++++++
 2 files changed, 58 insertions(+), 19 deletions(-)
diff --git a/builtin/branch.c b/builtin/branch.c
index 55cd9a6e99..658c9f8741 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -791,31 +791,33 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 	} else if (edit_description) {
 		const char *branch_name;
 		struct strbuf branch_ref = STRBUF_INIT;
+		struct strbuf buf = STRBUF_INIT;
+		int ret = 1; /* assume failure */
 
 		if (!argc) {
 			if (filter.detached)
 				die(_("Cannot give description to detached HEAD"));
 			branch_name = head;
-		} else if (argc == 1)
-			branch_name = argv[0];
-		else
+		} else if (argc == 1) {
+			strbuf_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL);
+			branch_name = buf.buf;
+		} else {
 			die(_("cannot edit description of more than one branch"));
+		}
 
 		strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
-		if (!ref_exists(branch_ref.buf)) {
-			strbuf_release(&branch_ref);
-
-			if (!argc)
-				return error(_("No commit on branch '%s' yet."),
-					     branch_name);
-			else
-				return error(_("No branch named '%s'."),
-					     branch_name);
-		}
+		if (!ref_exists(branch_ref.buf))
+			ret = error(!argc
+			      ? _("No commit on branch '%s' yet.")
+			      : _("No branch named '%s'."),
+			      branch_name);
+		else if (!edit_branch_description(branch_name))
+			ret = 0; /* happy */
+
 		strbuf_release(&branch_ref);
+		strbuf_release(&buf);
 
-		if (edit_branch_description(branch_name))
-			return 1;
+		return ret;
 	} else if (copy) {
 		if (!argc)
 			die(_("branch name required"));
@@ -835,9 +837,15 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		else
 			die(_("too many arguments for a rename operation"));
 	} else if (new_upstream) {
-		struct branch *branch = branch_get(argv[0]);
+		struct branch *branch;
+		struct strbuf buf = STRBUF_INIT;
 
-		if (argc > 1)
+		if (!argc)
+			branch = branch_get(NULL);
+		else if (argc == 1) {
+			strbuf_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL);
+			branch = branch_get(buf.buf);
+		} else
 			die(_("too many arguments to set new upstream"));
 
 		if (!branch) {
@@ -854,11 +862,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		dwim_and_setup_tracking(the_repository, branch->name,
 					new_upstream, BRANCH_TRACK_OVERRIDE,
 					quiet);
+		strbuf_release(&buf);
 	} else if (unset_upstream) {
-		struct branch *branch = branch_get(argv[0]);
+		struct branch *branch;
 		struct strbuf buf = STRBUF_INIT;
 
-		if (argc > 1)
+		if (!argc)
+			branch = branch_get(NULL);
+		else if (argc == 1) {
+			strbuf_branchname(&buf, argv[0], INTERPRET_BRANCH_LOCAL);
+			branch = branch_get(buf.buf);
+		} else
 			die(_("too many arguments to unset upstream"));
 
 		if (!branch) {
@@ -871,6 +885,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 		if (!branch_has_merge_config(branch))
 			die(_("Branch '%s' has no upstream information"), branch->name);
 
+		strbuf_reset(&buf);
 		strbuf_addf(&buf, "branch.%s.remote", branch->name);
 		git_config_set_multivar(buf.buf, NULL, NULL, CONFIG_FLAGS_MULTI_REPLACE);
 		strbuf_reset(&buf);
diff --git a/t/t3204-branch-name-interpretation.sh b/t/t3204-branch-name-interpretation.sh
index 993a6b5eff..793bf4d269 100755
--- a/t/t3204-branch-name-interpretation.sh
+++ b/t/t3204-branch-name-interpretation.sh
@@ -133,4 +133,28 @@ test_expect_success 'checkout does not treat remote @{upstream} as a branch' '
 	expect_branch HEAD one
 '
 
+test_expect_success 'edit-description via @{-1}' '
+	git checkout -b desc-branch &&
+	git checkout -b non-desc-branch &&
+	write_script editor <<-\EOF &&
+		echo "Branch description" >"$1"
+	EOF
+	EDITOR=./editor git branch --edit-description @{-1} &&
+	test_must_fail git config branch.non-desc-branch.description &&
+	git config branch.desc-branch.description >actual &&
+	printf "Branch description\n\n" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'modify branch upstream via "@{-1}" and "@{-1}@{upstream}"' '
+	git checkout -b upstream-branch &&
+	git checkout -b upstream-other -t upstream-branch &&
+	git branch --set-upstream-to upstream-other @{-1} &&
+	git config branch.upstream-branch.merge >actual &&
+	echo "refs/heads/upstream-other" >expect &&
+	test_cmp expect actual &&
+	git branch --unset-upstream @{-1}@{upstream} &&
+	test_must_fail git config branch.upstream-other.merge
+'
+
 test_done
-- 
2.36.1
Previous: Rubén Justo
Message 38 of 38 in “branch: support for at-refs like @{-1} in --edit-description, --set-upstream-to and --unset-upstream”
  1. 0/2 branch: support for at-refs like @{-1} in --edit-description, --set-upstream-to and --unset-upstreamRubén Justo via GitGitGadget, Sep 5, 2022
  2. 2/2 branch: support for at-refs like @{-1}Rubén Justo via GitGitGadget, Sep 5, 2022
  3. 1/2 branch: refactor edit_description command switch caseRubén Justo via GitGitGadget, Sep 5, 2022
  4. 0/2 branch: support for shortcuts like @{-1}, completedRubén Justo, Sep 7, 2022
  5. 1/2 branch: refactor "edit_description" code pathRubén Justo, Sep 7, 2022
  6. Junio C HamanoSep 7, 2022
  7. Rubén JustoSep 7, 2022
  8. Rubén JustoSep 8, 2022
  9. 2/2 branch: support for shortcuts like @{-1} completedRubén Justo, Sep 7, 2022
  10. 0/2 branch: support for shortcuts like @{-1}, completedRubén Justo, Sep 8, 2022
  11. 1/2 branch: refactor "edit_description" code pathRubén Justo, Sep 8, 2022
  12. branch: error codes for "edit_description"Rubén Justo, Sep 8, 2022
  13. Junio C HamanoSep 8, 2022
  14. 2/2 branch: support for shortcuts like @{-1} completedRubén Justo, Sep 8, 2022
  15. branch: support for shortcuts like @{-1}, completedRubén Justo, Oct 8, 2022
  16. Eric SunshineOct 8, 2022
  17. Junio C HamanoOct 8, 2022
  18. Rubén JustoOct 8, 2022
  19. Eric SunshineOct 8, 2022
  20. Rubén JustoOct 8, 2022
  21. Eric SunshineOct 8, 2022
  22. Junio C HamanoOct 8, 2022
  23. Rubén JustoOct 8, 2022
  24. Rubén JustoOct 8, 2022
  25. Eric SunshineOct 9, 2022
  26. Junio C HamanoOct 9, 2022
  27. Rubén JustoOct 9, 2022
  28. Junio C HamanoOct 8, 2022
  29. Rubén JustoOct 8, 2022
  30. branch: support for shortcuts like @{-1}, completedRubén Justo, Oct 8, 2022
  31. Junio C HamanoOct 9, 2022
  32. Junio C HamanoOct 9, 2022
  33. Rubén JustoOct 9, 2022
  34. Junio C HamanoOct 10, 2022
  35. Rubén JustoOct 10, 2022
  36. Junio C HamanoOct 10, 2022
  37. Rubén JustoOct 10, 2022
  38. branch: support for shortcuts like @{-1}, completedRubén Justo, Oct 10, 2022

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.