通过将DIR转换为新的分支,使GIT子目录更平坦

  • 本文关键字:GIT 子目录 分支 DIR 转换 git
  • 更新时间 :
  • 英文 :


我有一个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

最新更新