使用Git跟踪第三方代码 [英] Tracking 3rd party code with Git

查看:114
本文介绍了使用Git跟踪第三方代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎无法理解我找到的不同解决方案,并研究了
用于跟踪外部代码。更别提理解如何将它们应用到
我的用例中了......



你们会如此善待我们解决这个问题并帮助我b $ b我的具体用例是什么?具体问题是什么才是最好的解决方案? (我不会试图概括我的
问题,因为我可能会对某些东西做出错误的假设,特别是
,因为我对这些都很新颖......)

我正在Django(Python中的一个Web框架)中构建一个网站。现在,
有很多第三方插件可用于Django
(Django称之为'apps'),您可以将它们放在项目中。某些
这些应用程序可能需要一点修改才能像I
想要它们一样工作。但是如果你开始修改第三方代码,那么
会引入更新代码的问题,当新版本出现
并同时保留你的本地修改时。



所以,我在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 copy'd
之一是/ vendor / django-apps / blog-app中的标签。说它是v1.2。还有
,我现在想把我的版本升级到v1.3。正如你可以
看到的,我已经更新/ vendor / django-apps / blog-app / current
(使用svn_load_dirs)和'tagged'(svn copy)它作为
/ vendor / Django的应用程序/博客应用程序内/ 1.3。
现在我可以通过svn合并/vendor/django-apps/blog-app/1.2和
/ vendor / django-之间的更改
来更新/ trunk / apps / blog-app。 apps / blog-app / 1.3在/ trunk / apps / blog-app上。这将
保留我的本地更改。
(对于此流程未知的人,在
Subversion手册中描述:
http://svnbook.red-bean.com/en/1.5/svn.advanced.vendorbr.html


现在我想在Git中完成整个过程。我怎么做到这一点?



让我重新提出要求:


  • 我必须能够将外部代码放置在树中的任意位置
  • 我必须能够修改外部代码并在我的系统中保留(提交)这些
    修改Git Repos

  • 我必须能够轻松更新外部代码,如果发布新的
    版本,同时保留我的更改



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


  • 最好我想这样做没有像svn_load_dirs这样的东西。 I
    认为应该可以从他们的仓库直接跟踪应用程序及其更新
    (大多数第三方Django应用程序保存在
    Subversion中)。为我提供了在发布之间查看
    个人提交消息的额外好处。由于我可以处理很多小的提交
    而不是由svn_load_dirs创建的一个虚假提交,因此修复合并
    冲突更容易。
    我认为人们可以在svn:externals中做到这一点,但我有
    从来没有用过...



可以使用这两种方法的组合的解决方案将是
更可取,因为可能有应用程序开发人员不使用源代码管理或不使用源代码控制公开发布。
(这意味着类似svn_load_dirs的行为和从
Subversion reposity(或另一个Git)直接跟踪)

我认为我要么必须使用子树,子模块,rebase,分支......或者这些的组合,但是如果我知道哪一个或哪些是如何做到的话,就会击倒我:S

<我很热切地等待着你的回应!请在回复时尽可能详细地填写
,因为我已经很难理解在线发现的其他
示例。



在此先感谢 p>

解决方案

这里有两个单独的问题:


  1. 如何维护远程项目的本地分支,以及如何在自己的树中保存远程项目的副本?



  2. 问题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,一个选项是使用子模块。为此,cd进入你的主项目,然后运行:

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

    如果我使用git submodules,我需要知道吗?

    有时您可能会发现git子模块有点棘手。请注意以下几点:


    1. 在提交父代之前始终提交子模块。

    2. 在推送父代之前,始终推送子模块。

    3. 确保子模块的HEAD在提交之前指向分支。 (如果你是bash用户,我推荐使用 git )

    4. 总是在切换分支或提交更改后运行'git submodule update'。
    5. / li>

    您可以通过使用由我的同事创建的别名在某种程度上解决(4):

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

    ...然后运行:

      git pull-recursive 

    如果git子模块非常复杂,有什么优势?


    1. 您可以签出主项目而不检查从子模块中取出。当子模块非常庞大时,这非常有用,并且在某些平台上不需要它们。

    2. 如果您有经验的git用户,可能会有多个子模块分支,并且链接他们用你的主项目的不同分支。

    3. 有一天,有人可能会修正git子模块以更优雅地工作。子模块实施的最深部分实际上相当不错;它只是上层工具被打破。

    git子模块不适合我。接下来是什么?



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



    如果上游存储库使用Subversion,该怎么办?

    如果你知道如何使用git svn,这很简单:

      git svn clone -s https://示例。 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
    code>

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


    I can't seem to grok the different solutions I've found and studied for tracking external code. Let alone understand how to apply them to my use case...

    Would you guys be so kind to shed some light on this and help me with my specific use case? What would be the best solution for the following, concrete problem? (I'm not gonna attempt to generalize my problem, since I might make wrong assumptions about stuff, especially since I'm so new with all this...)

    I'm building a website in Django (a web framework in Python). Now, there are a lot of 3rd party plugins available for use with Django (Django calls them 'apps'), that you can drop in your project. Some of these apps might require a bit of modification to get working like I want them. But if you start making modifications to 3rd party code you introduce the problem of updating that code when newer versions appear AND at the same time keeping your local modifications.

    So, the way I would do that in Subversion is by using vendor branches. My repository layout would look like this:

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

    In this case /trunk/apps/blog-app would have been svn copy'd of one of the tags in /vendor/django-apps/blog-app. Say that it was v1.2. And that I now want to upgrade my version in trunk to v1.3. As you can see, I have already updated /vendor/django-apps/blog-app/current (using svn_load_dirs) and 'tagged' (svn copy) it as /vendor/django-apps/blog-app/1.3. Now I can update /trunk/apps/blog-app by svn merge'ing the changes between /vendor/django-apps/blog-app/1.2 and /vendor/django-apps/blog-app/1.3 on /trunk/apps/blog-app. This will keep my local changes. (for people unknown with this process, it is described in the Subversion handbook: http://svnbook.red-bean.com/en/1.5/svn.advanced.vendorbr.html)

    Now I want to do this whole process in Git. How can I do this?

    Let me re-iterate the requirements:

    • I must be able to place the external code in an arbitrary position in the tree
    • I must be able to modify the external code and keep (commit) these modifications in my Git repos
    • I must be able to easily update the external code, should a new version be released, whilst keeping my changes

    Extra (for bonus points ;-) ):

    • Preferably I want to do this without something like svn_load_dirs. I think it should be possible to track the apps and their updates straight from their repository (most 3rd party Django apps are kept in Subversion). Giving me the added benefit of being able to view individual commit messages between releases. And fixing merge conflicts more easily since I can deal with a lot of small commits instead of the one artificial commit created by svn_load_dirs. I think one would do this with svn:externals in Subversion, but I have never worked with that before...

    A solution where a combination of both methods could be used would be even more preferable, since there might be app developers who don't use source control or don't make their repos available publicly. (Meaning both svn_load_dirs-like behavior and tracking straight from a Subversion reposity (or another Git))

    I think I would either have to use subtrees, submodules, rebase, branches, ... or a combination of those, but smack down me if I know which one(s) or how do to it :S

    I'm eagerly awaiting your responses! Please be as verbose as possible when replying, since I already had a hard time understanding other examples found online.

    Thanks in advance

    解决方案

    There are two separate problems here:

    1. How do you maintain local forks of remote projects, and
    2. How do you keep a copy of remote projects in your own tree?

    Problem 1 is pretty easy by itself. Just do something like:

    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
    

    You can then work on your forked repository normally. When you want to merge in upstream changes, run:

    git pull upstream master
    

    As for problem 2, one option is to use submodules. For this, cd into your main project, and run:

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

    If I use git submodules, what do I need to know?

    You may find git submodules to be a little bit tricky at times. Here are some things to keep in mind:

    1. Always commit the submodule before committing the parent.
    2. Always push the submodule before pushing the parent.
    3. Make sure that the submodule's HEAD points to a branch before committing to it. (If you're a bash user, I recommend using git-completion to put the current branch name in your prompt.)
    4. Always run 'git submodule update' after switching branches or pulling changes.

    You can work around (4) to a certain extent by using an alias created by one of my coworkers:

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

    ...and then running:

    git pull-recursive
    

    If git submodules are so tricky, what are the advantages?

    1. You can check out the main project without checking out the submodules. This is useful when the submodules are huge, and you don't need them on certain platforms.
    2. If you have experienced git users, it's possible to have multiple forks of your submodule, and link them with different forks of your main project.
    3. Someday, somebody might actually fix git submodules to work more gracefully. The deepest parts of the submodule implementation are actually quite good; it's just the upper-level tools that are broken.

    git submodules aren't for me. What next?

    If you don't want to use git submodules, you might want to look into git merge's subtree strategy. This keeps everything in one repository.

    What if the upstream repository uses Subversion?

    This is pretty easy if you know how to use git svn:

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

    Then set up a local tracking branch in git.

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

    Then, to merge from upstream, run:

    git svn fetch
    git merge trunk
    

    (I haven't tested this code, but it's more-or-less how we maintain one submodule with an upstream SVN repository.)

    Don't use git svn rebase, because it will make it very difficult to use git submodule in the parent project without losing data. Just treat the Subversion branches as read-only mirrors of upstream, and merge from them explicitly.

    If you need to access the upstream Subversion repository on another machine, try:

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

    You should then be able to merge changes from upstream as before.

    这篇关于使用Git跟踪第三方代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