See second part (since Git 2.23, Q3 2019): git switch -c newBranch oldBranch
With Git 2.15 (Q4 2017), "git branch
" learned "-c/-C
" to create a new branch by copying an existing one.
See commit c8b2cec (18 Jun 2017) by Ævar Arnfjörð Bjarmason (avar
).
See commit 52d59cc, commit 5463caa (18 Jun 2017) by Sahil Dua (sahildua2305
).
(Merged by Junio C Hamano -- gitster
-- in commit 3b48045, 03 Oct 2017)
branch
: add a --copy
(-c
) option to go with --move
(-m
)
Add the ability to --copy
a branch and its reflog and configuration,
this uses the same underlying machinery as the --move
(-m
) option
except the reflog and configuration is copied instead of being moved.
This is useful for e.g. copying a topic branch to a new version,
e.g. work
to work-2
after submitting the work
topic to the list, while
preserving all the tracking info and other configuration that goes
with the branch, and unlike --move
keeping the other already-submitted
branch around for reference.
Note: when copying a branch, you remain on your current branch.
As Junio C Hamano explains, the initial implementation of this new feature was modifying HEAD, which was not good:
When creating a new branch B
by copying the branch A
that happens to
be the current branch, it also updates HEAD
to point at the new
branch.
It probably was made this way because "git branch -c A B
" piggybacked its implementation on "git branch -m A B
",
This does not match the usual expectation.
If I were sitting on a blue chair, and somebody comes and repaints it to red, I would accept ending up sitting on a chair that is now red (I am also OK to
stand, instead, as there no longer is my favourite blue chair).
But if somebody creates a new red chair, modelling it after the blue
chair I am sitting on, I do not expect to be booted off of the blue
chair and ending up on sitting on the new red one.
Second part: with git 2.23 (Q3 2019), no need to use git branch or the old confusing git checkout
: you have git switch
.
git switch -c newBranch oldBranch
With Git 2.40 (Q1 2023), 'git branch -c
'(man) is more robust and detects a no-op case.
See commit cfbd173 (17 Nov 2022) by Rubén Justo (rjusto
).
(Merged by Junio C Hamano -- gitster
-- in commit 963f8d3, 19 Dec 2022)
branch
: force-copy a branch to itself via @{-1} is a no-op
Signed-off-by: Rubén Justo
Signed-off-by: Taylor Blau
Since 52d59cc ("branch
: add a --copy
(-c) option to go with --move
(-m)", 2017-06-18, Git v2.15.0-rc0 -- merge listed in batch #12) we can copy a branch to make a new branch with the '-c' (copy) option or to overwrite an existing branch using the '-C' (force copy) option.
A no-op possibility is considered when we are asked to copy a branch to itself, to follow the same no-op introduced for the rename (-M) operation in 3f59481 (branch
: allow a no-op , 2011-11-25, Git v1.7.9-rc0 -- merge) (branch: allow a no-op "branch -M <current-branch>
HEAD", 2011-11-25).
To check for this, in 52d59cc we compared the branch names provided by the user, source (HEAD if omitted) and destination, and a match is considered as this no-op.
Since ae5a6c3 (checkout
: implement , 2009-01-17, Git v1.6.2-rc0 -- merge) (checkout: implement "@{-N}" shortcut name for N-th last branch, 2009-01-17) a branch can be specified using shortcuts like @{-1}.
This allows this usage:
$ git checkout -b test
$ git checkout -
$ git branch -C test test # no-op
$ git branch -C test @{-1} # oops
$ git branch -C @{-1} test # oops
As we are using the branch name provided by the user to do the comparison, if one of the branches is provided using a shortcut we are not going to have a match and a call to git_config_copy_section()
will happen.
This will make a duplicate of the configuration for that branch, and with this progression the second call will produce four copies of the configuration, and so on.
Let's use the interpreted branch name instead for this comparison.
The rename operation is not affected.