我有一个git分支,其中包含许多我想将这些目录变成所有新分支。看起来有点像这样:
git/dev/us-> us-One,us-two,us-three
我希望它像这样结束:
git/dev/us-Onegit/dev/us-two等
使用git-filter-branch似乎可以使用,但是我不确定如何将其与所有目录一起使用。我可以做类似的事情:
for branch in `find . -type d -d 1`; do
git filter-branch --subdirectory-filter $branch --prune-empty -- --all
done
好吧,我想有一种方法可以做到。首先指出一些后代的事情...
警告
由于您正在谈论使用filter-branch
,因此我想您已经考虑了为每个分支创建单独历史的含义。以防万一,我指出的是,使用您的旧存储库来在新存储库中找到相应的代码版本可能很困难。另外,如果跨目录之间的更改是协调的,这些协调将丢失(除非您做某事以重新创建它们(。
可能与最后一点有关,如果每个目录中的结构都足够相似,那么这是有意义的,那么如果他们有时不需要"共享"更改,那将是令人惊讶的。您描述的"当前状态"结构也不是您要求的"目标状态",如果确实是一个问题,那么真的会很好地支持这一点。
但是您将如何做?
在最简单的情况下,您刚刚有一个要为每个目录"突破"的分支。这在您的问题中暗示了,但是以防万一我会提供一个更通用的程序,该程序应该适用于多个分支。
因此,首先,您需要实际创建所需的所有分支。如果您有标签,则可能也需要复制它们,但我会回到那个。
对于您拥有的每个分支:
git checkout `branchA`
git branch `branchA-one`
git branch `branchA-two`
...
git checkout `branchB`
git branch `branchB-one`
git branch `branchB-two`
...
...
然后,您可以在每组REFS上运行filter-branch
。您肯定会使用subdirectory-filter
,如果您有标签可以保留,则也需要tag-name-filter
。如果典型的更改会影响某些(但不是全部(子目录,那么您需要确定是否要(a(保留并行历史,或(b(使filter-branch
消除空的commits
所以在最简单的情况下
git filter-branch --subdirectory-filter dir-one -- branchA-one branchB-one ...
如果要保留标签,最简单的是将它们复制到每个新历史记录中(使用与分支相同的后缀(,那么
git filter-branch --subdirectory dir-one --tag-name-filter 'sed s/$/-one' -- branchA-one branchB-one
,如果要删除不影响分支子树的提交的提交,则可以输入--prune-empty
。
filte-branch
的每次运行都会创建一些您要清理的"备份参考"(refs/original/...
(
请注意,此最有可能提供的是常见的根提交。您最终将在回购中获得独立的历史。通常没关系。如果您稍后决定将它们分成不同的存储库,这很方便。如果您预计在这些历史中合并,则不太方便。
在最后一个情况下,您可以大部分时间(例如合并中的--allow-unrelated-histories
(围绕独立历史进行工作,但是如果您不想要进行,那么您会修改上述过程。在执行filter-branches
之前,您将创建一个空的"共享根"
git branch --orphan newRoot
git rm -r *
git commit --allow-empty
,然后您将包括一个parent-filter
,将每个重写的根嫁接到newRoot
。