使用Git的条件配置文件

9

在我的Git项目中,我经常需要更改一个变量以连接到不同的服务器,但只是在开发分支上(使用JavaScript编写,无法使用预处理器定义)。

有没有一种方法可以根据我所在的分支条件性地使用一个或另一个文件呢?

我不能只是提交具有不同URL指定的更改,因为这样会把它留在我的提交历史记录中,如果我稍后回到已合并的Master版本中,它将具有开发服务器URL。


1
可能是提交机器特定配置文件的重复问题。 - Senseful
条件包含gitconfig在Git 2.13中开始变得可能。请参见下面的我的答案 - VonC
@VonC 这不是这个问题的重点,这是关于环境变量以及如何在分支之间更改它们的问题,来自一个不太了解最佳实践的初学者版本。 - Christian Stewart
3个回答

12

没有,但这是一个已经解决的问题。

你有几个选择:

对示例配置文件进行版本控制

  • 不要在版本控制中存储特定于环境的数据
  • 创建一个名为config.example的文件,列出需要指定的所有配置选项,并为开发提供合理的默认值。
  • 克隆您的 repo 的用户应该将 config.example 复制到真实的配置文件名,并添加真实的值
  • 将真实的配置文件名称添加到.gitignore中。
  • 将生产凭据存储在 git 之外,但备份它们,
  • 作为奖励,您可以添加一个名为setup.sh的脚本,将config.example复制到真实配置的位置,并用本地环境的变量填充它

例如,您可能有一个 JavaScript 应用程序,需要知道其数据库的位置,并从 config/database.json读取此信息。你可以使用类似下面的内容:

// config/database.example.json
DATABASE = {
  "host": "localhost",
  "user": "#TODO",
  "pass": "#TODO",
}
为在开发环境中运行,您需要将此文件复制到config/database.json中,并填写适合您的开发环境的值。
在生产环境中,您会有一个包含生产值但不受版本控制的config/database.json
存储X个不同的配置文件,每个环境一个,称为config.developmentconfig.production等。为您的环境创建符号链接。将符号链接添加到.gitignore。
如果您的配置文件中有任何敏感信息(例如AWS密钥或任何形式的密码),您应该使用第一种选项-仅存储配置选项的名称,而不是它的值,并要求用户通过版本控制之外的安全渠道提供自己的凭据。

谢谢。我可以根据分支情况添加一个钩子来复制默认值。 - Christian Stewart
我的回答的真正要点是,你不应该使用特定于环境的分支。你的特定于环境的内容应该存储在仓库之外。 - user229044
我明白,但在这种情况下,我通常会在开发分支上使用开发服务器。 - Christian Stewart

7
注意,条件包括配置将在Git 2.13(2017年第二季度)开始支持。
目前唯一支持的条件是项目名称,而不是主机名。
在您的情况下,如果每个分支都在自己的文件夹中检出(使用git worktree:请参见“使用Git进行多个工作目录”),那么这将起作用。

查看提交 86f9515提交 4aad2f1(于2017年4月5日)由Nguyễn Thái Ngọc Duy (pclouds)完成。
(由Junio C Hamano -- gitster --提交 a2e2c04中合并,于2017年4月24日)

config: 添加条件式包含

有时,一组存储库想要共享配置设置,这些设置与其他这样的存储库集合不同。
用户可能在两个项目上工作,每个项目都有多个存储库,并为一个项目使用一个user.email,而为另一个项目使用另一个。

设置$GIT_DIR/.config是可行的,但如果忘记更新$GIT_DIR/.config的代价很高(特别是当您经常克隆时),这可能不是最佳选择。
将设置放在~/.gitconfig中,对于仅适用于一组存储库的情况有效,但在这种情况下效果不佳。
拥有单独的${HOME}s可能会带来更多问题。

扩展include.path机制,使配置文件可以包含另一个配置文件,只有在满足某些条件时才能进行包含。
然后,~/.gitconfig可以说“仅在处理project-A时包括config-project-A”对于用户处理的每个project A

在此补丁中,唯一支持的分组基于$GIT_DIR(在绝对路径中),因此您需要按目录或类似方式对存储库进行分组,以利用它。

我们已经有了无条件包含的include.path
这个补丁使用includeIf.<condition>.path来使条件要求更清晰。
新配置采用与include.path相同的向后兼容方法:不理解includeIf的旧git版本将简单地忽略它们。


Git 2.14(Q3 2017)澄清了文档。

请查看提交ce933eb, 提交a076df2, 提交994cd6c, 提交9d71d94 (2017年5月11日) 由Jeff King (peff)提交。
(由Junio C Hamano -- gitster --提交ed98060中合并,2017年5月29日)

文档现在已经更新并包含以下内容:

包括

includeincludeIf部分允许您从另一个源包含配置指令。这些部分的行为完全相同,唯一的区别是如果条件不为真,则可以忽略includeIf部分;请参见下面的“条件包含”。

同样的Git 2.14增强了该功能。
请参考commit 0624c63(由Ævar Arnfjörð Bjarmason(avar于2017年5月16日提交)。
(由Junio C Hamano -- gitster -- commit b784d0b中合并,于2017年5月30日)

最近引入了"[includeIf "gitdir:$dir"] path=..."机制,并且进一步考虑了符号链接的影响。 在"gitdir:$dir"中指定的目录"$dir"可能是指向实际位置的符号链接,而不是$(getcwd)返回的内容。 在这种情况下,将"$dir"的真实路径与当前存储库的真实路径进行比较,以确定是否应包含命名路径的内容。

1
点赞以表支持,realpath 函数用于比较符号链接。 - Ederbit

0

听起来你可能对hook感兴趣;具体来说,可以研究一下post-checkout hook。基本上,你需要编写一个小脚本,在检出后根据$(git branch)的值修改文件。你没有明确提到需要发生什么,但很可能涉及sed。

你可以将相关文件添加到.gitignore文件中,或者编写一个pre-commit hook,以便你的更改不会意外传播到公共repo。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接