我似乎无法理解我发现和研究的不同解决方案 用于跟踪外部代码。更别说了解如何应用它们 我的用例...
你们是否会如此善意地阐明这一点并帮助我 我的具体用例?什么是最好的解决方案 以下,具体问题? (我不会试图概括我的 问题,因为我可能会对东西做出错误的假设,尤其是 因为我对这一切都很新......)
我正在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中完成整个过程。我怎么能这样做?
让我重新讨论要求:
额外(奖励积分;-)):
可以使用两种方法的组合的解决方案 更优选,因为可能有应用程序开发人员不这样做 使用源代码管理或不公开他们的回购。 (意思是svn_load_dirs之类的行为和直接跟踪 Subversion reposity(或其他Git))
我想我要么必须使用子树,子模块,rebase,分支......或者它们的组合,但是如果我知道哪一个或如何做的话就打倒我:S
我急切地等待你的回复!请尽可能详细 回答时,因为我已经很难理解其他人了 在线发现的例子。
提前致谢
答案 0 :(得分:27)
这里有两个不同的问题:
问题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子模块有时候有点棘手。以下是一些需要注意的事项:
您可以使用我的同事之一创建的别名在一定程度上解决(4):
git config --global alias.pull-recursive '!git pull && git submodule update --init'
...然后运行:
git pull-recursive
如果git子模块如此棘手,有什么好处?
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引用到另一个问题上。