【问题标题】:git: can I subtree merge just a subpath of a repository?git:我可以子树合并存储库的子路径吗?
【发布时间】:2010-11-13 13:07:24
【问题描述】:

我有遥控器 Foo 和 Bar。 Foo 是一个有很多目录的 Web 应用程序,其中相关的是 /public,其中包含各种文件和其他目录。

Bar 是一组库和前端没有使用的东西,因此它应该放在 Foo 中的 /public/bar 中。 Foo 那里没有文件。

无论是子模块还是子树合并,这都是小菜一碟。不过……

Bar 的树很乱,它有各种预制作文件,如 PSD 和 FLA,其中唯一真正有用的部分是其 /www/tools 中的内容。

所以,我想做的是将 Bar 的 /www/tools 合并到 Foo 的 /public/bar,并假装 Bar 的树的其余部分甚至不存在。

可以吗?

(我想这与您从最初将您的项目合并为子树的项目合并的方式非常相似。我也不知道该怎么做。)

【问题讨论】:

    标签: git merge version-control subtree


    【解决方案1】:

    我已使用以下命令成功完成此操作(针对您的场景重写)。

    $ git remote add Bar /path/to/bar
    $ git merge -s ours --no-commit Bar/master
    $ git read-tree --prefix=public/bar -u Bar/master:www/tools/
    

    严重警告!我仍在研究如何从 Bar 获取/合并。这将只引入一次所有内容。

    我目前合并更改的方式是这样的:

    $ get fetch Bar
    $ git pull -X subtree=public/bar Bar master
    

    这会给你留下冲突,说大量文件已被删除,你可以先git rm他们然后git commit

    我当然愿意接受有关更好地进行更改的建议。

    由于这是一个旧线程,我应该补充一点,我正在运行 Git 1.7.9。

    【讨论】:

    • 这样做的一个问题是它会引入分支的所有提交,而不仅仅是那些影响子目录的提交。有办法解决吗?
    • 如果您要合并多个存储库,您可能需要通过 --allow-unrelated-histories 进行合并。
    【解决方案2】:

    为此尝试使用git subtree。它允许您将项目的子树提取到另一个项目中,然后您可以将其合并到您的项目中。

    【讨论】:

    【解决方案3】:

    编辑:我突然想到你可以用git merge --no-commit 做到这一点。这将尝试合并,即使不冲突,它也会在提交之前停止。此时,您可以删除所有不需要的垃圾(包括在必要时恢复冲突文件)并创建仅包含所需子树的合并提交。

    原答案:

    您确实可以为此使用 filter-branch 。大纲:

    克隆您的源代码库:

    git clone --bare /path/to/bar /path/to/bar_clone
    

    使用裸克隆将节省您创建工作目录的时间和空间。

    接下来,在克隆上使用 filter-branch:

    git filter-branch --index-filter 'git rm -rf <unwanted files/directories>' -- --all
    

    --all 让它知道你想使用所有的 refs,而不仅仅是当前的 HEAD。您现在将拥有一个仅包含所需子目录以及与其关联的所有历史记录的存储库。

    注意:抱歉,除了您想要的内容之外,我不知道删除所有内容的真正简单方法。您必须小心使用通配符,因为您不想破坏任何 git 目录。这里有一些可行的方法,但速度较慢,尤其是在您有很多文件的情况下:

    git filter-branch --index-filter 'git rm -f `git ls-files | grep -v ^www/tools`' -- --all
    

    无论如何,无论您如何管理要删除的文件列表,您都可以继续进行子树合并,从bar_clone 拉入foo

    【讨论】:

      【解决方案4】:

      我认为这不能使用合并本身来完成,但这些步骤可能会奏效,至少就最终产品而言。第一:

      % git fetch Bar
      

      这会从 Bar 存储库中获取最新的提交,但不会尝试合并它们。它在 .git/FETCH_HEAD 中记录提交的 SHA

      % cat .git/FETCH_HEAD
      b91040363160aab4b5dd46e61e42092db74b65b7                branch 'Bar' of ssh://blah...
      

      这显示来自远程分支的最新提交的 SHA 标识符是什么。

      % git checkout b91040363160aab4b5dd46e61e42092db74b65b7 www/tools
      

      这会将 www/tools 中的文件副本用于获取的提交,并覆盖工作树中的内容。然后,您可以像往常一样将这些更改提交到本地存储库。生成的提交不会对它的来源有任何引用,但它至少应该让你的存储库包含你想要的文件版本。

      【讨论】:

      • 是的,我会更乐意保留历史。也许可以用 filter-branch 做点什么。
      • 1.) 您可以使用“git checkout FETCH_HEAD www/tools” 2.) 您可能可以使用“git checkout --merge FETCH_HEAD www/tools” 3.) 在工作目录中记录所需状态后,您可以通过在 git-commit 之前将 FETCH_HEAD 写入 .git/MERGE_HEAD 来手动创建合并
      • 啊,我知道必须有更好的方法来完成 FETCH_HEAD 部分
      【解决方案5】:

      我建议使用 subtree 两次——一次提取所有 /www/tools,一次提取 /public——听起来 /public 应该在它自己的仓库中,所以我建议你将 /public 推送到新的repo - 包含所有子树历史,然后将 /www/tools 的子树历史合并到新的 /public repo 中,并将其添加回 Foo 的子树。

      cd foo
      git subtree split --prefix=public --branch=new-shared-public --annotate='(split) '
      cd../bar
      git subtree split --prefix=www/tools --rejoin --branch=new-shared-www-tools --annotate='(split) '
      

      您的存储库中现在有两个新分支。一个带有公共的提交历史,另一个带有 www/tools。从这里开始我将省略cd

      创建您的新公共存储库(我假设这里是 github,但听起来您可能想在本地进行)并将您的子树推到那里: git checkout new-shared-public git push git@github.com:my_id/new-shared-repo.git HEAD:master

      然后将您的另一个分支合并到该分支中:

      git checkout new-shared-www-tools
      git remote add Foo git@github.com:my_id/new-shared-repo.git
      git merge -s ours --no-commit Bar/master
      

      虽然我已将 ours 指定为提交策略,但它可能(可能)并不重要。

      最后,在您执行合并并将其推送到新存储库后,返回到 Foo 存储库。从那里 Git rm 公共历史并将新的公共回购添加为子树:

      git subtree add --squash --prefix shared git@github.com:my_id/new-shared-repo.git master
      git subtree pull --squash --prefix shared git@github.com:my_id/new-shared-repo.git master
      git push
      

      【讨论】:

        猜你喜欢
        • 2013-09-03
        • 1970-01-01
        • 2014-05-30
        • 1970-01-01
        • 2023-03-28
        • 2014-07-09
        • 1970-01-01
        • 2013-03-03
        • 2011-09-19
        相关资源
        最近更新 更多