执行 git subtree split 时跟随重命名操作

20

我有很多子目录,想要将它们分离成一个单独的仓库。为了用一条命令提取这些文件,我将它们移动(重命名)到根目录下的一个子目录中。

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

如果我切换到这个新分支并运行git log --follow someoldfile,它只会显示与移动到临时子目录相关的日志条目。我想保留这些文件的完整历史记录。

在进行子树分割时,有没有一种方法可以保留完整的历史记录,包括重命名?是否有其他实现所需结果的方法?

我考虑在克隆的仓库上使用filter-branch,但我知道那会非常慢。


有趣的阅读材料:https://dev59.com/A2025IYBdhLWcg3w25yy,https://dev59.com/FXHYa4cB1Zd3GeqPP8pE#16416818。不确定这是否可能。 - VonC
我猜这是有道理的,如果目录结构完全不同,就没有办法使用旧的更改。 - el_tone
1个回答

11

实际上这是可能的,而且这个问题已经在这里提出了几次,虽然没有通用的方法,看起来你必须自己组合配方。

如果你只想留下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命令中有许多参数是关键的,可以遍历所有的历史记录、分支和标签。

为了加快速度,您可以先识别要删除的库中最大的部分,然后进行git gc --aggressive操作。用i5 CPU和SSD硬盘,完成一个git filter-branch迭代大约需要一分钟,大约处理了1000个历史记录条目。


1
这是我已经决定采用的解决方案,但从未有机会尝试。感谢您抽出时间回答。 - el_tone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接