使用Liquibase和Git的推荐工作流程是什么? - java

最近,我们开始使用Liquibase。它尚未发生,但是我们想象如果两个开发人员将更改日志文件中的更改提交到共享Git存储库会发生什么。

如何解决或避免合并冲突?为了扩大这个问题一些什么:

建议将Liquibase与Git结合使用的工作流程是什么?

示例场景:
-Michael更改了“客户”表中的一列。
-Jacob更改了表“帐户”中的一列。
因此,两个开发人员都在同一个变更日志文件changelog.xml中添加了<changeSet>

编辑:

正如所评论的,情况确实并不那么令人兴奋。假设雅各布是最后一个执行他的代码的人。他必须先拉。得到警告,有合并冲突要解决。他通过保留迈克尔和他的两部分代码来解决冲突。使用Liquibase更新数据库没有任何问题。

高级示例场景:
-Michael在“first_name”中更改表“customer”的“name”列的名称,进行提交和推送。
-Jacob在“last_name”中更改表“customer”的“name”列的名称并提交。
-在提取Michael的代码时,Jacob发生合并冲突。
-雅各布和迈克尔讨论了冲突,并同意它必须是“姓氏”,由雅各布提交并推动。
-Michael拉出已解决的冲突并运行Liquibase更新。他收到一个错误:column "name" does not exist

参考方案

总有一些情况需要手动处理,但通常很少发生。 Git通常可以在文本级别很好地处理更改合并,因此合并后的文件中将同时包含两个changeSet,一个接一个。

由于liquibase通过id / author / filename跟踪changeSet,因此,在最终的changeSet中,Jacob的changeSet恰好在Michaels之前结束的事实无关紧要。当两个开发人员都运行最终的changeSet时,Liquibase将仅运行另一个开发人员的changeSet,因为他们的已被标记为已运行,而另一个则没有。对于所有其他环境,两个changeSet都将运行。

您的高级案例遇到了问题,因为两个开发人员都在进行相互矛盾的更改。如果两个开发人员都删除一列或添加具有相同名称的新列,您也可能会遇到类似的问题。同样,一个开发人员与另一个开发人员也不总是简单的,有时冲突的changeSet来自两个合并的独立功能分支。合并的changeSet本身在物理上没有问题,问题在于新的changelog在逻辑上是不正确的。这不是一个真正的git问题,而是一个逻辑问题。

在实践中,这种类型的冲突很少发生,因为不同的开发人员和不同的分支通常在代码库的不同区域工作,并且当存在潜在冲突时,他们可以通过沟通和规划来解决。

如果确实发生冲突,有几种解决方法。通常,这可以通过删除不正确或重复的changeSet来进行处理(例如在您的示例中),但是也可以通过创建将两者结合使用的全新changeSet来进行处理。无论哪种情况,您都需要处理运行了“错误的” changeSet的数据库。如何最好地处理这取决于运行了多少系统。

如果是单个开发人员,有时最简单的方法是运行liquibase changeLogSync将新的changeSet标记为已运行,然后手动在数据库中进行更改。如果最近运行了坏的changeSet,他们甚至可以运行liquibase rollbackCount X还原他们的坏更改,然后删除changeSet然后删除liquibase update
如果存在多个冲突和/或运行了问题变更集的多个系统,则最简单的方法通常是使用<preConditions onFail="MARK_RAN"><changeSetExecuted id=....></preConditions>标记。您可以删除错误的changeSet并添加一个仅在执行旧的changeSet时才运行的新changeSet,并将数据库置于以后的changeSets期望的状态。在您的示例中,它将first_name重命名回name,以便将last_name changeSet的名称正常工作。

Java:线程池如何将线程映射到可运行对象 - java

试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java:BigInteger,如何通过OutputStream编写它 - java

我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…

Java DefaultSslContextFactory密钥库动态更新 - java

我有一个使用org.restlet.engine.ssl.DefaultSslContextFactory的现有应用程序和一个在服务器启动时加载的密钥库文件。我有另一个应用程序,该应用程序创建必须添加的证书服务器运行时动态地更新到密钥库文件。为此,我在代码中创建了证书和私钥,然后将其写入到目录。该目录由bash脚本监视,该脚本检查是否有新文件,如果出现,它将…