From: "Andrea Stacchiotti via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Andrea Stacchiotti <andreastacchiotti@gmail.com>,
Andrea Stacchiotti <andreastacchiotti@gmail.com>
Subject: [PATCH] branch: move multiple branches in a single --force
Date: Tue, 10 Jun 2025 09:07:44 +0000 [thread overview]
Message-ID: <pull.1992.git.git.1749546464346.gitgitgadget@gmail.com> (raw)
From: Andrea Stacchiotti <andreastacchiotti@gmail.com>
Using either the 1-arg or 2-args form of --force
it is possible to only move one branch at a time,
to HEAD and <arg2> respectively.
Allow moving multiple branches to a single target by giving
'git branch --force b1 b2 b3 ... dest' cp-like semantics,
all the branches are moved/created to 'dest'.
The convention extends the 2-args form in the same way
'cp a b c ... dest' would do.
There could be another potential interpretation of
`--force a b c`: moving all 3 to HEAD, but the 2-args
form already changed the semantics to cp-like instead
of appending an implicit HEAD, so this seems the least
surprising way to support multiple moves.
No such change is done to the move/copy paths,
as such paths would error out anyway by trying
to create multiple branches of the same name.
Signed-off-by: Andrea Stacchiotti <andreastacchiotti@gmail.com>
---
branch: Move multiple branches in a single --force
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1992%2F12345ieee%2Fmaster-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1992/12345ieee/master-v1
Pull-Request: https://github.com/git/git/pull/1992
Documentation/git-branch.adoc | 2 +-
builtin/branch.c | 26 ++++++++++++++------------
t/t3200-branch.sh | 7 +++++++
3 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/Documentation/git-branch.adoc b/Documentation/git-branch.adoc
index c0afddc424d..817b4a5d3f6 100644
--- a/Documentation/git-branch.adoc
+++ b/Documentation/git-branch.adoc
@@ -17,7 +17,7 @@ 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] <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>
diff --git a/builtin/branch.c b/builtin/branch.c
index c150131bd9f..8ba04568c15 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -31,7 +31,7 @@
static const char * const builtin_branch_usage[] = {
N_("git branch [<options>] [-r | -a] [--merged] [--no-merged]"),
- N_("git branch [<options>] [-f] [--recurse-submodules] <branch-name> [<start-point>]"),
+ N_("git branch [<options>] [-f] [--recurse-submodules] <branch-name>... [<start-point>]"),
N_("git branch [<options>] [-l] [<pattern>...]"),
N_("git branch [<options>] [-r] (-d | -D) <branch-name>..."),
N_("git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"),
@@ -992,9 +992,9 @@ int cmd_branch(int argc,
strbuf_addf(&buf, "branch.%s.merge", branch->name);
git_config_set_multivar(buf.buf, NULL, NULL, CONFIG_FLAGS_MULTI_REPLACE);
strbuf_release(&buf);
- } else if (!noncreate_actions && argc > 0 && argc <= 2) {
- const char *branch_name = argv[0];
- const char *start_name = argc == 2 ? argv[1] : head;
+ } else if (!noncreate_actions && argc > 0) {
+ const char *start_name = argc == 1 ? head : argv[argc - 1];
+ int iters = argc == 1 ? 1 : argc - 1;
if (filter.kind != FILTER_REFS_BRANCHES)
die(_("the -a, and -r, options to 'git branch' do not take a branch name.\n"
@@ -1003,15 +1003,17 @@ 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,
- start_name, NULL, force,
- reflog, quiet, track, 0);
- ret = 0;
- goto out;
+ for (int i = 0; i < iters; i++) {
+ const char *branch_name = argv[i];
+
+ if (recurse_submodules)
+ create_branches_recursively(the_repository, branch_name,
+ start_name, NULL, force,
+ reflog, quiet, track, 0);
+ else
+ create_branch(the_repository, branch_name, start_name, force, 0,
+ reflog, quiet, track, 0);
}
- create_branch(the_repository, branch_name, start_name, force, 0,
- reflog, quiet, track, 0);
} else
usage_with_options(builtin_branch_usage, options);
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index f3e720dc10d..7cd31ca7820 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -60,6 +60,13 @@ test_expect_success 'git branch --force abc should succeed when abc exists' '
test_cmp expect actual
'
+test_expect_success 'git branch --force br1 br2 abc should create 2 new branches' '
+ git branch --force br1 br2 abc &&
+ test_ref_exists refs/heads/br1 &&
+ test_ref_exists refs/heads/br2 &&
+ git branch -d br1 br2
+'
+
test_expect_success 'git branch a/b/c should create a branch' '
git branch a/b/c &&
test_ref_exists refs/heads/a/b/c
base-commit: 4c0e625c091d4c648cec7319bafaed3cc81658e5
--
gitgitgadget
next reply other threads:[~2025-06-10 9:07 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-10 9:07 Andrea Stacchiotti via GitGitGadget [this message]
2025-06-10 21:25 ` [PATCH] branch: move multiple branches in a single --force Junio C Hamano
2025-06-10 22:17 ` Andrea Stacchiotti
2025-06-11 0:22 ` Junio C Hamano
2025-06-11 8:34 ` Andrea Stacchiotti
2025-06-11 15:26 ` Junio C Hamano
2025-06-12 0:19 ` Andrea Stacchiotti
2025-06-12 9:55 ` Junio C Hamano
2025-06-12 15:48 ` Junio C Hamano
2025-06-12 16:51 ` Andrea Stacchiotti
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=pull.1992.git.git.1749546464346.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=andreastacchiotti@gmail.com \
--cc=git@vger.kernel.org \
/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