你如何处理源代码pipe理中的configuration文件?
比方说,你有一个典型的Web应用程序和文件configuration。 每个在这个项目上工作的开发者都会为他们的开发工具箱提供一个版本,这将会有一个开发者,制作者和舞台版本。 你如何处理源代码pipe理? 根本不检查这个文件,用不同的名字检查它,或者做一些奇特的事情?
我过去所做的是有一个默认的configuration文件,签入到源代码pipe理。 然后,每个开发人员都有自己的覆盖configuration文件,从源代码pipe理中排除。 应用程序首先加载默认值,然后如果覆盖文件存在,则加载该覆盖文件,并使用覆盖的任何设置优先于默认文件。
一般来说,覆盖文件越小越好,但对于非标准环境的开发人员来说,它总是可以包含更多的设置。
不要版本该文件。 版本模板或其他东西。
configuration是代码,你应该版本。 我们的configuration文件基于用户名; 在UNIX / Mac和Windows中,你都可以访问用户的login名,只要这些对于项目来说是唯一的,你就可以。 你甚至可以在环境中重写这个,但你应该版本控制一切。
这也允许您检查其他人的configuration,这可以帮助诊断构build和平台问题。
我的团队为每个环境保存不同版本的configuration文件(web.config.dev,web.config.test,web.config.prod)。 我们的部署脚本复制出正确的版本,并将其重命名为web.config。 这样,我们对每个环境的configuration文件都有完整的版本控制,可以很容易地执行diff等。
目前我有一个“模板”configuration文件,例如:
web.config.rename
但是,如果关键的变化已经改变,我可以看到这个方法的问题。
我们使用的解决scheme是只有一个configuration文件(web.config / app.config),但是我们为包含所有环境设置的文件添加了一个特殊的部分。
有一个LOCAL,DEV,QA,PRODUCTION部分,每个部分都包含configuration文件中与该环境相关的configuration密钥。
使这一切工作的是一个名为xxx.Environment的程序集,它在所有我们的应用程序(winforms和webforms)中被引用,它告诉应用程序在哪个环境上运行。
xxx.Environment程序集读取给定机器的machine.config中的一行信息,告诉它它在DEV,QA等上。这个条目存在于我们所有的工作站和服务器上。
希望这可以帮助。
+1模板方法。
但是由于这个问题有标签Git,所以分布式的select会浮现在其中,定制被保存在一个私有的testing分支上:
A---B---C---D--- <- mainline (public) \ \ B'------D'--- <- testing (private)
在这种scheme中,主线包含一个通用的“模板”configuration文件,要求最less量的调整才能起作用。
现在,开发人员/testing人员可以将configuration文件调整为自己的内容,并且只在私有testing分支(例如B'= B +自定义)上本地提交这些更改。 每次主线程进展时,他们毫不费力地将其合并到testing中,从而导致合并提交,例如D'(= B的定制的D +合并版本)。
当“template”configuration文件被更新时,这个scheme真正地发光:双方的变化被合并,如果它们不兼容,极有可能导致冲突(或testing失败)!
我以前使用过这个模板,比如web.dev.config,web.prod.config等等,但是现在更喜欢'override file'技术。 web.config文件包含大部分设置,但是外部文件包含特定于环境的值(如数据库连接)。 保罗·威尔逊博客上的好解释。
我认为这减less了在添加新的值/属性时会导致痛苦的configuration文件之间的重复数量。
@Grant是对的。
我在一个有近100名其他开发人员的团队中,我们的configuration文件没有签入源代码pipe理。 我们有版本的资料库中的每个检查,但他们不会改变。
这对我们来说很好。
我始终将所有版本的configuration文件保存在源代码pipe理中,与web.config文件位于同一个文件夹中。
例如
web.config web.qa.config web.staging.config web.production.config
我更喜欢这个命名约定(与web.config.production或production.web.config相反)
- 当您按文件名sorting时,它将文件保存在一起
- 它通过文件扩展名sorting时将文件保存在一起
- 如果文件被意外推到生产中,您将无法通过http查看内容,因为IIS将阻止提供* .config文件
应configuration默认的configuration文件,以便您可以在自己的机器上本地运行应用程序。
最重要的是,这些文件应该在每个方面几乎100%相同,甚至格式化。 您不应该在一个版本中使用制表符,而在另一个版本中使用制表符来缩进 你应该能够对这些文件运行一个diff工具,看看它们之间究竟有什么不同。 我更喜欢使用WinMerge来区分文件。
当您的构build过程创build二进制文件时,应该有一个任务,使用适合该环境的configuration文件覆盖web.config。 如果文件被压缩,那么不相关的文件应该从该版本中删除。
我版本控制它,但从不推送到其他服务器。 如果生产服务器需要更改,则直接将该更改发送到configuration文件。
它可能不漂亮,但它工作得很好。
app / web.config的签入,普通版本应该足够通用,可以在所有开发人员机器上工作,并随时更新任何新的设置更改等。如果您需要一组特定的dev设置/testing/生产设置,使用这些设置检查单独的文件,正如GateKiller所说,用某种命名约定,虽然我通常使用“web.prod.config”,因为不改变文件扩展名。
我们使用一个模板configuration文件签入到版本控制中,然后使用我们的自动构build中的一个步骤来将模板文件中的特定条目replace为特定于环境的设置。 环境特定的设置存储在一个单独的XML文件中,该文件也受版本控制。
我们在自动构build中使用MSBuild,所以我们使用MSBuild社区任务中的XmlUpdate 任务来更新这些值。
很长一段时间,我已经完成了bcwood的工作。 我在源代码控制下保存了web.dev.config,web.test.config,web.prod.config等的副本,然后我的构build/部署系统在部署到各种环境时自动将其重命名。 你在文件之间得到了一定的冗余(特别是在那里有所有的asp.net的东西),但是一般来说它工作得很好。 您还必须确保团队中的每个人都记得在更改时更新所有文件。
顺便说一句,我喜欢保留“.config”作为扩展名,以便文件关联不会被破坏。
就configuration文件的本地开发版本而言,我总是尽我所能鼓励人们尽可能使用相同的本地设置,这样就不需要有自己的版本。 这并不总是适用于每个人,在这种情况下,人们通常只是根据需要在当地取而代之。 这不是太痛苦或什么。
在我们的项目中,我们将configuration存储在带有前缀的文件中,然后我们的构build系统根据当前系统的主机名引入相应的configuration。 这对于我们这个相对较小的团队来说效果很好,因此,如果/当我们添加一个新的configuration项时,允许我们将configuration更改应用到其他人的文件。 显然这绝对不能与无数开发人员扩展到开源项目。
我们只是保持生产configuration文件签入。开发人员有责任在将文件从源码安全地提取出来用于分段或开发时更改文件。 这已经烧了我们过去,所以我不会build议。
我们在这里有两个问题。
-
首先,我们必须控制软件附带的configuration文件。
如果开发人员在devolvement环境中使用相同的文件,则可以轻松地检入不需要的文件以更改主configuration文件。
另一方面,如果安装程序包含单独的configuration文件,则很容易忘记添加新的设置,或者使其中的注释与设备中的注释不同步configuration文件。
-
然后,我们遇到这样的问题:开发人员必须随时保存configuration文件的副本,因为其他开发人员会添加新的configuration设置。 但是,像数据库连接string的一些设置对于每个开发人员都是不同
-
问题/答案不包括第三个问题。 当您安装新版本的软件时,如何将客户对configuration文件所做的更改进行合并?
我还没有看到一个很好的解决scheme,在任何情况下都能很好地工作,但是我已经看到了一些解决scheme (可以根据需要以不同的组合方式进行组合),从而大大减less了这个问题。
-
首先减less主configuration文件中的configuration项数量。
如果您不需要让客户更改您的映射,请使用Fluent NHibernate(或其他方式)将configuration移动到代码中。
同样的dependency injection设置。
-
尽可能拆分configuration文件,例如使用单独的文件来configurationLog4Net的日志。
-
不要在许多configuration文件之间重复项目,例如,如果您有4个全部安装在同一台计算机上的Web应用程序,则具有每个应用程序中的web.config文件指向的整体configuration文件。
(默认情况下使用相对path,因此很less必须更改web.config文件)
-
处理开发configuration文件以获取运输configuration文件。
可以通过在构build完成后在configuration文件中设置Xml注释中具有默认值来完成。 或者将部分作为创build安装程序的一部分而删除。
-
而不是只有一个数据库连接string,每个开发人员。
例如,首先在运行时查找configuration文件中的“database_ianr”(其中ianr是我的用户名或机器名),如果找不到,则查找“database”
拥有第二级“eg -oracle或-sqlserver”可以使开发人员更快地访问这两个数据库系统。
这当然也可以为任何其他configuration值完成。
然后,所有以“_userName”结尾的值都可以在发送configuration文件之前被删除。
然而,最终,你是一个“configuration文件的拥有者”,负责pipe理configuration文件,如上所述。 他/她也应该在每次发货之前在客户configuration文件上做一些比较。
你不能删除一个关心的人一些这个短缺的问题。
我不认为有一种解决scheme适用于所有情况,因为它可能取决于configuration文件中数据的敏感性,或者您使用的编程语言以及其他许多因素。 但是我认为在源代码控制下保持所有环境的configuration文件是非常重要的,所以你可以随时知道什么时候发生了变化,什么时候发生了什么,更重要的是,如果发生错误,能够恢复它。 他们会的。
所以这是我如何做到这一点。 这通常用于nodejs项目,但我认为它也适用于其他框架和语言。
我所做的是在项目的根目录下创build一个configs
目录,并在该目录下为所有环境保留多个文件(有时还会为每个开发者环境分开文件),这些文件都在源代码pipe理中进行跟踪。 还有代码在项目的根目录下使用命名config
的实际文件。 这是唯一没有被跟踪的文件。 所以它看起来像这样
root | |- config (not tracked) | |- configs/ (all tracked) |- development |- staging |- live |- James
当有人签出项目时,他复制了他想在未跟踪的config
文件中使用的config
文件,他可以自由地按照自己的意愿对其进行编辑,但也有责任根据需要将这些更改复制到其他环境文件中。
而在服务器上,未跟踪文件可以简单地作为与该环境相对应的跟踪文件的副本(或引用)。 在JS中,你可以简单地有1行来要求该文件。
这个stream程起初可能有点复杂,但它有很大的优势:1.你不必担心configuration文件被删除或修改在服务器上,而没有备份2.如果开发人员有一些自定义configuration他的机器和他的机器因任何原因停止工作3.在任何部署之前,你可以比较configuration文件的development
和staging
例如,看看是否有什么缺失或损坏。
我面临同样的问题,我find了解决办法。 我首先将所有文件添加到中央存储库(也是开发人员)。
因此,如果开发人员从存储库中提取文件,开发人员configuration也在那里。 当对这个文件进行更改时,Git不应该意识到这些更改。 这种方式更改不能推送/提交到存储库,但保持本地。
我通过使用git命令解决了这个问题: update-index --assume-unchanged
。 我做了一个bat文件,这个文件在包含一个文件的项目的预build中执行,这个文件的变化应该被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
在我的prebuild中,我会打电话给bat文件,例如:
call "$(ProjectDir)\..\..\MakeFileBehaveLikeUnchangedForGit.bat" "$(ProjectDir)Web.config.developer" "$(SolutionDir)"
我find了一个bat文件,将正确的configuration文件复制到web.config / app.config。 我也在prebuild中调用这个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.
在我的prebuild中,我会打电话给bat文件,例如:
call "$(ProjectDir)\..\..\copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config