* [PATCH] branch: move multiple branches in a single --force
@ 2025-06-10 9:07 Andrea Stacchiotti via GitGitGadget
2025-06-10 21:25 ` Junio C Hamano
0 siblings, 1 reply; 10+ messages in thread
From: Andrea Stacchiotti via GitGitGadget @ 2025-06-10 9:07 UTC (permalink / raw)
To: git; +Cc: Andrea Stacchiotti, Andrea Stacchiotti
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-10 9:07 [PATCH] branch: move multiple branches in a single --force Andrea Stacchiotti via GitGitGadget
@ 2025-06-10 21:25 ` Junio C Hamano
2025-06-10 22:17 ` Andrea Stacchiotti
0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2025-06-10 21:25 UTC (permalink / raw)
To: Andrea Stacchiotti via GitGitGadget; +Cc: git, Andrea Stacchiotti
"Andrea Stacchiotti via GitGitGadget" <gitgitgadget@gmail.com>
writes:
> 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.
If you are renaming (or "moving") a branch that is not checked out
anywhere to a new name that is not in use, you do not even need to
force. You can just do:
git branch -m old new
You are not moving branches without "-m".
What you are doing is to point a branch A to point at a commit X
with
git branch A X
Your proposed log message talks about "--force" too much; if you are
creating a branch, you need "--force" only when the name you want to
use is already taken. Pointing the branch tip to a commit is not
inherently tied to "--force", but your description gives a false
impression that you are adding a special feature when "--force" is
used. The proposed log message needs rewritten.
If there is not yet a branch A, you do not even need "--force" on
this command line. Also take a special note that "X" does not have
to be a branch name. It only has to resolve to a commit, so this is
also valid:
git branch [--force] A X~4
I can understand that it may appear to be handy to be able to set
multiple branches at the same time with
git branch A X~4 B X~3 C X~2 (* does not exist *)
with or without "--force". If none of A, B, or C exist, they can be
created from these three comits X~4, X~3, and X~2.
Or you could propose a different syntax to create branches pointing
at the same commit
git branch A B C origin/master (* does not exist *)
But either syntax to create multiple branches feel somewhat
inadequate. What should happen to their associated configuration
data like branch.A.remote and branch.B.merge? Should they all point
at the same remote & a branch at the remote? How would that make
having multiple of them useful?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-10 21:25 ` Junio C Hamano
@ 2025-06-10 22:17 ` Andrea Stacchiotti
2025-06-11 0:22 ` Junio C Hamano
0 siblings, 1 reply; 10+ messages in thread
From: Andrea Stacchiotti @ 2025-06-10 22:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Andrea Stacchiotti via GitGitGadget, git
Thank you for your review, the concerns are fair, I'll reply point-to-point.
The general issue is that AFAIK the only way git has to say:
"point non-checked-out branch B to commit-ish X, leave B's config intact,
if B doesn't exist create it" is `git branch --force B X`.
This is likely an abuse of `branch -f`, it might be better giving it
another flag
altogether, like `-p/--point-to`.
`branch --force` is massively overloaded and most of its functionality is
tied to `--move` or `--copy`, so changing branch names, not repointing branches.
This patch aims to make repointing multiple branches to the same commit-ish
easier, currently it needs a shell loop.
I'd like this functionality for gitops repos, where each branch is an env
and I want to update dozens of envs to the last config state.
Il giorno mar 10 giu 2025 alle ore 23:25 Junio C Hamano
<gitster@pobox.com> ha scritto:
>
> "Andrea Stacchiotti via GitGitGadget" <gitgitgadget@gmail.com>
> writes:
>
> > 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.
>
> If you are renaming (or "moving") a branch that is not checked out
> anywhere to a new name that is not in use, you do not even need to
> force. You can just do:
>
> git branch -m old new
>
> You are not moving branches without "-m".
>
> What you are doing is to point a branch A to point at a commit X
> with
>
> git branch A X
Indeed, this is about repointing, not changing branch names.
> Your proposed log message talks about "--force" too much; if you are
> creating a branch, you need "--force" only when the name you want to
> use is already taken. Pointing the branch tip to a commit is not
> inherently tied to "--force", but your description gives a false
> impression that you are adding a special feature when "--force" is
> used. The proposed log message needs rewritten.
Right, it's that I'm using "force create branch A onto X, delete A if
it existed"
as "repoint branch A to X, create it if needed", I likely have a skewed
view on it.
This usecase might be better served by a new flag.
> If there is not yet a branch A, you do not even need "--force" on
> this command line. Also take a special note that "X" does not have
> to be a branch name. It only has to resolve to a commit, so this is
> also valid:
>
> git branch [--force] A X~4
Yeah, it was not clear from my message, nothing about the
change is about renaming a branch, my usecase is about
repointing to a generic commit-ish, like you say.
> I can understand that it may appear to be handy to be able to set
> multiple branches at the same time with
>
> git branch A X~4 B X~3 C X~2 (* does not exist *)
>
> with or without "--force". If none of A, B, or C exist, they can be
> created from these three commits X~4, X~3, and X~2.
I'm not opposed to implement this if it's preferred, but I liked
the cp-like syntax as it's less repeating and the average shell user
is already exposed to it via cp or mv.
> Or you could propose a different syntax to create branches pointing
> at the same commit
>
> git branch A B C origin/master (* does not exist *)
>
> But either syntax to create multiple branches feel somewhat
> inadequate. What should happen to their associated configuration
> data like branch.A.remote and branch.B.merge? Should they all point
> at the same remote & a branch at the remote? How would that make
> having multiple of them useful?
>
This is closer to the intended syntax and use of the feature, I'm more
focused on branch repoints but I'd also use this when I create, say,
the staging and prod env of client newclient via
`git branch [-f] newclient-prod newclient-stag <commit-ish>`
The branches are useful because they are then supposed to evolve
independently and track the real world state of the two envs.
If <commit-ish> is a remote branch the implementation sets up
tracking, but this is really not the intended usecase, once
the branches are created their remote tracking
is set at push time to <default remote>/<branch name> as per
default push config.
Thanks for your review, I hope my intent is clearer.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-10 22:17 ` Andrea Stacchiotti
@ 2025-06-11 0:22 ` Junio C Hamano
2025-06-11 8:34 ` Andrea Stacchiotti
0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2025-06-11 0:22 UTC (permalink / raw)
To: Andrea Stacchiotti; +Cc: Andrea Stacchiotti via GitGitGadget, git
Andrea Stacchiotti <andreastacchiotti@gmail.com> writes:
> This patch aims to make repointing multiple branches to the same commit-ish
> easier, currently it needs a shell loop.
Or "update-ref --stdin"?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-11 0:22 ` Junio C Hamano
@ 2025-06-11 8:34 ` Andrea Stacchiotti
2025-06-11 15:26 ` Junio C Hamano
0 siblings, 1 reply; 10+ messages in thread
From: Andrea Stacchiotti @ 2025-06-11 8:34 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Andrea Stacchiotti via GitGitGadget, git
Il giorno mer 11 giu 2025 alle ore 02:22 Junio C Hamano
<gitster@pobox.com> ha scritto:
>
> Andrea Stacchiotti <andreastacchiotti@gmail.com> writes:
>
> > This patch aims to make repointing multiple branches to the same commit-ish
> > easier, currently it needs a shell loop.
>
> Or "update-ref --stdin"?
I learned something new, but I'd still like to keep advocating for a syntax
like `branch --some-flag A B C X` instead of feeding by hand
update-ref commands.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-11 8:34 ` Andrea Stacchiotti
@ 2025-06-11 15:26 ` Junio C Hamano
2025-06-12 0:19 ` Andrea Stacchiotti
0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2025-06-11 15:26 UTC (permalink / raw)
To: Andrea Stacchiotti; +Cc: Andrea Stacchiotti via GitGitGadget, git
Andrea Stacchiotti <andreastacchiotti@gmail.com> writes:
> Il giorno mer 11 giu 2025 alle ore 02:22 Junio C Hamano
> <gitster@pobox.com> ha scritto:
>>
>> Andrea Stacchiotti <andreastacchiotti@gmail.com> writes:
>>
>> > This patch aims to make repointing multiple branches to the same commit-ish
>> > easier, currently it needs a shell loop.
>>
>> Or "update-ref --stdin"?
>
> I learned something new, but I'd still like to keep advocating for a syntax
> like `branch --some-flag A B C X` instead of feeding by hand
> update-ref commands.
I am personally not interested in such a mode, I do not know why you
think "--some-flag" is needed when the command can figure out from
the number of things on the command line being more than 2 just
fine.
But my comment was targetted against "it needs a shell loop" in the
justification in the proposed log message, which is not quite
correct.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-11 15:26 ` Junio C Hamano
@ 2025-06-12 0:19 ` Andrea Stacchiotti
2025-06-12 9:55 ` Junio C Hamano
0 siblings, 1 reply; 10+ messages in thread
From: Andrea Stacchiotti @ 2025-06-12 0:19 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Andrea Stacchiotti via GitGitGadget, git
So, if I may ask, is the proposed patch as written (branch -f A B C X)
acceptable and you just need me to rewrite the commit message
or are you not interested in it at all?
Il giorno mer 11 giu 2025 alle ore 17:26 Junio C Hamano
<gitster@pobox.com> ha scritto:
>
> Andrea Stacchiotti <andreastacchiotti@gmail.com> writes:
>
> > Il giorno mer 11 giu 2025 alle ore 02:22 Junio C Hamano
> > <gitster@pobox.com> ha scritto:
> >>
> >> Andrea Stacchiotti <andreastacchiotti@gmail.com> writes:
> >>
> >> > This patch aims to make repointing multiple branches to the same commit-ish
> >> > easier, currently it needs a shell loop.
> >>
> >> Or "update-ref --stdin"?
> >
> > I learned something new, but I'd still like to keep advocating for a syntax
> > like `branch --some-flag A B C X` instead of feeding by hand
> > update-ref commands.
>
> I am personally not interested in such a mode, I do not know why you
> think "--some-flag" is needed when the command can figure out from
> the number of things on the command line being more than 2 just
> fine.
>
> But my comment was targetted against "it needs a shell loop" in the
> justification in the proposed log message, which is not quite
> correct.
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-12 0:19 ` Andrea Stacchiotti
@ 2025-06-12 9:55 ` Junio C Hamano
2025-06-12 15:48 ` Junio C Hamano
0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2025-06-12 9:55 UTC (permalink / raw)
To: Andrea Stacchiotti; +Cc: Andrea Stacchiotti via GitGitGadget, git
Andrea Stacchiotti <andreastacchiotti@gmail.com> writes:
> So, if I may ask, is the proposed patch as written (branch -f A B C X)
> acceptable and you just need me to rewrite the commit message
> or are you not interested in it at all?
As I said, I personally am not interested in such a mode, but you
may be able to interest other people in it, and with wider support
I may change my mind. But I do not think the feature should not be
tied to "--force" option at all. "git branch A B C X" should be
able to create three new branches A B C that all tracks X if none of
them exist without "--force".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-12 9:55 ` Junio C Hamano
@ 2025-06-12 15:48 ` Junio C Hamano
2025-06-12 16:51 ` Andrea Stacchiotti
0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2025-06-12 15:48 UTC (permalink / raw)
To: Andrea Stacchiotti; +Cc: Andrea Stacchiotti via GitGitGadget, git
Junio C Hamano <gitster@pobox.com> writes:
> I may change my mind. But I do not think the feature should not be
> tied to "--force" option at all.
Sorry for a double-negation failure. What I think is that the
feature should be orthogonal to "--force".
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] branch: move multiple branches in a single --force
2025-06-12 15:48 ` Junio C Hamano
@ 2025-06-12 16:51 ` Andrea Stacchiotti
0 siblings, 0 replies; 10+ messages in thread
From: Andrea Stacchiotti @ 2025-06-12 16:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Andrea Stacchiotti via GitGitGadget, git
Il giorno gio 12 giu 2025 alle ore 17:48 Junio C Hamano
<gitster@pobox.com> ha scritto:
>
> Junio C Hamano <gitster@pobox.com> writes:
>
> > I may change my mind. But I do not think the feature should not be
> > tied to "--force" option at all.
>
> Sorry for a double-negation failure. What I think is that the
> feature should be orthogonal to "--force".
No worries, I got it, it makes sense.
I can implement the revised request if I see some replies expressing interest.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-06-12 16:51 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-10 9:07 [PATCH] branch: move multiple branches in a single --force Andrea Stacchiotti via GitGitGadget
2025-06-10 21:25 ` 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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox