* Orphan branch not well-defined?
@ 2023-11-22 0:28 Craig H Maynard
2023-11-22 1:08 ` Junio C Hamano
2023-11-22 1:42 ` Chris Torek
0 siblings, 2 replies; 7+ messages in thread
From: Craig H Maynard @ 2023-11-22 0:28 UTC (permalink / raw)
To: Git Community
Team,
Recently I tried creating an orphan branch in an existing repo using git-checkout and git-switch.
Both commands have an --orphan option.
The results were different:
git checkout --orphan <newbranch> retained the entire working tree, including subdirectories and their contents.
git switch --orphan <newbranch> retained subdirectories but NOT their content.
Leaving aside the question of whether or not this is a bug, there doesn't appear to be any formal definition of the term "orphan branch" in the git documentation. Am I missing something?
Thanks,
Craig
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Orphan branch not well-defined?
2023-11-22 0:28 Orphan branch not well-defined? Craig H Maynard
@ 2023-11-22 1:08 ` Junio C Hamano
2023-11-22 1:42 ` Chris Torek
1 sibling, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2023-11-22 1:08 UTC (permalink / raw)
To: Craig H Maynard; +Cc: Git Community
Craig H Maynard <chmaynard@me.com> writes:
> Recently I tried creating an orphan branch in an existing repo using git-checkout and git-switch.
>
> Both commands have an --orphan option.
>
> The results were different:
This is one of the very much deliberate differences between "switch"
and "checkout" (there are others).
The "switch" command was introduced as an experiment to figure out a
better UI choices for one half of "checkout", which deals with
checking out a branch to a working tree (the other half being
"restore", which is about checking out files out of a tree-ish).
The initial round of "switch" proposed to go with the identical
semantics as "checkout" for the "--orphan" option [*1*], but during
review discussion, a concensus was reached that a better behaviour
for creating an entirely new history may be to start from void
[*2*], and that is what is in the experimental command you see.
[Reference]
*1* https://lore.kernel.org/git/20190130094831.10420-9-pclouds@gmail.com/
*2* https://lore.kernel.org/git/CABPp-BF3_p3+fmQcWYEu2z3J4FfPmDmiMyFiBRXyz8TxKLL7jA@mail.gmail.com/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Orphan branch not well-defined?
2023-11-22 0:28 Orphan branch not well-defined? Craig H Maynard
2023-11-22 1:08 ` Junio C Hamano
@ 2023-11-22 1:42 ` Chris Torek
2023-11-24 2:03 ` Junio C Hamano
1 sibling, 1 reply; 7+ messages in thread
From: Chris Torek @ 2023-11-22 1:42 UTC (permalink / raw)
To: Craig H Maynard; +Cc: Git Community
On Tue, Nov 21, 2023 at 4:36 PM Craig H Maynard <chmaynard@me.com> wrote:
> [git checkout and git switch treat --orphan differently]
>
> Leaving aside the question of whether or not this is a bug,
Just to answer the implied question: this is intentional.
> there doesn't appear to be any formal definition of the term "orphan branch"
> in the git documentation. Am I missing something?
Whether it's documented anywhere or not, it's not done well. This is
not surprising: It is hard to do it well! Git uses two phrases for
this: "orphan branch" and "unborn branch". To understand them
properly, let's start at the real beginning. Bear with me for a
moment here.
In Git, the identity of a commit -- the way that Git locates the
commit internally -- is its hash ID. (Aside: until the SHA-256
conversion, therewas only ever one hash ID for any commit ever made
anywhere. Now that Git supports both SHA-1 and SHA-256, there are two
possible IDs, depending on which scheme you're using.) It's possible,
at least in theory, to use Git without ever creating a branch name:
all you have to do is memorize these random-looking hash IDs. But
that's not how people's brains work, and it's quite impractical. So
Git offers us branch names, like "main" or "master", "dev" or
"develop", and so on.
In Git, a branch name is just a human-readable name for one of Git's
internal hash IDs, with a special and very useful property that
distinguishes it from a tag name. Each tag name is a human-readable
name for a hash ID too; they just lack the special property of the
branch names. We won't get into all the properties here though, and
for the moment, we just need to know that the name stands in as a
memorable version of the ID.
As a result, a Git branch name literally cannot exist unless it
identifies one specific commit! We call that one specific commit the
"tip commit" of that branch (which introduces a whole new confusion,
of whether a "branch" is *one commit* or *many commits*, but again we
won't get into this here).
This leaves us with a big "chicken or egg" problem
(https://en.wikipedia.org/wiki/Chicken_or_the_egg). Suppose we've
just created a new, empty repository, which by definition has no
commits in it: it's *new*, and *empty*. How many branch names can we
have in this new, empty repository? We've just claimed that a branch
name must identify some specific commit, and we have no commits, so
the answer is: none. We cannot have any branch names at all.
But -- here's the other paradox -- whenever we make a *new* commit,
it's to be *added on to the current branch*. But we have an empty
repository, which cannot have any branch names, so how do we know what
the "current branch" even *is*?
** Unborn Branch is the better term **
Now that we understand the basic problem -- that a new repository
can't have any branches, but that we want Git to *create* a branch
when we make that very first commit -- we can see what an "orphan" or
"unborn" branch is all about. It papers over our chicken-or-egg
problem. We simply save the *name we want Git to create* somewhere,
then we make a new commit as usual. When, eventually, we do make that
commit, Git says: "OK, I should add this new commit to the current
branch br1", or whatever the name is. Git then creates the new commit
*and* creates the branch name, all as one big operation. Now the
branch exists: it's born.
When we have a normal (not-unborn) branch and create a new commit, Git
creates the new commit as usual and then -- here's the unique property
of *branch names* that makes them so special -- *updates* the branch
name to hold the new commit's new hash ID. Git also makes sure that
the new commit we just made links back to the commit that *was* the
tip commit of the branch, just a moment ago. So this is how branches
"grow" as you make commits. The *name* holds only the *last* commit
hash ID. Each commit holds the *previous* hash ID, so that Git can
start at the end of a branch and work backwards. The previous, or
parent, commit, has its own parent, which has another parent, all the
way back to the beginning of time.
This is also where the dual meaning of "branch" clears up somewhat: a
branch is both the tip commit *and* the whole-chain-of-commits,
starting at the tip and working backwards. How do we know which
meaning someone means? Sometimes it's clear from context. Sometimes
it's not clear. Sometimes whoever used the word isn't even aware of
the issue!
** The `--orphan` options **
That weird problematic state for a *new* repository, where no branches
can exist, yet you want to be "on" the branch you're going to create,
only exists as a problem for a new and empty repository. But given
that Git has to solve that problem, Git can let you enter that weird
state any time. That's what `--orphan` was originally invented for:
to go back into that state even if you have some commits.
That is, `git checkout --orphan` meant: make the current branch name
be an unborn branch, the way it is in a new and totally-empty
repository. Then when I make my next commit, that will create a new
commit that has no parent commit. Whether (and when and how) this is
actually useful is another question entirely, as is the reason for
switch and checkout behaving differently in terms of how they treat
the index and working tree. But this is the heart of the option: it
means "go into the unborn branch state".
(Side note: there are other ways to solve the "new repository"
problem, and there are other ways to define "branch". Other version
control systems sometimes use other ways. Git's rather peculiar
definition of branch was rare, perhaps even unique, in the early days
of Git.)
Chris
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Orphan branch not well-defined?
2023-11-22 1:42 ` Chris Torek
@ 2023-11-24 2:03 ` Junio C Hamano
2023-11-24 2:12 ` Junio C Hamano
2023-11-24 2:27 ` Eric Sunshine
0 siblings, 2 replies; 7+ messages in thread
From: Junio C Hamano @ 2023-11-24 2:03 UTC (permalink / raw)
To: Chris Torek; +Cc: Craig H Maynard, Git Community
Chris Torek <chris.torek@gmail.com> writes:
> ** Unborn Branch is the better term **
Yes, To orphan is a verb that denotes the act of becoming on an
unborn branch, and a few references to "orphan branch" in our
documentation are misuses of the word, I would have to say.
I suspect that there are other mentions of "orphan branch" in the
code comments, variable names, and even end-user facing messages,
some of which may need to be corrected, but the first place to start
is in the glossary. How about this?
Documentation/glossary-content.txt | 19 +++++++++++++++++++
Documentation/config/advice.txt | 2 +-
Documentation/git-checkout.txt | 2 +-
Documentation/git-switch.txt | 2 +-
Documentation/git-worktree.txt | 4 ++--
5 files changed, 24 insertions(+), 5 deletions(-)
diff --git c/Documentation/glossary-content.txt w/Documentation/glossary-content.txt
index 59d8ab8572..bbf7b84ab7 100644
--- c/Documentation/glossary-content.txt
+++ w/Documentation/glossary-content.txt
@@ -312,6 +312,13 @@ This commit is referred to as a "merge commit", or sometimes just a
[[def_octopus]]octopus::
To <<def_merge,merge>> more than two <<def_branch,branches>>.
+[[def_orphan]]orphan::
+ The act of becoming on an <<def_unborn,unborn>> branch.
+ After such an operation, the <<def_HEAD,HEAD>> points at a
+ <<def_branch,branch>> that does not yet exist, and the
+ commit first created from such a state becomes a root
+ commit, starting a new history.
+
[[def_origin]]origin::
The default upstream <<def_repository,repository>>. Most projects have
at least one upstream project which they track. By default
@@ -695,6 +702,18 @@ The most notable example is `HEAD`.
object,
etc.
+[[def_unborn]]unborn::
+ The <<def_HEAD,HEAD>> can point at a <<def_branch,branch>>
+ that does not yet have any <<def_commit,commit>> on it, and
+ such a branch is called an unborn branch. The most typical
+ way users encounter an unborn branch is by creating a
+ repository anew without cloning from elsewhere. The HEAD
+ would point at the 'main' (or 'master', depending on your
+ configuration) branch that is yet to be born. Also some
+ operations can get you on an unborn branch with their
+ <<def_orphan,orphan>> option.
+
+
[[def_unmerged_index]]unmerged index::
An <<def_index,index>> which contains unmerged
<<def_index_entry,index entries>>.
diff --git c/Documentation/config/advice.txt w/Documentation/config/advice.txt
index 2737381a11..4d7e5d8759 100644
--- c/Documentation/config/advice.txt
+++ w/Documentation/config/advice.txt
@@ -140,6 +140,6 @@ advice.*::
Advice shown when a fast-forward is not possible.
worktreeAddOrphan::
Advice shown when a user tries to create a worktree from an
- invalid reference, to instruct how to create a new orphan
+ invalid reference, to instruct how to create a new unborn
branch instead.
--
diff --git c/Documentation/git-checkout.txt w/Documentation/git-checkout.txt
index 240c54639e..26ad1a5e27 100644
--- c/Documentation/git-checkout.txt
+++ w/Documentation/git-checkout.txt
@@ -215,7 +215,7 @@ variable.
below for details.
--orphan <new-branch>::
- Create a new 'orphan' branch, named `<new-branch>`, started from
+ Create a new unborn branch, named `<new-branch>`, started from
`<start-point>` and switch to it. The first commit made on this
new branch will have no parents and it will be the root of a new
history totally disconnected from all the other branches and
diff --git c/Documentation/git-switch.txt w/Documentation/git-switch.txt
index c60fc9c138..3e23a82cf2 100644
--- c/Documentation/git-switch.txt
+++ w/Documentation/git-switch.txt
@@ -171,7 +171,7 @@ name, the guessing is aborted. You can explicitly give a name with
`branch.autoSetupMerge` configuration variable is true.
--orphan <new-branch>::
- Create a new 'orphan' branch, named `<new-branch>`. All
+ Create a new unborn branch, named `<new-branch>`. All
tracked files are removed.
--ignore-other-worktrees::
diff --git c/Documentation/git-worktree.txt w/Documentation/git-worktree.txt
index 93d76f5d66..2a240f53ba 100644
--- c/Documentation/git-worktree.txt
+++ w/Documentation/git-worktree.txt
@@ -99,7 +99,7 @@ command will refuse to create the worktree (unless `--force` is used).
If `<commit-ish>` is omitted, neither `--detach`, or `--orphan` is
used, and there are no valid local branches (or remote branches if
`--guess-remote` is specified) then, as a convenience, the new worktree is
-associated with a new orphan branch named `<branch>` (after
+associated with a new unborn branch named `<branch>` (after
`$(basename <path>)` if neither `-b` or `-B` is used) as if `--orphan` was
passed to the command. In the event the repository has a remote and
`--guess-remote` is used, but no remote or local branches exist, then the
@@ -234,7 +234,7 @@ This can also be set up as the default behaviour by using the
--orphan::
With `add`, make the new worktree and index empty, associating
- the worktree with a new orphan/unborn branch named `<new-branch>`.
+ the worktree with a new unborn branch named `<new-branch>`.
--porcelain::
With `list`, output in an easy-to-parse format for scripts.
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: Orphan branch not well-defined?
2023-11-24 2:03 ` Junio C Hamano
@ 2023-11-24 2:12 ` Junio C Hamano
2023-11-24 2:27 ` Eric Sunshine
1 sibling, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2023-11-24 2:12 UTC (permalink / raw)
To: Chris Torek; +Cc: Craig H Maynard, Git Community
Junio C Hamano <gitster@pobox.com> writes:
> Chris Torek <chris.torek@gmail.com> writes:
>
>> ** Unborn Branch is the better term **
>
> Yes, To orphan is a verb that denotes the act of becoming on an
> unborn branch, and a few references to "orphan branch" in our
> documentation are misuses of the word, I would have to say.
To be fair, the use of verb "orphan" by the folks first designed the
"checkout --orphan" does make quite a lot of sense and it is very
much consistent with the fact that the operation leaves the index
and the working tree intact (unlike "switch --orphan" that empties
the contents, which came much later).
The intended use case was that the user had the current set of
contents that is desirable with history that is undesirable behind
it, and wanted to part with the baggage^Whistory while keeping the
end state. The operation was meant to be the first step to create a
"parent-less" (aka "orphaned" from the parents in the original
history) commit that records the desired state. It is the reason
why "checkout --orphan" keeps the contents intact and moves the HEAD
to be on an unborn branch.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Orphan branch not well-defined?
2023-11-24 2:03 ` Junio C Hamano
2023-11-24 2:12 ` Junio C Hamano
@ 2023-11-24 2:27 ` Eric Sunshine
2023-11-24 2:31 ` Junio C Hamano
1 sibling, 1 reply; 7+ messages in thread
From: Eric Sunshine @ 2023-11-24 2:27 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Chris Torek, Craig H Maynard, Git Community
On Thu, Nov 23, 2023 at 9:03 PM Junio C Hamano <gitster@pobox.com> wrote:
> +[[def_orphan]]orphan::
> + The act of becoming on an <<def_unborn,unborn>> branch.
s/on an/an/
> + After such an operation, the <<def_HEAD,HEAD>> points at a
> + <<def_branch,branch>> that does not yet exist, and the
> + commit first created from such a state becomes a root
> + commit, starting a new history.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Orphan branch not well-defined?
2023-11-24 2:27 ` Eric Sunshine
@ 2023-11-24 2:31 ` Junio C Hamano
0 siblings, 0 replies; 7+ messages in thread
From: Junio C Hamano @ 2023-11-24 2:31 UTC (permalink / raw)
To: Eric Sunshine; +Cc: Chris Torek, Craig H Maynard, Git Community
Eric Sunshine <sunshine@sunshineco.com> writes:
> On Thu, Nov 23, 2023 at 9:03 PM Junio C Hamano <gitster@pobox.com> wrote:
>> +[[def_orphan]]orphan::
>> + The act of becoming on an <<def_unborn,unborn>> branch.
>
> s/on an/an/
I actually did mean it. It is not a verb whose subject is a branch.
The user (or you can call a repository) gets on a branch that
happens not to exist yet.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2023-11-24 2:31 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-22 0:28 Orphan branch not well-defined? Craig H Maynard
2023-11-22 1:08 ` Junio C Hamano
2023-11-22 1:42 ` Chris Torek
2023-11-24 2:03 ` Junio C Hamano
2023-11-24 2:12 ` Junio C Hamano
2023-11-24 2:27 ` Eric Sunshine
2023-11-24 2:31 ` Junio C Hamano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).