Difference between git filter branch and git subtree?
2016: Yes, git subtree
(a contrib/
shell) can be used to split repos, as described in "Using Git subtrees for repository separation" by Stu Campbell.
You need to remove the code that you have duplicated in your split folder, though (see also theamk's answer):
git subtree split --prefix=path/to/code -b splitgit push ~/shared/ split:mastergit rm -r path/to/codegit commit -am "Remove split code."
That differs from git filter-branch
(a native Git command) which rewrites the repo history, picking up only those commits that actually affect the content of a specific subdirectory.
Meaning: there is no code to git rm
once the filter-branch
has been run.git filter-branch
does not duplicate commits like : it deletes ("filters out") everything that does not match a certain criterion (here a subfolder path).git subtree split
does
Again, see theamk's answer for updates: there is no duplication when using a new branch: git subtree split --prefix=some_subdir -b some_branch
.
Update 2021:
Do use
git switch some_branch
orgit switch -c some_branch
, instead of the old and confusinggit checkout
command.Do consider the new and improved
git filter-repo
, sincegit filter-branch
andBFG
are officially obsolete.
(Seegit filter-branch
man page)
git filter-repo
can extract wanted paths and their history (stripping everything else)
git switch -c some_branch git filter-repo --path some_subdir/ --refs some_branch
When executed as written, the differences are pretty minor:
- your "subtree split" command will start from
HEAD
and put result tosome_branch
, which must not exist before - your "filter-branch" command will start with
some_branch
and put result back tosome_branch
, overridingsome_branch
with the new content. - In my tests, "git filter-branch" was ~50x faster (on a very old repo with only a few commits touching the selected path)
In other words, the two snippets below are exactly equivalent, as long as special subtree rejoin
commits are not found.
git subtree split --prefix=some_subdir -b some_branchgit checkout some_branch
and
git checkout -b some_branchgit filter-branch --subdirectory-filter some_subdir some_branch
why bother with "git subtree" then, you may ask? For --rejoin
and --onto
options -- they support a very specific workflow which original author was using.