git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 4/3] branch: fix "copy" to never touch HEAD

From
Junio C Hamano <gitster@pobox.com>
Date
Sep 27, 2017, 02:02 UTC
Message-ID
<xmqqvak47val.fsf@gitster.mtv.corp.google.com>
In-Reply-To
<874lrpw34z.fsf@evledraar.booking.com>
Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:
Show 16 quoted lines
> I do think however that we also need to update the docs, the relevant
> origin/master...gitster/sd/branch-copy diff is currently:
>
>     +The `-c` and `-C` options have the exact same semantics as `-m` and
>     +`-M`, except instead of the branch being renamed it along with its
>     +config and reflog will be copied to a new name.
>
> Suggestions welcome, but I think that should probably be changed to
> something like the following as part of this patch:
>
>     The `-c` and `-C` options have the exact same semantics as `-m` and
>     `-M`, except instead of the branch being renamed it along with its
>     config and reflog will be copied to a new name. Furthermore, unlike
>     its `-m` and `-M` cousins the `-c` and `-C` options will never move
>     the HEAD, whereas the move option will do so if the source branch is
>     the currently checked-out branch.

I do not think anybody even _imagines_ copy to move HEAD, and do not think "unlike -m, it doesn't touch HEAD" a worthwhile thing to say.

It is '-m' whose behaviour may look strange wrt HEAD, so _that_ may be worth mentioning, though.

I suspect that your reaction probably comes from being too married to the idea that HEAD has a string that is the same as the refname of the current branch. But that is a mere implementation detail. Users would think that HEAD points at the current branch and does not even care how that pointing is implemented.

Conceptually, you can consider that each branch has its own identity, separate from various traits it has, like what its upstream branch is, what commit it points at, what its reflog says, and (most notably) what its name is.

Then you can think of "branch -m old new" to be (1) finding the instance of branch that currently has name 'old' and (2) updating only one of its trait, namely, its name, without changing anything else. Creating a new instance of a branch by copying an existing one, on the other hand, would then be the matter of (1) finding the instance of branch with name 'old' and (2) creating another instance of branch with the same traits as the original, modulo its name is set to 'new'.

A necessary wrinkle for "branch -m" that falls out of the above world model is that HEAD needs to be adjusted in order to keep pointing at the same (renamed) instance of branch that now has an updated name, if HEAD happened to be pointing at the instance of the branch whose name trait has been updated.

So, from that point of view, I'd prefer to do something like the attached patch instead. I notice that "branch -m" does not mention configuration variables carried over to the new branch, but I do not necessarily think we want to exhaustively enumerate what traits are carried over here, so perhaps it is OK as is.

 Documentation/git-branch.txt | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index fe029ac6fc..d425e3acd4 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -63,11 +63,13 @@ With a `-m` or `-M` option, <oldbranch> will be renamed to <newbranch>.
 If <oldbranch> had a corresponding reflog, it is renamed to match
 <newbranch>, and a reflog entry is created to remember the branch
 renaming. If <newbranch> exists, -M must be used to force the rename
-to happen.
+to happen.  If you rename a branch that is currently checked out,
+`HEAD` is adjusted so that the branch (whose name is now
+<newbranch>) stays to be the current branch.
 
-The `-c` and `-C` options have the exact same semantics as `-m` and
-`-M`, except instead of the branch being renamed it along with its
-config and reflog will be copied to a new name.
+With a `-c` or`-C` option, a new branch <newbranch> is created by
+copying the traits like the reflog contents and `branch.*.*`
+configuration from an existing <oldbranch>.
 
 With a `-d` or `-D` option, `<branchname>` will be deleted.  You may
 specify more than one branch for deletion.  If the branch currently
Previous: Ævar Arnfjörð BjarmasonNext: Ævar Arnfjörð Bjarmason
Message 13 of 14 in “What's cooking in git.git (Jul 2017, #01; Wed, 5)”
  1. Junio C HamanoJul 5, 2017
  2. Stefan BellerJul 5, 2017
  3. Junio C HamanoJul 7, 2017
  4. Stefan BellerJul 10, 2017
  5. 0/3 branch: add a --copy to go with --moveÆvar Arnfjörð Bjarmason, Jul 5, 2017
  6. 1/3 config: create a function to format section headersÆvar Arnfjörð Bjarmason, Jul 5, 2017
  7. 2/3 branch: add test for -m renaming multiple config sectionsÆvar Arnfjörð Bjarmason, Jul 5, 2017
  8. 3/3 branch: add a --copy (-c) option to go with --move (-m)Ævar Arnfjörð Bjarmason, Jul 5, 2017
  9. Junio C HamanoJul 6, 2017
  10. 4/3 branch: fix "copy" to never touch HEADJunio C Hamano, Sep 22, 2017
  11. Brandon WilliamsSep 22, 2017
  12. Ævar Arnfjörð BjarmasonSep 26, 2017
  13. Junio C HamanoSep 27, 2017
  14. Ævar Arnfjörð BjarmasonSep 29, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.