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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.