如何移除Git子树合并?

3
我有一个项目,依赖于另外两个子项目,这两个子项目是使用子树合并策略合并的(如这里那里所述)。一段时间后,我发现其中一个子项目在当前项目中有自己的生命周期,因此我想将其与原始项目解耦,但我不知道如何实现。基本上,我注意到子项目在.git/config文件中列出,因此我想知道是否仅从该文件中删除即可。
根据Jakub的回答/问题,我将尝试向我的问题添加更多细节。我正在处理的ProjectA项目依赖于LibraryB库,它有自己的git存储库和生命周期。在设置ProjectA时,我使用了子树合并技术来添加对LibraryB的依赖项(步骤与VonC幸运地添加的链接中描述的步骤完全相同)。现在,ProjectA需要对LibraryB进行一些自定义更改,这些更改不足以推回LibraryB存储库。因此,我想将ProjectA中的LibraryB与其主存储库解耦(通过解耦,我意味着ProjectA中的LibraryB将无法从其主存储库进行更新,并且将仅在ProjectA中跟踪其自己的历史记录)。
更多细节:在检查我的ProjectA存储库后,我发现只有对LibraryB存储库的引用存在于ProjectA/.git/config文件中,格式如下:
[remote "gaelib"]
    url = ../libraries/gaelib
    fetch = +refs/heads/*:refs/remotes/gaelib/*

在包含LibraryB的ProjectA项目目录中(../libraries/gaelib),没有其他与git相关的信息。


您似乎忘记包含脚注[1]的链接。 - foxxtrot
4个回答

4

看起来你想要“撤销”子树合并并将其提交回上游。使用git subtree split命令可以实现此操作。


3
我不太理解。如果你使用子树合并方式将libraryB包含在projectA存储库中,你不需要进行任何解耦操作。你已经拥有了所需的全部内容:
  • 你可以从libraryB存储库中提取更新,这很好。

  • 你可以在projectA存储库中提交对libraryB的更改。这些更改将仅保留在本地存储库中,除非你决定将它们推送/拉取到另一个存储库。它们仅是projectA历史记录的一部分,并且不会自动传播到libraryB存储库。

这正是子树合并方法的整个目的,与子模块方法相反。

2

是的,请从配置文件中移除指向LibraryB的远程指针。这将防止任何人在使用您的存储库时不经意地从远程更新您的本地代码。

您无需执行其他操作--您只需不再从LibraryB存储库拉取或推送即可。


我会克隆这个仓库并尝试一下,以确保我没有搞砸它。我会回复帖子的。 - alexpopescu

0

如果你想要维护自己的LibraryB版本,你有几个选择:

  • 你可以将LibraryB作为项目的固有部分:只需在配置文件中删除或注释掉[remote "LibraryB"]部分,并对LibraryB进行更改即可。

    缺点是更难为LibraryB的规范(第三方)版本发送补丁。

  • 您可以继续使用“子树”合并,但不是从LibraryB的规范版本,而是从您自己的克隆(fork)库中。您将更改remote.LibraryB.url以指向您的本地版本,并且您的本地版本将是原始LibraryB的克隆。请注意,您应该合并自己的分支,而不是规范LibraryB的远程跟踪分支。

    缺点是您必须维护单独的克隆,并记住您对LibraryB的自己的更改(至少那些通用的)必须在LibraryB的分支中进行,而不是直接在ProjectA内部进行。

  • 您可能希望从“子树”合并转移到使用submoduletutorial)实现更多分离的方式。在这种情况下,您将拥有LibraryB的单独存储库(fork),但它将位于ProjectA的工作区内;ProjectA中的提交将具有指向LibraryB存储库中提交的指针,而不是具有LibraryB树的子树。然后,如果您不想关注LibraryB的开发,只需简单地不使用“git submodule update”(并且可能为了安全起见注释掉或删除对规范版本LibraryB的链接)。

    这样做的优点是易于将您的改进发送到规范LibraryB,并且使您在ProjectA的工作区内进行更改。缺点是必须学习稍微不同的工作流程。

    此外还存在如何从“子树”合并转移到子模块的问题。你可以:

    • 通过在超级项目工作库中的子项目子树中创建git存储库(即在适当的子目录中执行“git init”+适当的“git submodule init”等),从子树合并移动到子模块。这意味着您将拥有直到某个历史点的“子树”,以及后来的子模块。
    • 使用git filter-branch重写历史,以替换子树合并为子模块。这样做的缺点是重写历史(如果有人基于当前历史进行工作,则不可取),而好处是“干净的开始”。 或者您可以等待一段时间,“git submodule split”(git邮件列表上的线程)进入git...
      不幸的是,Splitting a git repository博客文章返回“找不到主机”

我希望这个版本能解决你的问题。

免责声明:我个人没有使用过子树合并、子模块或git-filter-branch。


我已经尽力提供了尽可能多的细节。感谢您尝试回答我的问题。 - alexpopescu
扩展的答案是否更好地解决了您的问题? - Jakub Narębski

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