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

[PATCH v3][Outreachy] branch -D: allow - as abbreviation of @{-1}

From
Elena Petrashen <elena.petrashen@gmail.com>
Date
Mar 31, 2016, 09:25 UTC
Message-ID
<1459416327-795-1-git-send-email-elena.petrashen@gmail.com>
Signed-off-by: Elena Petrashen <elena.petrashen@gmail.com>
---
This micro-patch is meant to allow “-“ as a short-hand for
“@{-1} for branch -d (Cf. $gmane/230828). Based on feedback
for v2:
* suppressable advice on restoring if a user deletes a branch
via @{-x} or - reference (to ensure safety: if a user deleted
the wrong branch instead what she thought is @{-1}, which seems
to be more likely compared with the situation when branch name
has to be typed in)
* if not enough switches exist to delete branch via @{-x} or -
reference, a corresponding warning is displayed 
Thank you! Looking forward to any feedback.
 Documentation/git-branch.txt |  2 ++
 advice.c                     | 10 ++++++++++
 advice.h                     |  2 ++
 builtin/branch.c             | 22 +++++++++++++++++++---
 t/t3200-branch.sh            | 10 ++++++++++
 5 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 4a7037f..42b96ed 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -65,6 +65,8 @@ to happen.
 With a `-d` or `-D` option, `<branchname>` will be deleted.  You may
 specify more than one branch for deletion.  If the branch currently
 has a reflog then the reflog will also be deleted.
+The "@{-N}" syntax for the N-th last branch deletes the specified branch.
+You may also specify - which is synonymous with "@{-1}".
 
 Use `-r` together with `-d` to delete remote-tracking branches. Note, that it
 only makes sense to delete remote-tracking branches if they no longer exist
diff --git a/advice.c b/advice.c
index 4dc5cf1..f14eb68 100644
--- a/advice.c
+++ b/advice.c
@@ -15,6 +15,7 @@ int advice_detached_head = 1;
 int advice_set_upstream_failure = 1;
 int advice_object_name_warning = 1;
 int advice_rm_hints = 1;
+int advice_delete_branch_via_at_ref = 1;
 
 static struct {
 	const char *name;
@@ -35,6 +36,7 @@ static struct {
 	{ "setupstreamfailure", &advice_set_upstream_failure },
 	{ "objectnamewarning", &advice_object_name_warning },
 	{ "rmhints", &advice_rm_hints },
+	{ "deletebranchviaatref", &advice_delete_branch_via_at_ref },
 
 	/* make this an alias for backward compatibility */
 	{ "pushnonfastforward", &advice_push_update_rejected }
@@ -117,3 +119,11 @@ void detach_advice(const char *new_name)
 
 	fprintf(stderr, fmt, new_name);
 }
+
+void delete_branch_advice(const char *name, const char *ref)
+{
+	const char fmt[] =
+	"\nNote: to restore the deleted branch:\n\ngit branch %s %s\n";
+
+	fprintf(stderr, fmt, name, ref);
+}
diff --git a/advice.h b/advice.h
index b341a55..192eef7 100644
--- a/advice.h
+++ b/advice.h
@@ -18,6 +18,7 @@ extern int advice_detached_head;
 extern int advice_set_upstream_failure;
 extern int advice_object_name_warning;
 extern int advice_rm_hints;
+extern int advice_delete_branch_via_at_ref;
 
 int git_default_advice_config(const char *var, const char *value);
 __attribute__((format (printf, 1, 2)))
@@ -26,5 +27,6 @@ int error_resolve_conflict(const char *me);
 extern void NORETURN die_resolve_conflict(const char *me);
 void NORETURN die_conclude_merge(void);
 void detach_advice(const char *new_name);
+void delete_branch_advice(const char *name, const char *ref);
 
 #endif /* ADVICE_H */
diff --git a/builtin/branch.c b/builtin/branch.c
index 7b45b6b..4f5ec72 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -178,6 +178,12 @@ static void delete_branch_config(const char *branchname)
 	strbuf_release(&buf);
 }
 
+static void expand_dash_shortcut(const char **argv, int dash_position)
+{
+	if (!strcmp(argv[dash_position], "-"))
+		argv[dash_position] = "@{-1}";
+}
+
 static int delete_branches(int argc, const char **argv, int force, int kinds,
 			   int quiet)
 {
@@ -187,6 +193,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 	const char *fmt;
 	int i;
 	int ret = 0;
+	int at_shortcut = 0;
 	int remote_branch = 0;
 	struct strbuf bname = STRBUF_INIT;
 
@@ -214,6 +221,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 		const char *target;
 		int flags = 0;
 
+		expand_dash_shortcut (argv, i);
+		if(!strncmp(argv[i], "@{-", strlen("@{-")))
+			at_shortcut = 1;
 		strbuf_branchname(&bname, argv[i]);
 		if (kinds == FILTER_REFS_BRANCHES && !strcmp(head, bname.buf)) {
 			error(_("Cannot delete the branch '%s' "
@@ -231,9 +241,12 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 					    | RESOLVE_REF_ALLOW_BAD_NAME,
 					    sha1, &flags);
 		if (!target) {
-			error(remote_branch
-			      ? _("remote-tracking branch '%s' not found.")
-			      : _("branch '%s' not found."), bname.buf);
+			error((!strncmp(bname.buf, "@{-", strlen("@{-")))
+				? _("There is not enough branch switches to"
+					" delete '%s'.")
+				: remote_branch
+					? _("remote-tracking branch '%s' not found.")
+					: _("branch '%s' not found."), bname.buf);
 			ret = 1;
 			continue;
 		}
@@ -262,6 +275,9 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 			       (flags & REF_ISBROKEN) ? "broken"
 			       : (flags & REF_ISSYMREF) ? target
 			       : find_unique_abbrev(sha1, DEFAULT_ABBREV));
+			if (at_shortcut && advice_delete_branch_via_at_ref)
+			       delete_branch_advice (bname.buf,
+				find_unique_abbrev(sha1, DEFAULT_ABBREV));
 		}
 		delete_branch_config(bname.buf);
 	}
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index a897248..0b59c94 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -372,6 +372,16 @@ test_expect_success 'test overriding tracking setup via --no-track' '
 	! test "$(git config branch.my2.merge)" = refs/heads/master
 '
 
+test_expect_success 'test deleting "-" deletes previous branch' '
+	git checkout -b prev &&
+	test_commit prev &&
+	git checkout master &&
+	git branch -D - >actual &&
+	sha1=$(git rev-parse prev | cut -c 1-7) &&
+	echo "Deleted branch prev (was $sha1)." >expect &&
+	test_cmp expect actual
+'
+
 test_expect_success 'no tracking without .fetch entries' '
 	git config branch.autosetupmerge true &&
 	git branch my6 s &&
-- 
2.8.0.dirty
Next: Matthieu Moy
Message 1 of 9 in “[Outreachy] branch -D: allow - as abbreviation of @{-1}”
  1. [Outreachy] branch -D: allow - as abbreviation of @{-1}Elena Petrashen, Mar 31, 2016
  2. Matthieu MoyMar 31, 2016
  3. Remi Galan AlfonsoMar 31, 2016
  4. elena petrashenApr 4, 2016
  5. Remi Galan AlfonsoApr 4, 2016
  6. elena petrashenApr 6, 2016
  7. Remi Galan AlfonsoApr 6, 2016
  8. Junio C HamanoMar 31, 2016
  9. elena petrashenApr 6, 2016

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.