详细解决方案
有关使用 npm 的 git 子模块的快速替代方法,请参阅此答案末尾的注释(最后一段);)
在下面的答案中,您将知道如何从存储库中提取文件夹并从中创建一个 git 存储库,然后将其包含为 submodule 而不是文件夹。
灵感来自 Gerg Bayer 的文章 Moving Files from one Git Repository to Another, Preserving History
一开始,我们有这样的东西:
<git repository A>
someFolders
someFiles
someLib <-- we want this to be a new repo and a git submodule!
some files
在下面的步骤中,我会将这个someLib 称为<directory 1>。
最后,我们会有这样的东西:
<git repository A>
someFolders
someFiles
@submodule --> <git repository B>
<git repository B>
someFolders
someFiles
从另一个仓库中的文件夹创建一个新的 git 仓库
步骤 1
获取要拆分的存储库的新副本。
git clone <git repository A url>
cd <git repository A directory>
第二步
当前文件夹将是新的存储库,因此请移除当前远程。
git remote rm origin
第三步
提取所需文件夹的历史记录并提交
git filter-branch --subdirectory-filter <directory 1> -- --all
您现在应该有一个 git 存储库,其中包含来自存储库根目录中 directory 1 的文件以及所有相关的提交历史记录。
第四步
创建您的在线存储库并推送您的新存储库!
git remote add origin <git repository B url>
git push
您可能需要为第一次推送设置upstream 分支
git push --set-upstream origin master
清理<git repository A>(可选,见cmets)
我们想从<git repository A> 中删除<git repository B> 的跟踪记录(文件和提交历史记录),因此该文件夹的历史记录只存在一次。
这是基于来自 github 的 Removing sensitive data。
转到一个新文件夹并
git clone <git repository A url>
cd <git repository A directory>
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch <directory 1> -r' --prune-empty --tag-name-filter cat -- --all
将<directory 1> 替换为您要删除的文件夹。 -r 将在指定的目录中递归执行:)。现在用--force推送到origin/master
git push origin master --force
Boss 阶段(见下方注释)
从<git repository B> 创建一个submodule 到<git repository A>
git submodule add <git repository B url>
git submodule update
git commit
验证一切是否按预期工作,push
git push origin master
注意
在完成所有这些之后,我意识到在我的情况下使用npm 来管理我自己的依赖项更合适。我们可以指定git urls和版本,见package.json git urls as dependencies。
如果你这样做,你想要用作要求的存储库必须是一个 npm 模块,所以它必须包含一个 package.json 文件,否则你会收到这个错误:@987654357 @。
tldr(替代解决方案)
您可能会发现使用npm 和manage dependencies with git urls 更容易:
- 将文件夹移至新存储库
- 在两个存储库中运行
npm init
- 运行
npm install --save git://github.com/user/project.git#commit-ish 安装依赖项的位置