From: "VALERI Yoann via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Patrick Steinhardt <ps@pks.im>,
Junio C Hamano <gitster@pobox.com>,
Yoann Valeri <yoann.valeri@cea.fr>,
Eric Sunshine <sunshine@sunshineco.com>,
Yoann Valeri <yoann.valeri@cea.fr>,
VALERI Yoann <yoann.valeri@cea.fr>
Subject: [PATCH v4 1/2] branch: add '--name-prefix' option
Date: Thu, 09 Apr 2026 10:43:09 +0000 [thread overview]
Message-ID: <322f94d12173e55e03baf187a37a3870192bc1d2.1775731390.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2202.v4.git.git.1775731390.gitgitgadget@gmail.com>
From: VALERI Yoann <yoann.valeri@cea.fr>
This patch adds a '--name-prefix' option to add a prefix to a newly
created branch. It can use a regular string or a token as prefix. The
only token currently handled is '@{current}', which is substituted for
the current branch's name.
Signed-off-by: VALERI Yoann <yoann.valeri@cea.fr>
---
Documentation/git-branch.adoc | 11 ++++++-
branch.c | 57 +++++++++++++++++++++++++++++++++++
branch.h | 12 ++++++++
builtin/branch.c | 24 ++++++++++-----
t/t3200-branch.sh | 24 +++++++++++++++
5 files changed, 120 insertions(+), 8 deletions(-)
diff --git a/Documentation/git-branch.adoc b/Documentation/git-branch.adoc
index c0afddc424..631b912119 100644
--- a/Documentation/git-branch.adoc
+++ b/Documentation/git-branch.adoc
@@ -17,7 +17,8 @@ git branch [--color[=<when>] | --no-color] [--show-current]
[(-r|--remotes) | (-a|--all)]
[--list] [<pattern>...]
git branch [--track[=(direct|inherit)] | --no-track] [-f]
- [--recurse-submodules] <branch-name> [<start-point>]
+ [--recurse-submodules] [--name-prefix=<token>]
+ <branch-name> [<start-point>]
git branch (--set-upstream-to=<upstream>|-u <upstream>) [<branch-name>]
git branch --unset-upstream [<branch-name>]
git branch (-m|-M) [<old-branch>] <new-branch>
@@ -64,6 +65,10 @@ Note that this will create the new branch, but it will not switch the
working tree to it; use `git switch <new-branch>` to switch to the
new branch.
+With a `--name-prefix` option, you can add a prefix to the branch to create.
+This can either be a simple name, or a token. Currently, only '@{current}' is
+supported as token, and will use the current branch name as prefix.
+
When a local branch is started off a remote-tracking branch, Git sets up the
branch (specifically the `branch.<name>.remote` and `branch.<name>.merge`
configuration entries) so that `git pull` will appropriately merge from
@@ -319,6 +324,10 @@ superproject's "origin/main", but tracks the submodule's "origin/main".
and the object it points at. _<format>_ is the same as
that of linkgit:git-for-each-ref[1].
+`--name-prefix <token>`::
+ A string that will be used as prefix to the name of the new branch to
+ create. Can be '@{current}' to use the current branch's name.
+
_<branch-name>_::
The name of the branch to create or delete.
The new branch name must pass all checks defined by
diff --git a/branch.c b/branch.c
index 243db7d0fc..42e7c799ad 100644
--- a/branch.c
+++ b/branch.c
@@ -365,6 +365,63 @@ int read_branch_desc(struct strbuf *buf, const char *branch_name)
return 0;
}
+static char *get_current_branch_name(void)
+{
+ const char *const prefix = "refs/heads/";
+ struct object_id rev;
+ const char *p;
+ char *output;
+ char *path;
+ int flag;
+
+ path = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, &rev, &flag);
+ if (!path) {
+ warning(_("Failed to get the current branch's path"));
+ return NULL;
+ } else if (!(flag & REF_ISSYMREF)) {
+ FREE_AND_NULL(path);
+ warning(_("Failed to get the current branch's name"));
+ return NULL;
+ }
+
+ if (skip_prefix(path, prefix, &p)) {
+ output = xstrdup(p);
+ free(path);
+ return output;
+ }
+
+ warning(_("Failed to get the current branch's name"));
+ return NULL;
+}
+
+int add_branch_prefix(const char *name_prefix, struct strbuf *buf)
+{
+ if (!name_prefix)
+ return 0;
+
+ if (name_prefix[0] != '@') {
+ strbuf_addstr(buf, name_prefix);
+ return 0;
+ }
+
+ if (strcmp(name_prefix, "@{current}") == 0) {
+ char *current_branch_name = get_current_branch_name();
+
+ if (!current_branch_name)
+ return 1;
+
+ strbuf_addstr(buf, current_branch_name);
+ free(current_branch_name);
+ } else {
+ advise(_("Token '%s' unrecognized, only '@{current}' is managed currently"),
+ name_prefix);
+ return 1;
+ }
+
+ return 0;
+}
+
/*
* Check if 'name' can be a valid name for a branch; die otherwise.
* Return 1 if the named branch already exists; return 0 otherwise.
diff --git a/branch.h b/branch.h
index 3dc6e2a0ff..97371444ff 100644
--- a/branch.h
+++ b/branch.h
@@ -146,6 +146,18 @@ int install_branch_config(int flag, const char *local, const char *origin, const
*/
int read_branch_desc(struct strbuf *, const char *branch_name);
+/*
+ * Store in 'buf' a prefix to the name of a branch to create by using the given
+ * string 'name_prefix'. It can either be a simple string to a shorthand
+ * starting with '@'.
+ *
+ * Currently, only '@{current}' is managed, and will retrieve the current branch
+ * to use as prefix.
+ *
+ * Return 1 if the function failed to set the branch prefix, 0 otherwise.
+ */
+int add_branch_prefix(const char *name_prefix, struct strbuf *buf);
+
/*
* Check if a branch is checked out in the main worktree or any linked
* worktree and die (with a message describing its checkout location) if
diff --git a/builtin/branch.c b/builtin/branch.c
index 1572a4f9ef..cf7d095f22 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -725,6 +725,7 @@ int cmd_branch(int argc,
struct string_list sorting_options = STRING_LIST_INIT_DUP;
struct ref_format format = REF_FORMAT_INIT;
struct repo_config_values *cfg = repo_config_values(the_repository);
+ char *name_prefix = NULL;
int ret;
struct option options[] = {
@@ -777,6 +778,7 @@ int cmd_branch(int argc,
OPT_BOOL('i', "ignore-case", &icase, N_("sorting and filtering are case insensitive")),
OPT_BOOL(0, "recurse-submodules", &recurse_submodules_explicit, N_("recurse through submodules")),
OPT_STRING( 0 , "format", &format.format, N_("format"), N_("format to use for the output")),
+ OPT_STRING(0, "name-prefix", &name_prefix, N_("name"), N_("prefix for the branch to create")),
OPT_END(),
};
@@ -996,6 +998,8 @@ int cmd_branch(int argc,
} else if (!noncreate_actions && argc > 0 && argc <= 2) {
const char *branch_name = argv[0];
const char *start_name = argc == 2 ? argv[1] : head;
+ struct strbuf new_branch_name = STRBUF_INIT;
+ int rc;
if (filter.kind != FILTER_REFS_BRANCHES)
die(_("the -a, and -r, options to 'git branch' do not take a branch name.\n"
@@ -1004,15 +1008,21 @@ int cmd_branch(int argc,
if (track == BRANCH_TRACK_OVERRIDE)
die(_("the '--set-upstream' option is no longer supported. Please use '--track' or '--set-upstream-to' instead"));
- if (recurse_submodules) {
- create_branches_recursively(the_repository, branch_name,
+ rc = add_branch_prefix(name_prefix, &new_branch_name);
+ if (rc)
+ die(_("Failed to add a branch prefix to '%s'"), branch_name);
+
+ strbuf_addstr(&new_branch_name, branch_name);
+
+ if (recurse_submodules)
+ create_branches_recursively(the_repository, new_branch_name.buf,
start_name, NULL, force,
reflog, quiet, track, 0);
- ret = 0;
- goto out;
- }
- create_branch(the_repository, branch_name, start_name, force, 0,
- reflog, quiet, track, 0);
+ else
+ create_branch(the_repository, new_branch_name.buf, start_name,
+ force, 0, reflog, quiet, track, 0);
+
+ strbuf_release(&new_branch_name);
} else
usage_with_options(builtin_branch_usage, options);
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index e7829c2c4b..f81d4380a9 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -1717,4 +1717,28 @@ test_expect_success 'errors if given a bad branch name' '
test_cmp expect actual
'
+test_expect_success 'create branch with --name-prefix' '
+ test_config branch.autosetupmerge false &&
+ git branch branch-with-prefix &&
+ test_ref_exists refs/heads/branch-with-prefix &&
+ git branch --name-prefix "blob" -- -with-prefix &&
+ test_ref_exists refs/heads/blob-with-prefix &&
+ test_must_fail git branch --name-prefix "blob" -- -with-prefix &&
+ git branch --name-prefix "@{current}" -- -with-prefix &&
+ test_ref_exists refs/heads/main-with-prefix &&
+ git switch blob-with-prefix &&
+ git branch --name-prefix "@{current}" -- -with-prefix &&
+ test_ref_exists refs/heads/blob-with-prefix-with-prefix &&
+ test_must_fail git branch --name-prefix "@{current}" -- -with-prefix &&
+ git branch --name-prefix "blob" --no-name-prefix branch-with-no-prefix &&
+ test_ref_exists refs/heads/branch-with-no-prefix &&
+ git checkout main &&
+ test_config alias.bn "branch --name-prefix=blob" &&
+ git bn --no-name-prefix bn-with-no-prefix &&
+ test_ref_exists refs/heads/bn-with-no-prefix &&
+ git branch -D branch-with-prefix main-with-prefix blob-with-prefix &&
+ git branch -D blob-with-prefix-with-prefix branch-with-no-prefix &&
+ git branch -D bn-with-no-prefix
+'
+
test_done
--
gitgitgadget
next prev parent reply other threads:[~2026-04-09 10:43 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-20 8:07 [PATCH] branch: add 'branch.addCurrentBranchAsPrefix' config param Yoann Valeri via GitGitGadget
2026-02-20 15:59 ` Junio C Hamano
2026-02-20 16:08 ` Junio C Hamano
2026-02-27 15:48 ` [PATCH v2 0/2] " Yoann Valeri via GitGitGadget
2026-02-27 15:48 ` [PATCH v2 1/2] " VALERI Yoann via GitGitGadget
2026-02-27 15:48 ` [PATCH v2 2/2] branch: add a no-prefix option VALERI Yoann via GitGitGadget
2026-02-27 17:07 ` Junio C Hamano
2026-03-06 13:14 ` [PATCH v3 0/3] branch: add prefixes to new branch names Yoann Valeri via GitGitGadget
2026-03-06 13:14 ` [PATCH v3 1/3] branch: add '--name-prefix' option VALERI Yoann via GitGitGadget
2026-03-07 7:06 ` Eric Sunshine
2026-03-08 7:06 ` Junio C Hamano
2026-03-06 13:14 ` [PATCH v3 2/3] branch: add 'branch.namePrefix' config param VALERI Yoann via GitGitGadget
2026-03-07 7:07 ` Eric Sunshine
2026-03-06 13:14 ` [PATCH v3 3/3] branch: add '--no-name-prefix' option VALERI Yoann via GitGitGadget
2026-03-06 21:38 ` Junio C Hamano
2026-03-06 21:01 ` [PATCH v3 0/3] branch: add prefixes to new branch names Junio C Hamano
2026-03-07 7:05 ` Eric Sunshine
2026-03-08 6:48 ` Junio C Hamano
2026-04-09 10:43 ` [PATCH v4 0/2] " Yoann Valeri via GitGitGadget
2026-04-09 10:43 ` VALERI Yoann via GitGitGadget [this message]
2026-04-09 10:43 ` [PATCH v4 2/2] branch: add 'branch.namePrefix' config param VALERI Yoann via GitGitGadget
2026-04-09 19:52 ` Junio C Hamano
2026-04-09 20:02 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=322f94d12173e55e03baf187a37a3870192bc1d2.1775731390.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=ps@pks.im \
--cc=sunshine@sunshineco.com \
--cc=yoann.valeri@cea.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox