问题描述
我有一个带有2个目录和多个分支的git repo,我想将它们拆分并创建所有分支
I have a git repo with 2 directories and multiple branches, I want to split them and create all branches
`-- Big-repo
|-- dir1
`-- dir2
Branches : branch1, branch2, branch3 ...
我想要的
我想将dir1和dir2拆分为两个单独的存储库,并在两个存储库中保留分支branch1,branch2....
I want to split dir1 and dir2 as two separate repos and retain branches branch1, branch2 ... in both repositories.
dir1
Branches : branch1, branch2, branch3 ...
dir2
Branches : branch1, branch2, branch3 ...
我尝试过的事情:
我可以使用
git subtree split -P dir1 -b dir1-only
git subtree split -P dir2 -b dir2-only
但是,分离后它不会创建任何分支.
But, it is not creating any branches after separation.
获取所有分支:
git checkout branch1 (in Big-repo)
git subtree split -p dir1 -b dir1-branch1
git checkout branch2 (in Big-repo)
git subtree split -p dir1 -b dir1-branch2
And push these branches to newly created repo.
这涉及更多的人工工作,我确定可能有一种快速的方法来实现这一目标?
This involves more manual effort and I am sure there might be a quick way to achieve this?
任何想法?
推荐答案
简短答案
git filter-branch
完全提供了您想要的功能.使用--subdirectory-filter
选项,您可以创建一组新的提交,其中subDirectory
的内容位于目录的根目录.
Short answer
git filter-branch
offers exactly the functionality you want. With the --subdirectory-filter
option you can create a new set of commits where the contents of subDirectory
are at the root of the directory.
git filter-branch --prune-empty --subdirectory-filter subDirectory -- --branches
演练
下面是一个以安全方式执行此操作的示例.您需要对将被隔离到其自己的存储库中的每个子目录执行此操作,在本例中为dir1
.
首先克隆您的存储库以使更改保持隔离:
First clone your repository to keep the changes isolated:
git clone yourRemote dir1Clone
cd dir1Clone
要准备克隆的存储库,我们将所有远程分支重新创建为本地分支.我们跳过以*
开头的那个,因为那是当前分支,在这种情况下,由于我们处于无头状态,因此它将读为(no branch)
:
To prepare the cloned repository we will recreate all remote branches as local ones. We skip the one starting with *
since that is the current branch, which in this case would read (no branch)
since we are in a headless state:
# move to a headless state
# in order to delete all branches without issues
git checkout --detach
# delete all branches
git branch | grep --invert-match "*" | xargs git branch -D
要在本地重新创建所有远程分支,请检查git branch --remotes
的结果.我们跳过包含->
的那些,因为它们不是分支:
To recreate all remote branches locally we go through the results of git branch --remotes
. We skip the ones containing ->
since those are not branches:
# get all local branches for remote
git branch --remotes --no-color | grep --invert-match "\->" | while read remote; do
git checkout --track "$remote"
done
# remove remote and remote branches
git remote remove origin
最后运行filter-branch
命令.这将使用所有触摸dir1
子目录的提交来创建新的提交.所有也触摸此子目录的分支都将得到更新.输出将列出所有未更新的引用,对于完全不触摸dir1
的分支就是这种情况.
Finally run the filter-branch
command. This will create new commits with all the commits that touch the dir1
subdirectory. All branches that also touch this subdirectory will get updated. The output will list all the references that where not updated, which is the case for branches that do not touch dir1
at all.
# Isolate dir1 and recreate branches
# --prune-empty removes all commits that do not modify dir1
# -- --all updates all existing references, which is all existing branches
git filter-branch --prune-empty --subdirectory-filter dir1 -- --all
此后,您将拥有一组新的提交,这些提交在存储库的根目录中具有dir1
.只需添加您的遥控器即可推送新的提交,或将它们完全用作新的存储库.
After this you will have a new set of commits that have dir1
at the root of the repository. Just add your remote to push the new commits, or use these as a new repository altogether.
如果您在乎存储库的大小,这是最后一个附加步骤:
As an additional last step if you care about the repository size:
即使更新存储库的所有分支仍将具有原始存储库的所有对象,也只能通过引用日志访问.如果您想删除这些内容,请阅读如何垃圾收集提交
Even if all branches where updated your repository will still have all the objects of the original repository, tho only reachable through the ref-logs. If you want to drop these read how to garbage collect commits
一些其他资源:
- Github Teaching for filter branch
- Git Book for rewriting history
这篇关于git通过子文件夹拆分存储库并保留所有旧分支的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!