在两个或多个rails应用程序之间共享代码… git子模块的替代方案?

我们有两个独立的rails_app, foo/bar/ (有很好的理由分开)。 它们都依赖于common/文件夹中的某些模型等,目前与foobar平行。

我们当前的svn设置使用svn:externals来共享common/ 。 本周末我们想试试git。 经过大量研究,似乎解决这个问题的“犹太教”方法是使用git submodule 。 在将foobarcommon分离到单独的存储库之后我们得到了这个工作,但随后实现了所有附加的字符串 :

  1. 在提交父级之前始终提交子模块。
  2. 在推送父模板之前始终按下子模块。
  3. 在提交之前,确保子模块的HEAD指向分支。 (如果您是bash用户,我建议使用git-completion将当前分支名称放在提示符中。)
  4. 切换分支或拉动更改后,始终运行’git submodule update’。

所有这些问题比addcommitpush更复杂。 我们正在寻找更简单的方法来共享git中的common 。 这个家伙似乎已经成功使用git subtree扩展,但与标准gitand不同,看起来仍然不那么简单。

鉴于我们的项目结构,这是我们能做的最好的吗? 我对rails plugins / engine知之甚少,但这似乎是一种可能的RoR-ish方式来共享库。

提前致谢。

我认为git子模块系统比svn有很大的优势:外部或符号链接(这也使得它们更难以使用):为每个超级项目版本存储实际的子模块版本。 因此,在破坏向后兼容性的子模块中进行更改是非常安全的:可以使用正确的子模块版本检出任何版本的超级项目,因为超级项目将包含对正确子模块代码的引用。 您还可以维护子模块的两个分支(例如,v1.0.x和v2.0.x),并在不同项目中使用不同的分支而不会出现问题。

所以我认为使用子模块确实是值得的,即使它们有点复杂。 Git 1.7在这方面有一些重大改进,例如git status现在表示子模块中未提交的修改,所以你可能不会忘记先提交子模块。 一个好的GUI也可能是一个帮助(我有一个小宠物项目,见这里 )。

如果你真的不想关心子模块版本(你永远不会在公共代码中进行向后不兼容的更改),那么我也建议使用符号链接。 虽然提交和获取并不比子模块容易得多……

我倾向于选择符号链接到子模块。

1)在3个单独的回购中有foobar和公共代码( common )。

2)在foo目录中,根据需要添加一个到common的符号链接。

 $ cd foo
 $ ln -s / path / to / common lib / common

3)检查链接。

 $ git add lib / common
 $ git commit

4)重复bar

这利用了git尊重符号链接并存储目标位置(而不是跟随链接)的事实。

当然,期望您始终如一地使用相同的目标路径。 我通过不检查符号链接来解决这个问题,并在每个项目中添加一个README.setup文件,提醒我在初始化时添加必要的符号链接。 拥有执行此类初始化的devsetup.sh在这里也很有用。

IMO,这比子模块更好。

一个插件是完全可行的方式,如果你最终在两个以上的项目中使用它或对公众有用,可能值得努力使它成为一个gem。

这是一个很好的资源

http://nubyonrails.com/articles/the-complete-guide-to-rails-plugins-part-i

更重要的是……

http://nubyonrails.com/articles/the-complete-guide-to-rails-plugins-part-ii

最后,你将有三个git存储库,一个用于foo ,一个用于bar ,一个用于插件

然后在每个项目中,您可以将数据保存到数据中

./script/plugin install --force git://github.com/path/to/plugin/repository

保持最新。

祝好运!

– 乔纳森

自1.7.11以来,Git子树是GIT的一部分,我写了一篇关于在Rails应用程序之间共享代码的文章: http : //igor-alexandrov.github.com/blog/2013/03/28/using-git-subtree-to -share码之间护栏的应用

简而言之:是的git-subtree工作并且效果很好!

如果你正在寻找一个插件,你也应该考虑制作一个gem。 它们在使用方面非常相似,但gem往往更容易使用,支持依赖管理,并且更容易与社区共享/分发。

Railscast的Ryan Bates有一个关于制作gem的精彩教程video,你可以在这里找到: http : //railscasts.com/episodes/135-making-a-gem

您可以使用公共代码创建存储库并将其克隆两次。 两个克隆都会成为foo和bar。 您仍然可以在两个项目的单独分支中开发公共代码,并将该分支推送到公共代码存储库。 要更新项目中的公共代码,您只需将公共分支合并到foo和bar的主分支中。

更新:您可以将其想象为具有三个分支的单个存储库:common,foo和bar。 您将在公共分支中拥有公共代码,并仅将项目特定代码添加到foo或bar分支。 现在你可以将这个存储库克隆两次作为foo和bar,并从它们中删除一个分支(来自bar存储库的branch foo和来自foo存储库的branch bar)。 然后你将从第一个存储库中删除foo和bar。 这将成为公共存储库。 最终结果与上述相同。

你可以做的最好的事情是为你的公共库,甚至是一个gem创建一个插件,这样你就可以很好地更新/分发它。