执行git子树拆分时请遵循重命名

时间:2014-10-10 17:29:56

标签: git git-subtree

我有很多子目录,我想把它们分成一个单独的仓库。为了使用单个命令提取它们,我将它们移动(重命名)到根目录内的单个子目录。

然后我跑:git subtree split -P my_new_subdir -b newbranch

如果我然后签出这个新分支并运行git log --follow someoldfile它只显示与移动到临时子目录有关的日志条目。我想继续这些文件的完整历史记录。

有没有办法保留完整的历史记录,包括在进行子树分割时重命名?还有其他方法可以达到预期的结果吗?

我考虑在repo的克隆上使用filter-branch,但我知道这将非常慢。

1 个答案:

答案 0 :(得分:8)

实际上这是可能的,这个问题已在这里提出过几次,虽然没有通用方法,看起来你必须自己编写食谱。

如果您只想保留my_new_subdir中的文件,您需要自己删除所有其他文件。这个概念是使用:

git filter-branch --tag-name-filter cat --index-filter \
  'git rm -r --cached --ignore-unmatch 
    unneeded-subdir-1 unneeded-pattern-* unneeded-etc' \
--prune-empty -f -- --all

然后,为了帮助找到其他必须删除的内容,您可以使用类似:

git log --name-status --all  | grep -P '^\w\s+[\S]+$'

甚至例如:

git log --name-status --all  | grep -P '^\w\s+[\S]+$' | \
  sed s/^.// | cut -f 1-2 -d '/' | sort -u

通过这种方式,您可以随时找到存储在仓库中的所有文件/目录(或者只是前两个路径段)。之后,您可以使用以下命令来清理仓库:

git gc --aggressive

所以在将文件移到my_new_subdir之后我已经使用了上述命令的组合来清理历史记录中任何不需要的文件。但是我仍然在历史中发现了不相关的合并,但最后我对结果感到满意。请注意,上面有一些git命令的参数对于遍历所有历史记录,分支和标记至关重要。

为了加快速度,您可以在第一次迭代中识别要删除的repo的最大部分,然后执行git gc --aggressive。拥有i5 CPU和SSD磁盘我花了大约一分钟完成一次git filter-branch次迭代,并且已经处理了大约1000个历史条目。