如何在保留历史记录和文件结构的同时将git存储库的一部分提取到其自己的存储库中?

时间:2014-08-12 21:49:00

标签: git

我有一个大型git存储库,其文件夹结构如下:

/A
/B
/C
/D
...

我想在维护历史记录的同时将/ A和/ B文件夹提取到他们自己的仓库中(我只关心主分支)。因此,新的回购将如下:

/A
/B

我该怎么做?我发现git filter-branch有助于重写历史记录,但我不知道如何使用它来保存多个子目录。

2 个答案:

答案 0 :(得分:4)

git clone initial final
cd final
git filter-branch --tree-filter 'rm -rf <list of folders separated by space>' HEAD

上述命令将删除列表中提到的所有文件夹,但将保留原始提交历史记录。

git filter-branch -f --prune-empty 

然后可以用于删除可能显示在已删除文件夹列表中的任何空提交。

或者,如果您有一个历史悠久的大型存储库,这可能需要一段时间。在这种情况下,您可以采取略微不同的方法 -

首先为要迁移的每个文件夹创建单独的存储库。这可以使用filter-branch命令完成,如下所示

 git filter-branch –prune-empty –subdirectory-filter A/ master
 git filter-branch –prune-empty –subdirectory-filter B/ master

每个文件夹都包含相应文件夹的内容及其所有历史记录。然后,您可以将它们作为临时存储库推送到远程。 (如果您需要重新执行此过程,这些也将作为检查点)

接下来,创建新的存储库

git clone <remote path> NewRepo
cd NewRepo

# add a readme file
touch Readme.md
git add .
git commit -am "Adding ReadMe file"

然后,您可以将各个文件夹(A和B repos)合并到NewRepo

# Merge Repo A
git remote add -f A <remote path for A>
git merge -s ours --no-commit A/master
git read-tree --prefix=A/ -u A/master
git commit -m "Merge A into NewRepo"
git remote remove A

# Merge Repo B
git remote add -f B <remote path for B>
git merge -s ours --no-commit B/master
git read-tree --prefix=B/ -u B/master
git commit -m "Merge B into NewRepo"
git remote remove B

接下来,您可以确认您的原点设置为指向NewRepo并推送代码

git remote add origin <remote path for NewRepo>
git push origin master

NewRepo现在应该包含文件夹及其所有历史记录。

答案 1 :(得分:0)

filter-branch可能需要一段时间才能运行,但我会尝试在本地复制存储库并将其用于测试。

git clone repoA repoB
cd repoB
git filter-branch --tree-filter 'rm -rf C D <other files you DON'T want>' HEAD

同样,这可能需要很长时间才能运行,但我认为它会做你正在寻找的事情。