我有一个以特定方式探索其他 Web 应用程序的 Web 应用程序。它在一个文件夹中包含一些网络演示,demos
其中一个演示现在应该有它自己的存储库。我想为这个演示应用程序创建一个单独的存储库并使其成为分包 来自主存储库的子模块,而不会丢失其提交历史。
是否可以保留存储库文件夹中文件的提交历史记录并从中创建存储库并将其用作子模块?
我有一个以特定方式探索其他 Web 应用程序的 Web 应用程序。它在一个文件夹中包含一些网络演示,demos
其中一个演示现在应该有它自己的存储库。我想为这个演示应用程序创建一个单独的存储库并使其成为分包 来自主存储库的子模块,而不会丢失其提交历史。
是否可以保留存储库文件夹中文件的提交历史记录并从中创建存储库并将其用作子模块?
请参阅此答案末尾的注释(最后一段),以快速替代使用 npm 的 git 子模块;)
在以下答案中,您将知道如何从存储库中提取文件夹并从中创建一个 git 存储库,然后将其作为子模块而不是文件夹包含在内。
灵感来自 Gerg Bayer 的文章将文件从一个 Git 存储库移动到另一个,保留历史
一开始,我们有这样的事情:
<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 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>
(可选,见评论)我们想从中删除跟踪(文件和提交历史记录),<git repository B>
因此<git repository A>
该文件夹的历史记录仅存在一次。
这是基于从 github中删除敏感数据。
转到一个新文件夹,然后
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
将在指定的目录中递归地执行它:)。现在推origin/master
到--force
git push origin master --force
从into创建一个子模块<git repository B>
<git repository A>
git submodule add <git repository B url>
git submodule update
git commit
验证一切是否按预期工作,并且push
git push origin master
在完成所有这些之后,我意识到在我的情况下,使用npm来管理我自己的依赖项更合适。我们可以指定 git url 和版本,查看package.json git url 作为依赖项。
如果你这样做,你想用作需求的存储库必须是一个npm 模块,所以它必须包含一个package.json
文件,否则你会得到这个错误:Error: ENOENT, open 'tmp.tgz-unpack/package.json'
.
您可能会发现使用npm和使用 git urls 管理依赖项更容易:
npm init
在两个存储库中运行npm install --save git://github.com/user/project.git#commit-ish
您希望安装依赖项的位置运行@GabLeRoux 的解决方案压缩了分支和相关的提交。
克隆和保留所有这些额外分支和提交的简单方法:
1 - 确保你有这个 git 别名
git config --global alias.clone-branches '! git branch -a | sed -n "/\/HEAD /d; /\/master$/d; /remotes/p;" | xargs -L1 git checkout -t'
2 - 克隆遥控器,拉出所有分支,更改遥控器,过滤您的目录,推送
git clone git@github.com:user/existing-repo.git new-repo
cd new-repo
git clone-branches
git remote rm origin
git remote add origin git@github.com:user/new-repo.git
git remote -v
git filter-branch --subdirectory-filter my_directory/ -- --all
git push --all
git push --tags
GabLeRoux 的解决方案效果很好,除非您git lfs
在要分离的目录下使用并且有大文件。在这种情况下,在第 3 步之后,所有大文件将仍然是指针文件,而不是真实文件。我想这可能是由于.gitattributes
在过滤器分支过程中删除了文件。
意识到这一点,我发现以下解决方案对我有用:
cp .gitattributes .git/info/attributes
.gitattributes
将git lfs 用于跟踪大文件的目录复制到目录.git/
以避免被删除。
.gitattributes
当 filter-branch 完成后,如果您仍想为新存储库使用 git lfs,请不要忘记放回:
mv .git/info/attributes .gitattributes
git add .gitattributes
git commit -m 'added back .gitattributes'