【问题标题】:Managing different Rails versions in different git branches with RVM使用 RVM 在不同的 git 分支中管理不同的 Rails 版本
【发布时间】:2011-09-13 08:58:03
【问题描述】:

我正在开发一个项目,该项目在 master 分支上的 Rails ~> 3.0 和另一个分支上运行 ~> 3.1

显然这两个分支需要不同的宝石。

您知道使用 RVM 处理这种情况的便捷方法吗?

我想到了几个选项,但没有一个是最佳的:

  • 使用gemsets我必须记得在每个git checkout之后手动切换gemset

  • 使用bundle package我必须跟踪vendor/bundle 目录

  • 这两种方法的混合甚至是不可能的,因为.bundle/config 没有被跟踪

  • 我可以写一个 git post-checkout 钩子,但这听起来有点老套(硬编码的分支名称等等)

我想不出更好的方法吗?

【问题讨论】:

  • 我知道这个问题有点老了。但我终于开始记下我使用的步骤,为 git 分支处理不同的 RVM gemsets。也许它可以帮助那些偶然发现这一点的人。 is.gd/pao3ZZ

标签: git rvm bundler


【解决方案1】:

当您切换到项目目录时,您将不再需要这样做。 RVM 1.8.1 默认重新启用此功能。 (我已在网站和 rvm 注释中添加了相关文档)

但是,由于这是目录中的 rvmrc 更改,并且 .rvmrc 中的更改不会被拾取,您可以通过执行“rvm reload”来强制它。 应该获取更改,但如果没有,则重新加载。

请将您在执行此操作后遇到的任何问题发送到https://github.com/wayneeseguin/rvm/issues

谢谢,

德丽尔·R·杜塞特

注意:在与 Wayne 交谈后,他通过 IRC 告诉我,他会建议您在 .bash_profile 中按照以下方式做一些事情来帮助您完成您想要的事情:

  git() { command git "$@" ; [[ -s .rvmrc ]] && . .rvmrc ; }

另外,如您所知,RVM 不会以任何形式或形式作为守护进程运行。因此,您最希望 RVM 做的事情肯定不会添加到 RVM 中。正如韦恩所说,这将是一种有趣的方式来弄乱某人的头! :)

这样想。虽然公认是做作的,但动作仍然是一样的。如果有人在您处理某事时更改了您下面的 rvmrc(另一个开发人员在 dir 上工作但不知道您是),或者某个流氓野兽入侵了您的系统并更改了您的 rvmrc,您认为他可能通过这样做以某种方式获得一些额外的特权。 (这可能在一个组控制的项目目录中,他通过另一个用户的帐户获得了访问权限,发现你在同一个组中,将你下面的 rvmrc 更改为他通过组权限设置的不同的 ruby​​+gemset多用户安装中的 RVM 组,并导致执行一些任意命令。进一步想象,您中,例如,wheel 组,您刚刚为 root 和减少授权的超时尚未完成。由于 rvmrc 实际上只不过是一个 bash 脚本,所以这并没有想象的那么远。所以最后,这会造成一个非常危险的环境,更不用说一个极其困难的情况了进行监视和控制。

【讨论】:

  • 必须记住rvm reload 有点重要,因为我还不如做一个rvm gemset use :)
  • rvm reload 的输入速度明显快于 rvm gemset use 1.9.2@rails31 所以我不接受它作为有效参数。但是,话虽如此,我将与韦恩交谈,看看当 PWD 中的 .rvmrc 发生更改时,预期的行为是什么。
  • 是的,它更快,但我的意思是您的解决方案只解决了问题的简单部分(节省击键)。必须记住在每个 git checkout 之后做某事是真正的问题。
  • 为什么?你只需使用 git 的钩子,比如 post-commit。由于 RVM 不是(也永远不会是)守护进程,人们通常使用 $project_dir/.git/hooks/post-commit 来导致这些类型的操作发生。虽然我确实意识到这不是您想要的确切解决方案,但它处理它的正确方法。请仔细阅读progit.org/book/ch7-3.html,它涵盖了这些钩子。另一个很有帮助的是goo.gl/Uv1Px
  • 你是对的,它可以设置为一个钩子——没想到。无论如何,在 git 中跟踪 .rvmrc 对我来说似乎是一个肮脏的解决方案(应用程序仓库本身不应该关心开发人员的本地环境)所以我不太热衷于采用这个解决方案。
【解决方案2】:

您可以在项目目录中创建一个 .rvmrc 文件并将其添加到 git 存储库。对于一个分支,.rvmrc 文件将包含类似

的行
rvm 1.9.3-head@rails30 --create

对于另一个分支,它将包含

rvm 1.9.3-head@rails31 --create

这样你最终会得到两个 gem 集(rails30 和 rails31)。另外不要忘记在您的 {home}/.rvmrc 中激活 .rvmrc 文件的自动执行(最新版本的 rvm 是必需的,请参阅 rvm 文档)。

