需求:近期我们发现有两个没有太多开发交集的项目放在了一个代码仓库里,遂对其中的一个仓库进行了拆分,将目录放到了一系列子仓中。
本来准备使用git filter-branch命令,但是在运行时,它提示这个命令会慢,建议使用替代工具git-filter-repo.
一番搜索后,找到了工具及使用方法,非常好用,分享一下。
git-filter-repo官方github地址:
https://github.com/newren/git-filter-repo/
manual page:GitHub & BitBucket HTML Preview
参考文档:
这篇很全:https://josh.fail/2022/merging-git-repos-with-git-filter-repo/
抛砖系列之git仓库拆分工具git-filter-repo_git 拆分仓库_qq_43479892的博客-CSDN博客
这里是filter-branch转换为filter-repo命令的表格:https://github.com/newren/git-filter-repo/blob/main/Documentation/converting-from-filter-branch.md
一、git-filter-repo安装
git-filter-repo 运行环境要求:
- git >= 2.22.0 at a minimum; some features require git >= 2.24.0 or later
- python3 >= 3.5
安装git-filter-repo:
git-filter-repo就是一个python脚本(将文件下载下来:https://raw.githubusercontent.com/newren/git-filter-repo/main/git-filter-repo),并该文件放到你的系统路径下即可,我选择的路径是:/usr/local/bin/git-filter-repo
二、git-filter-repo使用
原仓库tree:
|-- moduleA
| |-- subdir1
| |-- subdir2
| |-- subdir3
| |-- subdir4
主要使用了git-filter-repo的两个命令。
1) git filter-repo --subdirectory-filter moduleA/subdir1 # 将子目录moduleA/subdir1下的内容筛选到根路径下
2) git filter-repo --path moduleA/subdir2 --path moduleA/subdir2 # 将子目录筛选出来,但路径保持不变
以上两个命令可以组合使用就可以达到你想要的分仓效果。
三、分仓后提交
在运行完git filter-repo命令后,使用如下命令进行推送
git push --set-upstream "ssh://新仓库git地址" master --force
四、示例
如我想把原仓库中的moduleA/subdir1下的内容放到一个新仓库中,则在当前仓库根下运行:
git filter-repo --subdirectory-filter moduleA/subdir1
git push --set-upstream "ssh://新git仓库地址" master --force
如我想把原仓库中的moduleA下的subdir2,subdir3放到一个新仓库中,则可以运行如下命令:
git filter-repo --subdirectory-filter moduleA
git filter-repo --path subdir2 --path subdir3
git push --set-upstream "ssh://新git仓库地址" master --force
将根目录移到某个子目录subdir中:
git filter-repo --path-rename :subdir/
总结
这个git-filter-repo工具还是很好用的,可以运行git-filter-repo --help 查看更多命令。
这个是帮助里给出的示例:
EXAMPLES
To get a bunch of reports mentioning renames that have occurred in
your repo and listing sizes of objects aggregated by any of path,
directory, extension, or blob-id:
git filter-repo --analyze
(These reports can help you choose how to filter your repo; it can
be useful to re-run this command after filtering to regenerate the
report and verify the changes look correct.)
To extract the history that touched just 'guides' and 'tools/releases':
git filter-repo --path guides/ --path tools/releases
To remove foo.zip and bar/baz/zips from every revision in history:
git filter-repo --path foo.zip --path bar/baz/zips/ --invert-paths
To replace the text 'password' with 'p455w0rd':
git filter-repo --replace-text <(echo "password==>p455w0rd")
To use the current version of the .mailmap file to update authors,
committers, and taggers throughout history and make it permanent:
git filter-repo --use-mailmap
To extract the history of 'src/', rename all files to have a new leading
directory 'my-module' (e.g. src/foo.java -> my-module/src/foo.java), and
add a 'my-module-' prefix to all tags:
git filter-repo --path src/ --to-subdirectory-filter my-module --tag-rename '':'my-module-'