使用Git跟踪第三方代码

时间:2009-03-24 13:28:05

标签: git

我似乎无法理解我发现和研究的不同解决方案 用于跟踪外部代码。更别说了解如何应用它们 我的用例...

你们是否会如此善意地阐明这一点并帮助我 我的具体用例?什么是最好的解决方案 以下,具体问题? (我不会试图概括我的 问题,因为我可能会对东西做出错误的假设,尤其是 因为我对这一切都很新......)

我正在Django构建一个网站(Python中的Web框架)。现在, 有很多第三方插件可供Django使用 (Django将它们称为“应用程序”),您可以放入项目中。一些 这些应用程序可能需要一些修改才能像我一样工作 要他们。但是如果你开始修改第三方代码你 介绍在出现较新版本时更新该代码的问题 并同时保留您的本地修改。

所以,我在Subversion中这样做的方法是使用供应商分支。 我的存储库布局如下所示:

/trunk
  ...
  /apps
    /blog-app
  ...
/tags
  ...
/branches
  ...
/vendor
  /django-apps
    /blog-app
      /1.2
      /1.3
      /current
    /other-app
      /3.2
      /current

在这种情况下,/ trunk / apps / blog-app将被svn复制其中一个 / vendor / django-apps / blog-app中的标签。说它是v1.2。和 我现在想将我的版本在trunk中升级到v1.3。尽你所能 看,我已经更新/ vendor / django-apps / blog-app / current (使用svn_load_dirs)和'tagged'(svn copy)将其作为 /vendor/django-apps/blog-app/1.3。 现在我可以通过svn merge更改/ trunk / apps / blog-app来更新 在/vendor/django-apps/blog-app/1.2和。之间 / trunk / apps / blog-app上的/vendor/django-apps/blog-app/1.3。这将 保持我的本地变化。 (对于这个过程中未知的人,它在 颠覆手册: http://svnbook.red-bean.com/en/1.5/svn.advanced.vendorbr.html

现在我想在Git中完成整个过程。我怎么能这样做?

让我重新讨论要求:

  • 我必须能够将外部代码放在树中的任意位置
  • 我必须能够修改外部代码并保留(提交)这些代码 我的Git回购中的修改
  • 我必须能够轻松更新外部代码,应该是新的 版本发布,同时保留我的更改

额外(奖励积分;-)):

  • 我最好不要使用像svn_load_dirs这样的东西。一世 认为应该可以跟踪应用程序及其更新 直接从他们的存储库(大多数第三方Django应用程序保留在 颠覆)。给我能够查看的额外好处 发布之间的单独提交消息。并修复合并 因为我可以处理很多小提交,所以更容易发生冲突 而不是由svn_load_dirs创建的一个人为提交。 我想在Subversion中使用svn:externals可以做到这一点,但我有 从来没有与之合作......

可以使用两种方法的组合的解决方案 更优选,因为可能有应用程序开发人员不这样做 使用源代码管理或不公开他们的回购。 (意思是svn_load_dirs之类的行为和直接跟踪 Subversion reposity(或其他Git))

我想我要么必须使用子树,子模块,rebase,分支......或者它们的组合,但是如果我知道哪一个或如何做的话就打倒我:S

我急切地等待你的回复!请尽可能详细 回答时,因为我已经很难理解其他人了 在线发现的例子。

提前致谢

4 个答案:

答案 0 :(得分:27)

