题
假设您有一个典型的 Web 应用程序和一个文件配置。无论如何。每个从事该项目的开发人员都会有一个适合其开发盒的版本,其中会有开发版、产品版和阶段版。您如何在源代码控制中处理这个问题?根本不签入该文件,用不同的名称检查它还是干脆做一些奇特的事情?
解决方案
我过去所做的是拥有一个签入源代码管理的默认配置文件。然后,每个开发人员都有自己的覆盖配置文件,该文件被排除在源代码控制之外。应用程序首先加载默认设置,然后如果存在覆盖文件,则加载该文件并优先使用覆盖中的任何设置而不是默认文件。
一般来说,覆盖文件越小越好,但对于具有非常非标准环境的开发人员来说,它始终可以包含更多设置。
其他提示
不要对该文件进行版本控制。版本模板或其他东西。
配置 是 代码,并且您应该对其进行版本控制。我们的配置文件基于用户名;在 UNIX/Mac 和 Windows 中,您都可以访问用户的登录名,只要这些对项目来说是唯一的,就可以了。您甚至可以在环境中覆盖它,但是您 应该 版本控制一切。
这还允许您检查其他人的配置,这可以帮助诊断构建和平台问题。
我的团队为每个环境保留单独版本的配置文件(web.config.dev、web.config.test、web.config.prod)。我们的部署脚本复制出正确的版本,并将其重命名为 web.config。这样,我们就可以对每个环境的配置文件进行完整的版本控制,可以轻松地执行差异等。
目前我有带有添加扩展名的“模板”配置文件,例如:
web.config.rename
但是,如果关键更改发生变化,我会发现此方法存在问题。
我们使用的解决方案是只有一个配置文件 (web.config/app.config),但我们向该文件添加一个特殊部分,其中包含所有环境的设置。
有一个 本地、开发、质量检查、生产 每个部分都包含与我们的配置文件中的环境相关的配置键。
使这一切工作的是一个名为的程序集 xxx.环境 我们所有的应用程序(winforms 和 webforms)都会引用它,它告诉应用程序它正在运行的环境。
xxx.Environment 程序集从 机器配置 给定机器的信息告诉它它处于 DEV、QA 等状态。该条目存在于我们所有的工作站和服务器上。
希望这可以帮助。
模板方法+1。
但是,由于这个问题具有标记git,因此在私人测试分支上保存自定义的分布式替代弹簧:
A---B---C---D--- <- mainline (public)
\ \
B'------D'--- <- testing (private)
在此方案中,主线包含一个通用的“模板”配置文件,需要最少的调整才能发挥功能。
现在,开发人员/测试人员可以将配置文件调整为他们心脏的内容,并且只能在一个私人测试分支上本地提交这些更改(例如B' = B + 定制)。每次Mainline进步时,它们都会毫不费力地将其合并为测试,从而导致合并d'(例如B的自定义的= D +合并版本)等合并。
当“模板”配置文件更新时,这个方案真的很出色:双方的变化都合并了,如果不兼容,则极有可能导致冲突(或测试失败)!
我以前使用过该模板,即web.dev.config、web.prod.config 等,但现在更喜欢“覆盖文件”技术。web.config 文件包含大部分设置,但外部文件包含特定于环境的值,例如数据库连接。很好的解释 保罗·威尔逊的博客.
我认为这减少了配置文件之间的重复量,这在添加新值/属性时可能会造成痛苦。
我始终将所有版本的配置文件保存在源代码管理中,与 web.config 文件位于同一文件夹中。
例如
web.config
web.qa.config
web.staging.config
web.production.config
我更喜欢这种命名约定(而不是 web.config.Production 或 Production.web.config),因为
- 当您按文件名排序时,它会将文件放在一起
- 当您按文件扩展名排序时,它会将文件放在一起
- 如果文件意外推送到生产环境,您将无法通过 http 查看内容,因为 IIS 将阻止提供 *.config 文件
应配置默认配置文件,以便您可以在自己的计算机上本地运行应用程序。
最重要的是,这些文件在各个方面都应该几乎 100% 相同,甚至格式也是如此。您不应在一个版本中使用制表符,而在另一版本中使用空格来缩进。您应该能够对这些文件运行 diff 工具,以准确查看它们之间的不同之处。我更喜欢使用 WinMerge 来比较文件。
当您的构建过程创建二进制文件时,应该有一个任务使用适合该环境的配置文件覆盖 web.config。如果文件被压缩,则应从该版本中删除不相关的文件。
@格兰特是对的。
我所在的团队有近 100 名其他开发人员,我们的配置文件没有签入源代码管理。我们在存储库中拥有每次签出时都会提取的文件版本,但它们不会更改。
这对我们来说效果很好。
我对其进行版本控制,但从不将其推送到其他服务器。如果生产服务器需要更改,我会直接对配置文件进行更改。
它可能不漂亮,但效果很好。
签入的 app/web.config 的普通版本应该足够通用,可以在所有开发人员计算机上工作,并与任何新的设置更改等保持同步。如果您需要一组特定的开发/测试/生产设置设置,请使用这些设置签入单独的文件,如 GateKiller 所说,并使用某种命名约定,尽管我通常使用“web.prod.config”,而不是更改文件扩展名。
我们使用签入版本控制的模板配置文件,然后在自动构建中使用特定于环境的设置替换模板文件中的特定条目。特定于环境的设置存储在同样受版本控制的单独 XML 文件中。
我们在自动构建中使用 MSBuild,因此我们使用来自 MSBuild 社区任务 更新值。
很长一段时间以来,我所做的正是 bcwood 所做的事情。我保留 web.dev.config、web.test.config、web.prod.config 等的副本。在源代码控制下,然后我的构建/部署系统在部署到各种环境时自动重命名它们。文件之间存在一定量的冗余(特别是其中包含所有 asp.net 内容),但通常它工作得很好。您还必须确保团队中的每个人都记得更新 全部 文件进行更改时。
顺便说一句,我喜欢将“.config”保留在末尾作为扩展名,这样文件关联就不会被破坏。
至于配置文件的本地开发人员版本,我总是尽力鼓励人们尽可能使用相同的本地设置,这样就不需要有自己的版本。它并不总是适合所有人,在这种情况下,人们通常只是根据需要在本地替换它,然后从那里开始。不是太痛什么的。
在我们的项目中,我们将配置存储在带有前缀的文件中,然后我们的构建系统根据当前系统的主机名提取适当的配置。这对于我们相对较小的团队来说效果很好,允许我们在添加新配置项时将配置更改应用于其他人的文件。显然,这绝对无法扩展到拥有无限数量开发人员的开源项目。
我们这里有两个问题。
首先,我们必须控制软件附带的配置文件。
如果开发人员在转移环境中使用相同的文件,那么开发人员可以轻松地将不需要的更改签入主配置文件。
另一方面,如果安装程序包含一个单独的配置文件,则很容易忘记向其中添加新设置,或者让其中的注释与devolvement中的注释不同步配置文件。
然后我们遇到的问题是,当其他开发人员添加新的配置设置时,开发人员必须保持配置文件的副本是最新的。但是,某些设置(例如数据库连接字符串)对于每个开发人员来说都是不同的。
还有一个问题/答案没有涵盖的第三个问题。 当您安装新版本的软件时,如何合并客户对您的配置文件所做的更改?
在所有情况下,我还没有看到一个很好的解决方案,但是我已经看到了一些 部分解决方案(可以根据需要将其组合成不同的组合),从而大大减少了问题。
首先减少主配置文件中的配置项数量。
如果您不需要让客户更改映射,请使用 Fluent NHibernate(或其他方式)将配置移至代码中。
对于依赖注入设置也是如此。
尽可能拆分配置文件,例如使用单独的文件来配置 Log4Net 记录的内容。
不要在多个配置文件之间重复项目,例如如果您有 4 个 Web 应用程序都安装在同一台计算机上,则每个应用程序中的 web.config 文件都指向一个总体配置文件。
(默认使用相对路径,因此很少需要更改 web.config 文件)
处理开发配置文件以获得交付配置文件。
这可以通过在 Xml 注释中使用默认值来完成,然后在构建完成时在配置文件中设置默认值。或者在创建安装程序的过程中删除某些部分。
每个开发人员都拥有一个数据库连接字符串,而不是只有一个数据库连接字符串。
例如,首先在运行时在配置文件中查找“database_ianr”(其中ianr是我的用户名或机器名),如果没有找到,则查找“database”
有第二级“例如-oracle 或 -sqlserver” 使开发人员能够更快地访问这两个数据库系统。
当然,这也可以针对任何其他配置值来完成。
然后,在传送配置文件之前,可以删除所有以“_userName”结尾的值。
但是,最终您是“配置文件的所有者”,它负责任地管理配置文件如上或其他方式。他/她还应该在每次装运之前对客户面配置文件进行差异。
你无法因为这么短的问题而消除对有爱心的人的需要。
我认为没有一个解决方案适用于所有情况,因为它可能取决于配置文件中数据的敏感性,或您正在使用的编程语言,以及许多其他因素。但我认为将所有环境的配置文件置于源代码控制之下很重要,这样您就可以随时知道它何时以及由谁更改,更重要的是,如果出现问题,能够恢复它。他们会的。
我是这样做的。这通常适用于 Nodejs 项目,但我认为它也适用于其他框架和语言。
我所做的是创建一个 configs
项目根目录下,并在该目录下保留所有环境的多个文件(有时也为每个开发人员的环境提供单独的文件),这些文件都在源代码管理中进行跟踪。代码使用的实际文件名为 config
在项目的根部。这是唯一未被跟踪的文件。所以看起来像这样
root
|
|- config (not tracked)
|
|- configs/ (all tracked)
|- development
|- staging
|- live
|- James
当有人签出项目时,他会复制他想要在未跟踪的项目中使用的配置文件 config
他可以根据需要自由编辑它,但也有责任在根据需要提交到其他环境文件之前复制这些更改。
在服务器上,未跟踪的文件可以只是与该环境相对应的跟踪文件的副本(或引用)。在 JS 中,您只需使用 1 行即可获取该文件。
这个流程一开始可能有点复杂,但它有很大的优点:1.您不必担心配置文件在服务器上不会在没有备份2的情况下删除或修改。如果开发人员在其机器上有一些自定义配置,并且由于任何原因,他的机器停止工作3。在任何部署之前,您可以比较配置文件 development
和 staging
例如,看看是否有任何东西丢失或损坏。
我们只需签入生产配置文件即可。当开发人员将文件从源安全中拉出以进行暂存或开发时,他们有责任更改文件。这在过去让我们很恼火,所以我不建议这样做。
我遇到了同样的问题,并且找到了解决方案。我首先将所有文件添加到中央存储库(也是开发人员的文件)。
因此,如果开发人员从存储库中获取文件,开发人员配置也在那里。对此文件进行更改时,Git 不应该知道这些更改。这样,更改就无法推送/提交到存储库,而是保留在本地。
我通过使用 git 命令解决了这个问题: update-index --assume-unchanged
. 。我制作了一个在项目的预构建中执行的 bat 文件,该项目包含一个文件,该文件的更改应被 Git 忽略。这是我放入bat文件中的代码:
IF NOT EXIST %2%\.git GOTO NOGIT
set fileName=%1
set fileName=%fileName:\=/%
for /f "useback tokens=*" %%a in ('%fileName%') do set fileName=%%~a
set "gitUpdate=git update-index --assume-unchanged"
set parameter= "%gitUpdate% %fileName%"
echo %parameter% as parameter for git
"C:\Program Files (x86)\Git\bin\sh.exe" --login -i -c %parameter%
echo Make FIleBehaveLikeUnchangedForGit Done.
GOTO END
:NOGIT
echo no git here.
echo %2%
:END
在我的预构建中,我将调用 bat 文件,例如:
call "$(ProjectDir)\..\..\MakeFileBehaveLikeUnchangedForGit.bat" "$(ProjectDir)Web.config.developer" "$(SolutionDir)"
我在 SO 上发现了一个 bat 文件,它将正确的配置文件复制到 web.config/app.config 中。我还在预构建中调用此 bat 文件。这个bat文件的代码是:
@echo off
echo Comparing two files: %1 with %2
if not exist %1 goto File1NotFound
if not exist %2 goto File2NotFound
fc %1 %2
if %ERRORLEVEL%==0 GOTO NoCopy
echo Files are not the same. Copying %1 over %2
copy %1 %2 /y & goto END
:NoCopy
echo Files are the same. Did nothing
goto END
:File1NotFound
echo %1 not found.
goto END
:File2NotFound
copy %1 %2 /y
goto END
:END
echo Done.
在我的预构建中,我将调用 bat 文件,例如:
call "$(ProjectDir)\..\..\copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config