git subtree split 生成空提交是因为 --prefix 路径未严格匹配历史:必须以斜杠结尾、大小写完全一致,且该路径需在提交历史中真实存在并被完整提交过;它扫描历史中修改该路径的提交重写新分支,而非提取当前工作区。
执行 git subtree split 后新分支里 git log 有记录但 git show <commit> 看不到文件,tree 为空——这不是 bug,是路径没对上或历史不匹配。
--prefix 必须以斜杠结尾,比如 --prefix=src/lib/;写成 src/lib 或 src/lib/(少斜杠)都会静默失败Src/utils/,写 src/utils/ 就找不到git log --oneline --follow -- src/lib/ 确认这个路径真有连续提交历史git add 过),需要先补一次全量提交:git add src/lib && git commit -m "feat: initial import"
第一次推送到全新远程仓库时,git push origin main 报 ! [rejected] main -> main (non-fast-forward),不是权限问题,是本地分支没关联远程起点。
git push -f 强推,这会破坏后续同步基础git remote add origin-new <new-url>,再显式推送:git push origin-new split-branch:main
master),把 main 换成对应名git branch --set-upstream-to=origin-new/main split-branch,之后才能直接 git push
你要彻底断开和原仓库的关系、追求最干净的历史,git filter-repo 是更优解;如果只是临时切出一个带历史的子模块用于同步维护,subtree split 更轻量。
git filter-repo --path src/cli/:只保留该路径所有历史,其他全删,新仓库根目录就是 src/cli/ 下的内容git filter-repo --subdirectory-filter src/cli/:把 src/cli/ 提升为新仓库根目录(自动去掉前缀)git subtree split 不重写 commit hash,适合后续还要用 git subtree pull/push 双向同步的场景git filter-repo 会重写全部 commit ID,历史不可追溯回原仓库,但新仓库更“独立”git subtree split 只处理指定 --prefix 下的文件,不会把根目录的 .gitignore 或 README.md 带过去——这其实是设计使然,不是 bug。
cp /path/to/original/.gitignore .(注意别复制错路径)README.md,但建议重写开头,注明这是从原项目 packages/core/ 拆出的独立模块package.json 的 "name" 和 "publishConfig" 字段(如果是 npm 包),否则发布时会撞名lerna.json 或 turbo.json 相关配置实际操作中最容易被忽略的,是路径末尾斜杠和历史路径大小写的严格匹配——它不报错,只静默返回空结果,等你发现时已经浪费了半小时排查。