How to create a new (and empty!) "root" branch?
Asked Answered
P

4

191

I would like to define a new "root" branch in this git repository. By "root" branch I mean a branch that is entirely independent of all the other branches in the repository1.

Unfortunately, even the commit (let's call it A) at the very base of the repo's commit tree contains a lot of files (this was a repository that was initialized on an already fairly mature project).

This means that even if I gave A as the new branch's <start-point>, this new branch would not start from a "clean slate", but rather it would contain all the files that were committed in A.

Is there some way I can create a completely bare branch in this repository, with <start-point> as close to A as possible?


1BTW, this is not equivalent to creating a new repo. Separate repos would be less convenient for a lot of reasons.


EDIT: OK, this is what I did, based on vcsjones' answer:

# save rev of the current earliest commit
OLDBASE=$(git rev-list --max-parents=0 HEAD)

# create a new orphan branch and switch to it
git checkout --orphan newbranch
# make sure it's empty
git rm -rf .

# create a new empty commit in the new branch, and
# save its rev in NEWBASE
git commit --allow-empty -m 'base commit (empty)'
NEWBASE=$(git rev-list HEAD)

# specify $NEWBASE as the new parent for $OLDBASE, and
# run filter-branch on the original branch
echo "$OLDBASE $NEWBASE" > .git/info/grafts
git checkout master
git filter-branch

# NOTE: this assumes that the original repo had only one
# branch; if not, a git-filter-branch -f <branch> command
# need to be run for each additional branch.

rm .git/info/grafts

Although this procedure is a bit involved, the end result is an empty base commit that can serve as the <start-point> for any new "clean-slate branch"; all I'd need to do then is

git checkout -b cleanslate $(git rev-list --max-parents=0 HEAD)

In the future I will always create new repositories like this:

git init
git commit --allow-empty -m 'base commit (empty)'

...so that the first commit is empty, and always available for starting a new independent branch. (This would be, I know, a very rarely needed facility, but it is quite effortless to make it readily available.)

Praiseworthy answered 22/2, 2013 at 22:37 Comment(4)
Duplicate of #13969550Ashantiashbaugh
@Anonymoose: Just for the record (rather than debate): I disagree with your opinion.Praiseworthy
There seems to be a much simpler solution based on git rebase --onto, see #645950Forestaysail
Possible duplicate of In git, is there a simple way of introducing an unrelated branch to a repository?Setter
I
290

Use the --orphan when creating the branch:

git checkout --orphan YourBranchName

This will create a new branch with zero commits on it, however all of your files will be staged. At that point you could just remove them.
("remove them": A git reset --hard will empty the index, leaving you with an empty working tree)

Take a look at the man page for checkout for more information on --orphan.

Incommensurate answered 22/2, 2013 at 22:41 Comment(2)
Does this essentially create a blank slate? As in, from scratch? Or does it keep all your previous changes, but just not in the git history?Aryl
@ConAntonakos This creates a new branch without a parent. The other branches are unaffected, all their changes are kept.Jeffjeffcoat
D
27

To add to the accepted answer - best practice to revert to clean state is to create an initial empty commit so you can easily rebase while setting up your branches for posterity. Plus since you want a clean state you probably have committed files that you shouldn't, so you have to remove them from the index. With those in mind you should:

$ git checkout --orphan dev2
Switched to a new branch 'dev2'
$ git reset # unstage all the files, you probably don't want to commit all of them
$ git commit --allow-empty -m 'Initial empty commit'
[dev2 (root-commit) a515c28] Initial empty commit
Dingdong answered 24/10, 2017 at 16:57 Comment(1)
I believe this is not necessary as of 2012 because you can rebase onto root.Phthisic
S
10

Is there some way I can create a completely bare branch in this repository.

The actual command to use (with Git 2.28+) is:

git switch --discard-changes --orphan newBranch
# or
git switch -f --orphan newBranch

git switch is available from Git 2.23 (August 2019), and replaces the old confusing git checkout command.

But I would recommend Git 2.28 (Q3 2020), because git switch --discard-changes --orphan has been optimized in that version.

See commit 8d3e33d, commit 8186128 (21 May 2020) by brian m. carlson (bk2204).
(Merged by Junio C Hamano -- gitster -- in commit ded44af, 09 Jun 2020)

builtin/checkout: simplify metadata initialization

Signed-off-by: brian m. carlson
Reviewed-by: Derrick Stolee

When we call init_checkout_metadata in reset_tree, we want to pass the object ID of the commit in question so that it can be passed to filters, or if there is no commit, the tree.

We anticipated this latter case, which can occur elsewhere in the checkout code, but it cannot occur here.

The only case in which we do not have a commit object is when invoking git switch with --orphan.

Moreover, we can only hit this code path without a commit object additionally with either --force or --discard-changes.

In such a case, there is no point initializing the checkout metadata with a commit or tree because

  • (a) there is no commit, only the empty tree, and
  • (b) we will never use the data, since no files will be smudged when checking out a branch with no files.

Pass the all-zeros object ID in this case, since we just need some value which is a valid pointer.

Test:

git switch master
echo foo >foo.txt
git switch --discard-changes --orphan new-orphan2
git ls-files >tracked-files
# test_must_be_empty tracked-files
Starvation answered 13/6, 2020 at 15:42 Comment(0)
J
5

If you use git 2.23 or above you may be used to git switch and git restore instead of git checkout. If so, the flag is the same as mentioned in this answer.

git switch --orphan YourBranchHere
Johny answered 23/3, 2020 at 20:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.