* 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).