如何把子目录拆分成独立的 Git 仓库
拆分子目录为独立仓库并保留历史:git subtree split --prefix=<子目录> -b 新分支,再 init 新仓库 pull 该分支;大规模用 git filter-repo --path <子目录> 更干净。拆分后原仓库的该目录可删除。
推荐 git filter-repo,一条命令把子目录连同历史提出来变成仓库根。经典替代是 git subtree split:先把子目录的历史拆成分支,再基于它建独立仓库。两者都能保留完整提交历史。
方法一:filter-repo(推荐)
pip install git-filter-repo
git clone 原仓库 new-repo && cd new-repo
git filter-repo --subdirectory-filter path/to/subdir
# 子目录内容变成仓库根,历史只保留与它相关的提交
方法二:subtree split(无需装工具)
cd 原仓库
git subtree split --prefix=path/to/subdir -b subdir-history
mkdir ../new-repo && cd ../new-repo
git init
git pull ../原仓库 subdir-history # 拉入拆分出的历史
拆分后收尾
- 新仓库添加远程并推送:
git remote add origin <新地址> && git push -u origin main; - 原仓库删除该目录并提交;
- 若两边还要同步(过渡期),用
git subtree push/pull双向同步,或干脆上 submodules。
常见问题(FAQ)
Q:拆分会丢历史吗?
两种方法都保留该子目录相关的提交历史(提交哈希会变,因为路径变了)。filter-repo 还会自动重写提交信息里的路径引用。
Q:原仓库历史里的大文件让仓库很臃肿怎么办?
这正是 filter-repo 的另一主场:--strip-blobs-bigger-than 10M 之类。拆分+瘦身一起做。
Q:monorepo 拆成多仓库的依赖怎么管?
拆出去的库发版本(npm/pip/maven 私服),主仓库按依赖引用;保留源码级联引用的话用 submodule/subtree 组合。