83

I've just discovered git checkout --orphan, but I don't know how to use it. Its help page says it creates a new unparented branch.

In the master branch, I've tried git checkout --orphan br, only to see the files in the working directory change to “Changes to be committed”, and the git log saying fatal: bad default revision 'HEAD'.

So what's the advantage of using git checkout --orphan?

reymon359
  • 1,240
  • 2
  • 11
  • 34
jsvisa
  • 2,987
  • 2
  • 24
  • 30

5 Answers5

101

The core use for git checkout --orphan is to create a branch in a git init-like state on a non-new repository.

Without this ability, all of your git branches would have a common ancestor, your initial commit. This is a common case, but in no way the only one. For example, git allows you to track multiple independent projects as different branches in a single repository.

That's why your files are being reported as “changes to be committed”: in a git init state, the first commit isn't created yet, so all files are new to git.

JB.
  • 40,344
  • 12
  • 79
  • 106
  • `is to create a branch in a git init-like state on a non-new repository` in what situation would it be useful to do that? – Unknow0059 Jan 19 '21 at 07:16
  • 1
    In a situation where you want to keep the files from a certain branch and truncate the history of your repository. I am currently in a scenario, where I have to truncate the git history in order to trim the size of that repository as my Azure App Service doesn't have enough space to accommodate that repo's >16 GBs of commit history. – SouravOrii May 06 '22 at 13:57
  • and in addition - another use case is for deleting commit history and keep your codes current state - right? – Gel Jun 26 '22 at 20:14
  • hint because i just wanted a really empty branch without history and without any files (after a .NET core refactoring): after creating the new branch with `git checkout --orphan ` you get a new branch with no history but same files from branch you started. to get rid of all the files use `git rm -rf .` (mind the dot and make sure you are really standing in the right branch ;-) the result is a branch with no files and no history – golfo Mar 16 '23 at 20:17
  • Top comment for me. – Abdel Shokair Mar 21 '23 at 07:29
23

It's used by e.g. GitHub Pages, which stores a repo's website inside the repo but on a separate branch. There's no reason to store anything but the website's history on this branch.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
7

We were moving to a public repo from a private one and because of sensitive commit information, we wanted to reset a branch as new and push it as a blank branch. Here is a typical way of a workflow for that:

how to delete all commit history in github?

user1767754
  • 23,311
  • 18
  • 141
  • 164
1

In my opinion, this command can be somewhat surprising. There are two very different expectations that you might have for this command:

  1. Fresh start with a truncated history (same tree)
  2. Completely fresh start (new tree; you have to add files from scratch)

1: What it actually does

As JB. has explained, git checkout --orphan <branch name> will:

  1. Put you on an orphan branch, which is a branch that does not have any commits yet
  2. Stage the tree that you came from (master^{tree} if you were on master)
  3. Leave whatever unstaged and untracked files as-is

This means that the trees of the previous commit that you were on and the commit that you create immediately after will be equal:[1]

$ # Let’s say that you’re currently on `master`
$ git checkout --orphan orphan
$ git commit --message 'A new start'
$ git diff master

The diff gives no output because the trees are equal.

This effectively truncates all the commits that you have on master. (Of course master is still there.)

2: What you might expect it to do

Here’s what I expected it to do:

  1. Put you on an orphan branch
  2. Give you an empty tree

The use-case might be to add some files that document some repository-wide metadata, e.g. branch metadata.[2]

It turns out that you can use git switch --orphan <branch name> to accomplish this task, since it almost does what I expected git checkout --orphan <branch name> to do:

  1. Put you on an orphan branch
  2. Remove all tracked files from the tree but leave the untracked ones
    • This means your new tree will contain all of the stuff that you ignored through things like .gitignore
    • Use git clean --force -d if you want to remove all those untracked files

But do note that this command is marked “EXPERIMENTAL” as of the time of writing (Git 2.40.0).

Accomplishing the same thing with git checkout --orphan <branch name>

Maybe you don’t want to use an experimental command. This is the command circumlocution that man git checkout recommends that you do if you want to start with a fresh tree:

git checkout --orphan orphan
git rm -rf .

And then you can also do (added by me):

git clean --force -d

Notes

  1. Well, I guess it will in practice be exactly the same tree, since they have the same hash. :)

  2. Say:

     $ <make orphan branch>
     $ vim branch-descriptions.txt
     $ git add branch-descriptions.txt
     $ git commit --message "Init: descriptions"
    
Guildenstern
  • 2,179
  • 1
  • 17
  • 39
0

Another use case where this may be useful is build machines or virtual instances for testing that require specific .git folder settings (e.g. user, remote url) and all history discarded because of space limitations. This is often the case with legacy setups that don't use containers such as Docker.

It would tipically be done for dedicated deployment branches instead of dealing with master. Once the new branch is pushed to remote, on the instance do:

git clone [remote-url] --branch [name] --single-branch [folder]

Shallow clone would be a better option when working directly with master (not recommended):

git clone -–depth [depth] [remote-url]