Export subtree in Git with history
Asked Answered
S

2

81

I have a folder in my Git repository that I'd like to move out in to its own repository. Is it possible to move the history of that folder along with the folder?

I've previously been doing just a git rm -r --cached subfolder/ and then git init on the subfolder. However, the history is not imported in to the new repository.

Spectacle answered 2/11, 2009 at 18:3 Comment(2)
Similar to, or duplicate of: #811751Rockies
Possible duplicate of How can I move a single directory from a git repository to a new repository whilst maintaining the history?Ankh
H
107

Quoting an example from git-filter-branch(1)

To rewrite the repository to look as if foodir/ has been its project root, and discard all other history:

git filter-branch --subdirectory-filter foodir -- --all

Thus you can, e.g., turn a library subdirectory into a repository of its own. Note the -- that separates filter-branch options from revision options, and the --all to rewrite all branches and tags.

Howey answered 2/11, 2009 at 18:10 Comment(7)
Just make sure to run this on a clone of the original repository, as it wipes the rest of the repo.Aviva
Amazing! I couldn't understand that option without a working example. Thanks!Spectacle
Also, thanks to @Aviva for the heads up. I pushed all my changes to my remote /before/ trying this, so I'd be safe if it wiped my repo; but it would certainly be unexpected.Spectacle
You'd expect the resulting clone to be smaller when you only keep one directory's history, but more work is necessary. The easiest way to shrink it after doing filter-branch is to clone again. See the git-filter-branch(1) manpage for details ("CHECKLIST FOR SHRINKING A REPOSITORY").Rockies
@AdamMonsen: you can do git gc instead of cloning the repo.Portative
To clone the local directory git clone original_repo foodirCorium
See below for an updated answer, as core git team strongly disagrees with this methodAuscultate
W
27

For anyone else arriving here in 2021 (or later), git filter-branch is not strongly recommended by the core git team.

WARNING git filter-branch has a plethora of pitfalls that can produce non-obvious manglings of the intended history rewrite (and can leave you with little time to investigate such problems since it has such abysmal performance). These safety and performance issues cannot be backward compatibly fixed and as such, its use is not recommended. Please use an alternative history filtering tool such as git filter-repo. If you still need to use git filter-branch, please carefully read SAFETY (and PERFORMANCE) to learn about the land mines of filter-branch, and then vigilantly avoid as many of the hazards listed there as reasonably possible.

Instead the recommended tool is git-filter-repo which makes easy work of this problem

git filter-repo --path subfolder/   # Filter the repo to just the sub-dir
git mv subfolder/* .                # Move the contents of the sub-dir to the root
git commit -m "Filtered from main repo"
Wilmington answered 2/2, 2021 at 2:20 Comment(2)
You can even merge it into a single step: git filter-repo --path subfolder/ --path-rename 'subfolder/':''Desolation
Using --path-rename 'subfolder':'' didn't work for me. Instead I used this command to filter and rename in one step: git filter-repo --subdirectory-filter subfolder/Chinese

© 2022 - 2024 — McMap. All rights reserved.