一、背景及目标介绍
背景: 把存放于 后台仓库 的 前端代码 完整抽离为一个单独的仓库,并保留需要的分支及提交记录。
目标: 新仓库中,只包含:public目录、dist目录、package.json、package-lock.json、README.md 文件
1. 服务端代码库目录结构:
# 如:projects-backend.git
├── backend
├── projects
│ ├── ...
│ ├── public -- 要提取的文件夹
│ ├── dist -- 要提取的文件夹
│ ├── package.json -- 要提取的文件
│ ├── package-lock.json -- 要提取的文件
│ ├── README.md -- 要提取的文件
├── ...
└── ...
2. 预期实现的效果:
# 如:projects-front-end.git
├── public
├── dist
├── package.json
├── package-lock.json
└── README.md
二、大致步骤:
0. 安装 git-filter-repo
1. 创建新的 git 仓库 备用
2. 通过设置 depth 浅 clone projects-backend 仓库 ,保留近 100次 commit (原因:仓库太大,完整拿不下来, 或完整拿下来后,push到新仓库失败)
3. 分别 fetch 要保留的分支(因为 浅clone 下来的仓库,只有 master 分支的代码,想要其他的分支,需单独做分支拉取操作)
4. 使用 --subdirectory-filter,把 public、dist 等前端文件和文件夹提取到第一级(根目录),去除 projects 这层目录
5. 使用 filter-repo --path 拿取我们想要的文件和文件夹
6. 将 remote origin 更改为 新仓库的地址
7. 将保留下来的分支 push 到远程,完成前端代码抽离及分支保留。
Tips:
如果仓库原本就比较小,那么 第2步 直接执行 git clone ,不设置 depth , 之后就进入 4、5、6、7 步即可,第 3 步就不需要了。
三、实际操作:
0. 安装 git-filter-repo
使用 brew 安装 git-filter-repo,也可百度、google 搜索其他方法,能安装上就好。
# 安装 git-filter-repo
$ brew install git-filter-repo
# 查看 git-filter-repo 版本
$ git-filter-repo --version
10401e45d5f0
安装时如果遇到以下错误,可能是 .bash_profile 中设置了 HOMEBREW_BOTTLE_DOMAIN 阿里云镜像等
tar: Error opening archive: Failed to open '/Library/Caches/Homebrew/downloads/40d8398e4a3d8973f8ed6624552162a05390ef1653e15904bf6a3961bf084cc5--pcre2-10.37.catalina.bottle.tar.gz'
解决办法:
- 方法一: 去除 .bash_profile 中的
HOMEBREW_BOTTLE_DOMAIN镜像 - 方法二: 在终端执行
export HOMEBREW_BOTTLE_DOMAIN=''命令,临时去除镜像 - 去除镜像后,再执行
brew install git-filter-repo进行安装
官方安装说明:github.com/newren/git-…
1. 创建新的 git 仓库 备用
在 git.projects.com 中,创建新的工程 projects-front-end, 创建成功后备用
2. 通过设置 depth 浅 clone projects-backend 仓库 ,保留近 100次 commit
(原因:仓库太大,完整拿不下来, 或完整拿下来后,push到新仓库失败).
$ git clone --depth 100 git@git.projects.com:root/projects-backend.git projects-front-end
正克隆到 'projects-front-end'...
remote: Enumerating objects: 77200, done.
...
正在更新文件: 100% (49129/49129), 完成.
# 进入 clone 下来的仓库中,后续操作,都在此目录下执行
$ cd projects-front-end
刚 clone 下来的文件目录如下
$ ll // 等价于 ls -al
total 8
-rwxr-xr-x 1 staff 1770 Apr 16 14:29 .gitignore*
drwxr-xr-x 3 staff 96 Apr 16 14:29 backend/
drwxr-xr-x 44 staff 1408 Apr 16 14:29 projects/
drwxr-xr-x 14 staff 448 Apr 16 14:30 .../
drwxr-xr-x 3 staff 96 Apr 16 14:30 .../
3. 分别 fetch 要保留的分支(因为 浅clone 下来的仓库,只有 master 分支的代码,想要其他的分支,需单独做分支拉取操作)
如果第 2 步 clone 时,没有设置 --depth ,这一步可跳过
$ git remote set-branches origin remote_branch_name
$ git fetch --depth 100 origin remote_branch_name
$ git checkout remote_branch_name
这里想保留哪些分支,就把 remote_branch_name 换成哪些分支名称就可以。
4. 使用 --subdirectory-filter,把 public、dist 等前端文件和文件夹提取到第一级(根目录),去除 projects 这层目录
如果想要抽离的文件 和 文件夹,原本就在根目录下,这一步可跳过
$ git filter-repo --subdirectory-filter projects/ --force
Parsed 12300 commits
New history written in 2153.92 seconds; now repacking/cleaning...
Repacking your repo and cleaning out old unneeded objects
HEAD 现在位于 55bf0f955 推送兼容
...
总共 182125(差异 110168),复用 172692(差异 106866),包复用 0
Completely finished after 2821.50 seconds.
# 查看结果
$ ll
├── ...
├── public
├── dist
├── package.json
├── package-lock.json
├── README.md
├── ...
├── ...
└── ...
5. 使用 filter-repo --path 拿取我们想要的文件和文件夹
$ git filter-repo --path public --path dist --path package.json --path package-lock.json --path README.md --force
# 查看结果
$ ll
├── public
├── dist
├── package.json
├── package-lock.json
└── README.md
6. 将 remote origin 更改为 新仓库的地址
$ git remote add origin git@git.projects.com:root/project-front-end.git
# 查看设置
$ git remote -v
origin git@git.projects.com:root/project-front-end.git (fetch)
origin git@git.projects.com:root/project-front-end.git (push)
7.将保留下来的分支 push 到远程,完成前端代码抽离及分支保留。
# 全部 push 上去
$ git push --all
# or
# 只 push 某些分支
$ git push origin one_branch_name
# 如果失败,可以加 --force
$ git push --all --force
然后就可以访问远程仓库,查看提取的文件及分支了。
补充:如果采用只拿取部分历史记录的方式抽离分支(--depth n),后续分支之间第一次合并时会报错 refusing to merge unrelated histories. 解决方案为:
git merge 时添加 --allow-unrelated-histories 强制合并,参考命令如下:
$ git merge <对应的分支> --allow-unrelated-histories
参考文档:将子文件夹拆分成新仓库