最近我们开始使用Liquibase。它还没有发生但我们想象如果两个开发人员将更改日志文件中的更改提交到共享Git存储库会发生什么。
如何解决或避免合并冲突?为了扩大这个问题:
使用Liquibase与Git结合使用的推荐工作流程是什么?
示例场景:
- 迈克尔改变了表格中的一栏'客户'
- 雅各布改变表格中的一栏'帐号'
因此,两位开发人员都在同一个changelog文件changelog.xml中添加了<changeSet>
。
编辑:
正如所评论的那样,情景并非如此令人兴奋。假设雅各布是最后一个推动他的代码的人。他必须先拉。获取一个警告,要解决合并冲突。他通过保留代码的两部分,迈克尔和他的代码来解决冲突。使用Liquibase更新数据库没有任何问题。
高级示例场景:
-Michael更改列的名称&#39; name&#39;表&#39;客户&#39; in&#39; first_name&#39;,提交和推送。
-Jacob更改了列名称&#39; name&#39;表&#39;客户&#39; in&#39; last_name&#39;和承诺。
-Jacob在提取迈克尔代码时会发生合并冲突
-Jacob和迈克尔讨论了这场冲突并同意它必须是#last;&#39 ;,雅各布承诺和推动。
-Michael拉出已解决的冲突并运行Liquibase更新。他收到错误:column "name" does not exist
答案 0 :(得分:5)
在我的公司,我们使用liquibase的方式可以防止这些情况发生。基本上,您为每个更改创建一个单独的liquibase文件。我们使用一些描述性文本命名JIRA票证之后的文件。每个文件,我们都放在一个文件夹中,用于它们所用的系统版本;如果下一个版本是1.22,那么当我们开始进行数据库更改时会创建该文件夹,并且我们将每个liquibase文件与只包含它们的update.xml脚本放在一起。这个update.xml文件最终成为冲突真正发生的唯一地方,而且它们很容易解决。
为了说明,这是src/main/liquibase
文件夹:
├── install
│ ├── projectauthor.xml
│ ├── project_obspriorities.xml
│ ├── project_priorities.xml
│ ├── project_udv.xml
│ ├── project.xml
│ ├── roles.xml
│ ├── scan.xml
│ ├── (the other table definitions in the system go here)
│
├── install.xml <-- this reads all the files in ./install
│
├── local.properties <--
├── prod.properties <-- these are database credentials (boo, hiss)
├── staging.properties <--
├── test.properties <--
│
├── update.xml <-- reads each version/master.xml file
│
├── v1.16
│ ├── 2013-06-06_EVL-2240.xml
│ ├── 2013-07-01_EVL-2286-remove-invalid-name-characters.xml
│ ├── 2013-07-02_defer-coauthor-projectauthor-unique-constraint.xml
│ └── master.xml
├── v1.17
│ ├── 2013-07-19_EVL-2295.xml
│ ├── 2013-09-11_EVL-2370_otf-mosaicking.xml
│ └── master.xml
├── v1.18
│ ├── 2014-05-05_EVL-2326-remove-prerequisite-construct.xml
│ ├── 2014-06-03_EVL-2750_fix-p-band-polarizations.xml
│ └── master.xml
install.xml文件只是一堆文件包含:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<include file="src/main/liquibase/project/install/projectauthor.xml"/>
<include file="src/main/liquibase/project/install/project_obspriorities.xml"/>
...
</databaseChangeLog>
update.xml文件是同一个故事:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<include file="src/main/liquibase/project/v1.18/master.xml"/>
</databaseChangeLog>
我不喜欢的工作流程的一个方面是install / * .xml应该在当前版本之前创建数据库,但我们通常不记得这样做。< / p>
无论如何,这种方法可以帮助您避免陷入困境。我们正在使用Subversion,并且没有任何合并困难。
答案 1 :(得分:4)
总会有边缘情况需要手动处理,但它们通常很少发生。 Git通常可以很好地处理文本级别的更改合并,因此合并后的文件将一个接一个地包含changeSet。
由于liquibase通过id / author / filename跟踪changeSet,雅各布的changeSet恰好在Michaels&#39;之前结束。在最后的changeSet中并不重要。当两个开发人员都运行最终的changeSet时,Liquibase将只运行另一个开发人员的变更集,因为他们已被标记为已运行但另一个尚未标记为已运行。对于所有其他环境,两个changeSets都将运行。
您的高级案例会遇到问题,因为两个开发人员都在进行相互矛盾的更改。如果两个开发人员都删除了一个列,或者添加了一个具有相同名称的新列,您也可能会遇到类似的问题。它也不总是只是一个开发人员与另一个开发人员,有时冲突的变更来自两个独立的功能分支被合并。合并的changeSet本身在物理上没有问题,问题是新的更改日志在逻辑上不正确。它不是一个真正的git问题,它是一个逻辑问题。
实际上,这种类型的冲突很少发生,因为不同的开发人员和不同的分支通常在代码库的不同区域工作,当有可能发生冲突时,他们会通过沟通和规划来处理它。
如果您遇到冲突,有几种方法可以解决它。通常通过删除不正确或重复的changeSet来处理(如在您的示例中),但也可以通过创建两者的组合的全新changeSet来处理。在任何一种情况下,您都需要处理运行&#34;错误&#34;变更。如何最好地处理这取决于运行它的系统数量。
如果是单个开发人员,有时最简单的方法就是运行liquibase changeLogSync
将新的changeSet标记为已运行并在数据库中手动进行更改。如果最近运行了错误的changeSet,他们甚至可以运行liquibase rollbackCount X
以恢复其不良更改,然后删除changeSet然后liquibase update
如果有多个冲突和/或多个系统运行了问题更改集,则最简单的方法通常是使用<preConditions onFail="MARK_RAN"><changeSetExecuted id=....></preConditions>
标记。您可以删除错误的changeSet并添加一个新的changeSet,只有在执行旧的changeSet时才会运行,并将数据库恢复到以后的changeSet预期的状态。在您的示例中,它会将first_name重命名为name,以便last_name changeSet的名称可以正常工作。
答案 2 :(得分:0)
我不知道液体基地,但我认为错误是在“雅各布和迈克尔讨论冲突并且同意它必须是'last_name',Jacob承诺并推动。”
更改日志必须匹配要完成的操作(或已在数据库上完成的操作)。即你无法删除推送的更改。
因此,正确的解析是name-&gt; first_name AND first_name-&gt; last_name。
答案 3 :(得分:0)
TL; DR:将/path/to/changelogfile.xml merge=union
添加到.gitattributes文件中。
我已经看到了一些有关拥有单独文件的讨论。在liquibase中有两种单独的文件的方法:
includeAll
标签,然后继续将新文件推送到该文件夹。include
标签来指示顺序。这两种方式仍然会引起问题:(1)includeAll将仅按文件名的字典顺序选择文件,如果每次提交新更改时都执行changelog,则该方法会很好地工作,但是如果要部署,它将失败到一个全新的文件。除非您有命名策略来指示顺序。但是,如果迈克尔和雅各布同时工作,这仍然是一个问题:他们可能使用相同的名称,这会导致冲突。 (2)Michael和Jacob都需要编辑主文件的最后几行。换句话说:合并冲突!
实际的解决方案是不更改您的liquibase策略。保持您到目前为止一直遵循的相同策略。问题的根源在于源代码控制和合并机制。 liquibase changelog文件本质上是一个历史记录。可以将其视为发行说明文件,开发人员只需将其工作添加到文件的最后一行即可。在这种情况下,如果两个开发人员添加两行添加末尾无关紧要,则无论顺序如何,两者都应该执行。因此,解决方案是在git项目的根文件夹中创建一个.gitattributes文件(如果还没有的话),并在其中添加以下行:
/path/to/changelogfile.xml merge=union
这仍然不是故障诊断。为了解决您的高级示例场景,我想不出任何自动策略或工作流程。开发人员在触摸相同的表(或相同的db对象)时应进行通信。这种情况不仅是“文件”冲突,而且是语义冲突。那时,良好的CI变得很方便。最后提交并合并代码的开发人员将收到错误,并且需要与首先赢得比赛的开发人员取得联系。
请注意,也许您的Git门户网站不支持合并策略,但您仍然会在请求请求(也称为合并请求)上遇到合并冲突。但是,当您看到这种情况并尝试合并回去或重新设置基础以解决冲突时,该冲突已经解决。我知道GitLab确实支持它。不确定Github或BitBucket。