19

我一直在使用 git-subtree 扩展(https://github.com/apenwarr/git-subtree)来管理我们主项目中的子项目。除了当我尝试从我们的主项目中拆分对子项目所做的更改时它失败之外,它正在做我想要的事情。

例如,早些时候我做过

git subtree add -P Some/Sub/Dir --squash git@gitserver:lib.git master

在我们的主项目中将库代码引入 Some/Sub/Dir。这里的一切都很好,所以我将我的更改推送到我们的中心主项目裸 git repo。然后我决定在 Some/Sub/Dir 中更改我的本地版本的 lib,提交它,然后将其拆分以将其推回 lib.git 存储库

git subtree split -P Some/Sub/Dir -b some_branch

一切都按预期工作。不再需要我删除的 repo 的本地副本。

从我们的中央仓库克隆了一个新的仓库副本后,我对 Some/Sub/Dir 中的 lib 进行了一些更改,并决定将这些更改拆分出来并将它们推送回 lib.git 存储库。我尝试使用与以前相同的子树拆分命令,但是这次我最终得到以下输出:

1/      3 (0)
2/      3 (1)
3/      3 (1)
fatal: bad object d76a03f0ec7e20724bcfa253e6a03683211a7bb1

d76a03f0ec7e20724bcfa253e6a03683211a7bb1 来自我添加子树时:

commit 43b3eb7d69d5eb64241eddb12e5bd74fd0215083
Author: Ian Bond <ibond@onezero.com>
Date:   Fri Apr 22 15:06:50 2011 -0400

    Squashed 'Subtree/librepoLib/' content from commit d76a03f

    git-subtree-dir: Subtree/librepoLib
    git-subtree-split: d76a03f0ec7e20724bcfa253e6a03683211a7bb1

这实际上是指 lib.git 存储库中的提交。


我能够拼凑起来的(我是一个 git noob,所以我可能是错的,忽略了某些东西,或者在这里使用了不正确的术语),'git subtree add --squash' 将带来整个历史将远程 lib.git 存储库放入当前存储库,将其压缩为单独的提交,然后将该提交添加到工作分支中。lib.git 提交历史保留在当前存储库中,但是它们是悬空提交,因为除了通过 squash 提交的文本之外,它们实际上并没有被引用。只要那些悬空提交仍然存在,git-subtree 就可以使用它们来执行拆分,但是由于推送或拉取不包含悬空对象(或者如果我运行 gc 并完全修剪悬空对象),那些悬空提交就会丢失并且git-subtree 不再具有执行拆分所需的信息。

我添加了一个脚本,可以完全重现我遇到的问题。


我的问题是:

1)我可以做些什么来处理现有的情况,我现在有子树,我想合并回它们的原始仓库,但不再有任何类型的历史将它们链接在一起。我目前的想法是做类似的事情:

git subtree split -P Some/Sub/Dir 43b3eb7^.. --ignore-joins -b splitBranch

拆分自“git subtree add”以来的所有历史记录并将其合并回原始存储库(幸运的是,自添加以来没有任何更改)。这是最好的方法吗?关于我应该如何执行合并的任何建议?

2)我能做些什么来让 git-subtree 按预期工作吗?我相信如果我在 'git subtree add' 上省略 --squash 参数,那么一切都会正常工作,但这会导致一堆不相关的历史记录被注入到我的 repo 中。有没有办法保留所需的提交(最好不保留图书馆的整个历史)?

4

2 回答 2

15
于 2011-04-23T09:18:05.027 回答
1

@Chris Johnsen 的回答非常正确,它解释了为什么拆分在克隆中起作用而不是拉动情况。

对于问题中提供的解决方法并在@Chris Johnsen 的回答的脚注 2 中进行了解释,我可以确认git subtree split -P Some/Sub/Dir -b splitBranch --ignore-joins并且git subtree split -P Some/Sub/Dir -b splitBranch 43b3eb7..实际上产生了相同的提交和相同的分支,这可以反映在本地存储库中所做的修改,但不能推送到原始 repoLib repo,因为它们没有共同的访问器,即使 git diff 显示d76a03f0ec7e2并且43b3eb7d69d是相同的。

因此,为了使子树推送在拉取情况下工作,必须添加并获取原始 repoLib 远程 repod76a03f0ec7e2以生成与原始 repoLib 具有共同访问器的分支。

原来的重现脚本在linux下不能流畅运行,这里是一个新的: http: //pastebin.com/3NAQKEz9

于 2012-03-08T15:41:47.107 回答