Programming
How to create a new and empty root branch
Git, the ubiquitous version control system, empowers developers with incredible flexibility in managing project histories. While most developers are familiar with creating feature branches that stem from an existing commit history, there are specific scenarios where a completely clean slate is required. This isn’t about simply deleting files; it’s about severing all ties with the past and starting a new, independent line of development within the same repository. Understanding how to create a new (and empty!) “root” branch is a powerful technique for these unique situations, offering a pristine environment for new project components or documentation without polluting your main codebase’s history. This guide will walk you through the precise steps and best practices to master this advanced Git command, ensuring you can leverage its full potential for structured and isolated project management.
Understanding Git Branches and the “Root” Concept
In Git, a “branch” is essentially a lightweight movable pointer to one of your commits. When you make a new commit, the branch pointer automatically moves forward to the latest commit. This creates a linear history. The “root” commit, in any given branch’s history, is the very first commit in that specific line of development. Typically, all branches in a repository share a common ancestor, tracing back to the initial commit made when the repository was first initialized with git init.
However, Git offers a special type of branch called an “orphan branch.” An orphan branch is unique because, when created, it specifically lacks any parent commits. It starts with an entirely new, unassociated commit history. This means that the first commit you make on an orphan branch will be its “root” commit, and it will have no historical connection to any other commits or branches in your repository, even though it resides within the same .git directory. This powerful feature is crucial when you need to maintain separate, distinct version control streams within a single repository structure.
For instance, imagine you have a large monorepo containing multiple projects. While generally, you’d want a unified history, there might be a component, like a public documentation site, that needs its own, completely isolated history for easier deployment or to avoid exposing internal project details through commit messages. The concept of an orphan branch allows for this level of isolation, providing a truly independent starting point, a new “root,” without creating an entirely new repository.
Why You Might Need an Empty “Root” Branch
Creating an empty “root” branch, often referred to as an orphan branch, serves several distinct purposes in project management and deployment workflows. It’s not a daily operation for most developers, but when the need arises, it’s an indispensable tool for maintaining clean, separated histories within a single Git repository. This approach is particularly beneficial for scenarios where components within the same project or repository have fundamentally different lifecycle or deployment requirements.
Common use cases for establishing an empty “root” branch include:
- GitHub Pages Hosting: This is perhaps the most common reason. Many projects use a
gh-pagesbranch to host static website content for documentation or project showcases. This content often has a completely different structure and history from the main source code, making an orphan branch ideal for managing it independently. - Project Documentation: Similar to GitHub Pages, if your documentation is generated from a separate process or maintained in a distinct format (e.g., Markdown files rendered by a static site generator) and needs its own version control history, an orphan branch provides the perfect isolation.
- Large Binary Assets: Sometimes, repositories accumulate large binary files (e.g., design assets, pre-built libraries) that don’t fit well with the main code’s history. An orphan branch can house these, allowing you to manage their versions separately, potentially even using Git LFS, without bloating the primary branch’s history.
- Cleaning Up Messy History: In rare cases, if a project’s history becomes unmanageably convoluted with sensitive data or irrelevant commits, an orphan branch can serve as a “clean start” for a new, pristine history, while still retaining the old, messy history for reference if needed. This allows you to start fresh without losing the original development lineage entirely.
The ability to create a truly independent line of development ensures that your main project’s commit history remains focused and relevant, while allowing ancillary components to evolve on their own terms. According to a Git SCM documentation, branches are designed for parallel development, and the orphan branch specifically extends this concept to parallel, independent histories.
Creating an empty “root” branch, or an orphan branch, involves a few precise steps. This process will effectively wipe your working directory and index clean, preparing it for an entirely new, unassociated commit history. It’s crucial to follow these steps carefully to achieve the desired outcome without accidentally losing work or creating unintended historical connections. Always ensure your current work is committed or stashed before proceeding.
-
Navigate to Your Repository
First, open your terminal or command prompt and navigate to the root directory of your existing Git Question & Answer :
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
Aas 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 inA.Is there some way I can create a completely bare branch in this repository, with
<start-point>as close toAas 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/graftsAlthough 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 isgit 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.)
Use the
--orphanwhen creating the branch:git checkout --orphan YourBranchNameThis 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”: Agit reset --hardwill empty the index, leaving you with an empty working tree)Take a look at the man page for checkout for more information on –orphan.