“git filter-branch --subdirectory-filter”的相反操作是什么?

7
使用git filter-branch --subdirectory-filter命令,您可以将当前存储库中的子目录转换为单独的存储库。然而,我想做相反的事情:创建一个包含当前存储库完整内容的子目录的存储库,保留所有历史记录,就好像它们一直在该子目录中。我不想使用子模块,因为我希望该目录成为存储库的完全组成部分。
背景:我被要求编写一个简单的脚本,但任务范围已经扩大,所以现在这个脚本只是一个更大项目中的一个子目录。它也没有自己生存的意义,因此最好不使用子模块的解决方案。
3个回答

9
最简单的解决方案是不要动历史记录:只需将所有文件git mv到一个子目录中,提交更改,然后继续生活。
如果你真的想假装一直在子目录中完成这项工作,最简单的方法是使用以下命令:
git filter-branch --tree-filter "mkdir SUBDIR && bash -c 'git mv -k {,.[!.],..[!.]}* SUBDIR/'"

请用目标子目录的名称替换SUBDIR。

Jamey,谢谢,这正是我需要的 :) 至于命令行,它几乎可以正常工作,但不幸的是,它会跳过隐藏文件。我找到了正确匹配它们的解决方案,但它也不能直接使用。不幸的是,这似乎需要显式运行bashgit默认使用sh吗?)。因此,我建议修改您的答案,虽然代码有点臃肿,但对于隐藏文件也有效。 - Septagram
修改对我来说很有意义!我敢打赌你是对的,git filter-branch确实会显式调用sh来运行给定的命令。 - Jamey Sharp
“bash -c'” 部分不是必需的…你必须手动移动被忽略的文件。顺便说一下,我的.gitignore也已经被移动了… - inf3rno

1

您可以将子项目存储库中的文件移动到更大的存储库中所需的目录中,然后将这些提交合并到最终存储库中。这将完全保留两个存储库的历史记录,包括所有提交 ID。

可以使用类似以下命令来完成此操作:

cd /path/to/subproject
mkdir subproject_dir
git mv file1 dir2 dir3... subproject_dir
git commit
cd /path/to/main_project
git pull /path/to/subproject

1
使用git subtree命令。假设您有一个新的存储库:
$ cd $ROOT_OF_NEW_REPO
$ git subtree add --prefix=subdirectory/for/old/repo <old git repo URL or checkout> <commit ref>

eg.

$ git subtree add --prefix=history ~/repos/oldrepo HEAD

history 目录将包含 HEAD 提交时的旧版本文件,以及所有历史记录。


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