一卓的博客

怕什么真理无穷,
进一寸有一寸的欢喜。

0%

如何仅将一个 Git 仓库的一部分(子集,文件夹)迁移到另一个仓库并保留提交记录

我有一个 Git 存储库,其中包含许多子目录。现在,我发现一个子目录与另一个子目录无关,应该将其分离到单独的存储库中。

如何在保留子目录中文件历史记录的同时执行此操作?

为了清楚起见,假如项目结构为

1
2
3
4
5
XYZ/
.git/
XY1/
ABC/
XY2/

分离后的项目结构为

1
2
3
4
5
6
7
XYZ/
.git/
XY1/
XY2/
ABC/
.git/
ABC/

下面将介绍一种简单的方式来实现分离。

其实这种情况非常普遍,以至于 Git 团队提供了一个新的命令 git subtree 来处理这种情况。需 Git 版本 >= 1.7.11。

第一步 原存储库

1
2
cd <big-repo>
git subtree split -P <name-of-folder> -b <name-of-new-branch>

注意: <name-of-folder> 不得包含前导或尾随字符。例如,subproject 的参数必须为 subproject,而不是./subproject/

Windows 用户注意事项:当文件夹深度> 1时,<name-of-folder> 必须使用文件夹分隔符(/)。例如,名为path1\path2\subproject 的文件夹则参数必须为 path1/path2/subproject

第二步 创建新的仓库

1
2
3
mkdir ~/<new-repo> && cd ~/<new-repo>
git init
git pull </path/to/big-repo> <name-of-new-branch>

第三步 将新仓库链接到 GitHub 或任何地方

1
2
git remote add origin <git@github.com:user/new-repo.git>
git push -u origin master

如果需要删除 <big-repo> 中的目录,可以执行

1
2
git rm -rf <name-of-folder>
git push

例子

项目目录如下

1
2
3
4
5
6
7
8
9
10
11
tree ~/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

我想将 btoa 目录拆分为单独的 Git 存储库

1
2
cd ~/node-browser-compat/
git subtree split -P btoa -b btoa-only

现在,我有了一个新分支,btoa-only 该分支仅具有提交功能,并且我想创建一个新的存储库。

1
2
3
mkdir ~/btoa/ && cd ~/btoa/
git init
git pull ~/node-browser-compat btoa-only

接下来,我在 GitHub 或 Gitlab 上创建一个新的仓库,或将其添加为 origin

1
2
git remote add origin git@github.com:node-browser-compat/btoa.git
git push -u origin master

最后,我要从原仓库中删除文件夹

1
git rm -rf btoa

参考链接:

https://stackoverflow.com/questions/359424/detach-move-subdirectory-into-separate-git-repository

请作者喝杯咖啡吧