How to Move Subdirectory Into New Git Repository?
Wednesday, February 2, 2022 • 3 minutes to read
I have had to move one of the subdirectories of a Git repository to a new one. I needed to keep the commits history on the new repository. But, of course, only that relevant part of history for my subfolder. Looking on the Internet for a solution, I have found a lot of articles suggesting
filter-branch, but it turns out it is not the best solution. At least for me.
Let’s start with clearly defining what we want to do. We would like to have a new repository with the content and commits history, including merges, of a subfolder from some other repository. Let’s assume the subdirectory name is
docs and will create a new repo called
How to split a subfolder content and history into a new branch?
The easiest way to achieve our goal will be using Git
subtree command. The following command will create a new branch with history prefixes with
$ git subtree split -P docs -b docs_branch
What does it mean? The new history includes only the commits that affected our subfolder
docs, and each of those commits now has the contents of
docs at the root of the project instead of in a subfolder.
In plain words, our
docs_branch has all history of our
docs subfolder as is no other part of the old repo exists. This command does not change anything in the original repository or amend any history.
There are some essential remarks here. First, repeated splits with the same prefix (
-P) produce the same commit ID; thus, every command’s call creates the same history tree. This command will not be suitable if you split multiple subfolders with different names.
How to create a new repository from a branch?
After the previous command, you will have a branch with the desired data and history, and you can initialize a new repository based on it. The following commands will create a repo and pull the branch as a new
$ git init docs-repo $ cd docs-repo $ git pull ../original_repo docs_branch
You can add a remote, empty repository as the “origin” one and push the “master” branch if you desire.
$ git remote add origin remote_repo $ git push -u origin master
In the end, you can remove the subfolder which we successfully split from the original repository and commit your changes.
How can I remove history from the Git repository?
The short answer is, you cannot. Or, to be more precise, you cannot if you published your repository before the split. The history of our deleted folder is still in the repository, although the files are not there.
There is an option to remove the history, the
filter-branch command, at the beginning of this article.
$ git filter-branch --prune-empty --tree-filter 'rm -rf docs' HEAD
You will notice that the history of that folder is not existing when you run
git log, but when you want to push it to the remote repository, you will not be able to do it unless you call
git pull, which will, of course, recover the history.
On the other hand, in “Git best practices”, I describe why you should not rewrite any history. So please do not do it.