【讨论】:

  • 请记住在您无意合并到具有不同 rvmrc 的分支上执行此操作,否则它将覆盖该分支的 rvmrc。
  • 我不想跟踪.rvmrc 文件。它们代表本地环境,不属于 VCS 恕我直言。
【解决方案3】:

我最终使用了以下git post-checkout 脚本。 在master 分支中,我使用了安装在$GEM_HOME 中的gems。在其他分支中,gems 本地安装到vendor/cache

#!/usr/bin/env bash

#set -x

git_rev() {
  ref=$(git symbolic-ref HEAD 2>/dev/null) || return
  echo ${ref#refs/heads/}
}

ref=$(git_rev)

case $ref in
  master)
    echo "removing .bundle/config"
    mv .bundle/config .bundle/config.no
    ;;
  *)
    if [ -f .bundle/config.no ] ; then
      echo "using vendor/cache"
      mv .bundle/config.no .bundle/config
    fi
    ;;
esac

【讨论】:

  • 这将是一个很好的评论。作为答案,它未能提供足够的细节来帮助下一个偶然发现这个问题的人。愿意提供任何其他详细信息吗?
【解决方案4】:

按照 morgler 的回答,如果您将 .rvmrc 签入到您的 git 项目中,您可以使用 git 完成将 git 分支名称添加到 .rvmrc gemset 名称中,以自动为每个分支创建 gemset,例如:

PROJECT_NAME="my_app"
RUBY_VERSION="ruby-1.9.2-p290"
GEMSET_NAME="${PROJECT_NAME}"
# if you have bash completion setup the way I do, you get a gemset for each git branch
if [ -f /usr/local/etc/bash_completion.d/git-completion.bash ]; then
  . /usr/local/etc/bash_completion.d/git-completion.bash;
  GEMSET_NAME="${PROJECT_NAME}-$(__git_ps1 '%s')";
fi
rvm --create "${RUBY_VERSION}@${GEMSET_NAME}"

(注意:您可能需要修改它。它适用于我在 OS X 中,但我已经在使用 git completion for my terminal prompt。)

然后 cd 进入该目录,如果您执行 rvm gemset list,您应该会看到为该 git 分支创建了一个 gemset。唯一的问题是,在您创建一个新的 git 分支后,您需要 cd 出入目录以使其识别在 .rvmrc 中创建的不同 gemset(即使 .rvmrc 是同一个文件,它也会运行不同)。

这不是一个完美的解决方案,项目中的每个人都必须参与其中。如果您将 .rvmrc 用于一个项目,则应考虑将其用于所有项目,否则只需 cd 进入目录,ruby 版本和 gemset 可能会更改,然后如果您返回另一个没有的项目没有 .rvmrc,您可能不会注意到它发生了变化并且遇到了问题。

编辑:Michal Papis mentioned

一个可能的解决方案是使用 .versions.conf 引入 在这里:https://gist.github.com/1912050#gistcomment-86575 - 应该是 很容易放一个标志-> ruby​​-gemset-git-branch 将附加 如果与 master 不同,则分支到 gemset 名称

【讨论】:

    【解决方案5】:

    使用 rbenv 代替 RVM。然后,您将完全使用 Bundler 管理您的 gem。

    修改您的 Gemfile,使一个分支用于 Rails 3,另一个用于 Rails 3.1。

    然后在启动 WEBrick 时运行bundle exec rails server,bundler 将使用您所在分支所需的 Rails 版本。保持干燥;)

    阅读我对getting started with rbenv 的简短介绍。

    【讨论】:

    • 仅使用捆绑器来管理 gem 版本会强制您使用 bundle exec ...,在 bundle exec rails server 的情况下,与 r s 相比开销很大(您可以通过使用我的 gem rubygems.org/gems/rubygems-bundleralias r=rails) ...但捆绑器仍然没有为插件提供分离 - 就像 ruby​​gems 插件,你可以得到它们全部或没有......
    • 需要引用。 rbenv 有用于使用 gem 而不是 bundler 安装的 gem 的 binstub,只需 gem install 它,然后您可以照常使用 rails s。另外,如果你要给某些东西起别名,为什么不给 bundle exec rails 起别名呢?
    • 这里是我的文章更详细的内容niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm,以及为什么不使用别名 r 来捆绑 exec rails - 因为它仅适用于 rails,您必须从 rake 开始为每个二进制文件创建别名以haml或上帝结束
    • 这与您的 rails 别名没有什么不同 - 它特定于 rails 二进制文件。如果您想要更广泛的解决方案,请别名 bundle exec。如果您真的希望 gem 二进制文件可以在全球范围内访问,只需 gem install 他们。使用 RVM,您必须为每个项目拥有一个 gemset,以实现 bundle exec 为您提供的功能,这意味着您最终会得到 N 个 rails、haml、rspec、pg、paperclip、factory_girl 的副本......
    猜你喜欢
    • 1970-01-01
    • 2019-11-12
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    相关资源
    最近更新 更多