删除不在子树中或原始存储库中的提交

时间:2014-01-19 13:28:06

标签: git git-filter-branch git-subtree git-rewrite-history

我实际上有两个存储库:

  • main
  • external

main存储库在一段时间后合并到external/main目录(作为子树)。 现在,我想将对external/main所做的更改迁移回main存储库,但仅限于这些提交,而不是external/<anything-else>之类的其他无关提交。

我实际上尝试过经典:

git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter main -- --all

但是它也删除了对初始main存储库的所有提交,只留下了external git存储库中的提交。


所以:如何只保留提交:

a)对初始main存储库

b)对externalexternal/main

的子树进行了制作

当我尝试git pull -s subtree ../external时,提交都被合并,包括在子树中没有改变任何内容的提交。我想只有实际改变了子树中某些东西的提交,而且还只有关于子树中文件的信息。

2 个答案:

答案 0 :(得分:2)

您应该可以使用命令的filter-branch部分中的--not --remotes来限制<rev-list options>重写的提交:

git filter-branch --tag-name-filter cat --prune-empty
    --subdirectory-filter main -- --all --not --remotes

这将导致filter-branch不包括从远程分支可到达的提交。如果您有多个遥控器,则可以使用类似--remotes=origin的内容来指定要考虑的遥控器。

答案 1 :(得分:1)

为了将main external中发生的所有相关变更纳入main,需要做两件事:

  • 隔离原始main
  • external
  • 中发生的所有提交归入main

首先,隔离原始main

好像你可能在自己的存储库中有external

如果不是,只要原始main提交设置为创建external/main子目录的提交的父级,就可以从main存储库中检索它。这方面的一个例子是Git Book Subtree Merging page

中概述的流程

提交可以找到引入子树的地方in this answer

然后,这只是抓住作为main基础的整组提交并从中创建存储库的问题。


对于第二个,external 中发生的所有提交带入exteral/main

您已经隔离了包含main子文件夹中的更改的提交,但正如您所声明的那样,它不包含原始的git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter main -- --all 提交。

filter-branch

这是因为read-tree只会检查特定子目录位置中的文件,而不知道如何处理更复杂的操作,例如创建子目录的filter-branch

main/external操作之后,您将收到一组提交,其中包含filteredMain中发生的所有更改。让我们假设可以在main分支中达到这组提交。

由于内容已从子目录移动到根目录,因此文件的位置现在与main存储库中的内容相同。这将允许两个树连接。由于这两棵树,filterBranch的主分支和rebase没有共同的历史记录,所以可以通过# in the main repository # bring the external repository and get the branch git remote add external /path/to/external git fetch external filteredMain git checkout filteredMain # We need the first commit of this tree for the rebase command firstCommit=$(git rev-list --max-parents=0 HEAD) # run the rebase git rebase --onto master $firstCommit filteredMain 重播提交的更改来加入它们。

filteredMain

在此之后,external/main分支应该包含mastermain存储库中原始{{1}}分支顶部重播的所有更改。