这里有两个不同的问题:

  1. 如何维护远程项目的本地分支和
  2. 如何在自己的树中保留远程项目的副本?
  3. 问题1本身很容易。做一些像:

    git clone git://example.com/foo.git
    cd foo
    git remote add upstream git://example.com/foo.git
    git remote rm origin
    git remote add origin ssh://.../my-forked-foo.git
    git push origin
    

    然后,您可以正常处理分叉存储库。如果要合并上游更改,请运行:

    git pull upstream master
    

    对于问题2,一个选项是使用子模块。为此,请进入主项目,然后运行:

    git submodule add ssh://.../my-forked-foo.git local/path/for/foo
    

    如果我使用git子模块,我需要知道什么?

    你可能会发现git子模块有时候有点棘手。以下是一些需要注意的事项:

    1. 在提交父级之前始终提交子模块。
    2. 在推送子模块之前始终按下子模块。
    3. 确保子模块的HEAD在提交之前指向分支。 (如果您是bash用户,我建议您使用git-completion将当前分支名称放在提示中。)
    4. 在切换分支或提取更改后,始终运行'git submodule update'。
    5. 您可以使用我的同事之一创建的别名在一定程度上解决(4):

      git config --global alias.pull-recursive '!git pull && git submodule update --init'
      

      ...然后运行:

      git pull-recursive
      

      如果git子模块如此棘手,有什么好处?

      1. 您可以在不查看子模块的情况下查看主项目。当子模块很大,并且在某些平台上不需要它们时,这很有用。
      2. 如果您有经验的git用户,则可以使用子模块的多个分叉,并将它们与主项目的不同分支链接。
      3. 有一天,有人可能会修复git子模块以更优雅地工作。子模块实现中最深的部分实际上非常好;它只是破坏的上层工具。
      4. git子模块不适合我。下一步是什么?

        如果您不想使用git子模块,可能需要查看git merge's subtree strategy。这将所有内容保存在一个存储库中。

        如果上游存储库使用Subversion会怎样?

        如果您知道如何使用git svn:

        ,这很容易
        git svn clone -s https://example.com/foo
        cd foo
        git remote add origin ssh://.../my-forked-foo.git
        git push origin
        

        然后在git中设置本地跟踪分支。

        git push origin master:local-fork
        git checkout -b local-fork origin/local-fork
        

        然后,要从上游合并,请运行:

        git svn fetch
        git merge trunk
        

        (我没有测试过这段代码,但是我们维护一个带有上游SVN存储库的子模块的方式或多或少。)

        不要使用git svn rebase,因为它会使得在父项目中使用git子模块非常困难而不会丢失数据。只需将Subversion分支视为上游的只读镜像,并明确地从它们合并。

        如果您需要访问另一台计算机上的上游Subversion存储库,请尝试:

        git svn init -s https://example.com/foo
        git svn fetch
        

        然后,您应该能够像以前一样合并来自上游的更改。

答案 1 :(得分:3)

我环顾四周,偶然发现了Braid。它是一个在Git中自动化供应商分支的工具。它可以使用Git或SVN repos。

通过浏览源我发现它使用了子树策略。似乎让它变得非常简单!而且,它似乎满足了我的所有要求!

在我进入并使用它之前:这里有没有人有过Braid的经验?如果有的话,我想了解可能的缺点。另外,如果你没有使用过Braid,但是在Git中有一些专业知识,那你一眼就能想到什么呢?

答案 2 :(得分:1)

我使用git子模块跟踪我的Django项目中的可重用应用程序,但从长远来看它有点混乱。

部署很麻烦,因为你无法使用git archive获得整个树(带子模块)的干净存档。有一些技巧,但没有什么是完美的。 此外,子模块更新机制对于处理子模块分支并不好。

您可能需要查看virtualenv和pip,因为他们最近有一些改进才能使用外部存储库。

pip:http://pip.openplans.org/ 并使用pip / virtualenv:http://www.b-list.org/weblog/2008/dec/15/pip/

答案 3 :(得分:0)

我认为我对另一个问题的回答为这里描述的问题提供了一个很好的解决方案,没有进入子模块的地狱(我已经尝试了,但是甚至没有接近svn:我使用的外部到)

不过,请看看这个答案: Do you version control the invidual apps or the whole project or both?

在再次删除我的答案之前,我不知道我无法将自己的答案复制到另一个问题,即使我确信它是有用的答案。对不起,但试试这个答案,这真的是一个很好的解决方案。 所以我希望我可以将我自己的anser引用到另一个问题上。