我使用Flyway跟踪数据库更改,并使用git进行版本控制。
Flyway依赖于迁移脚本,每次迁移都会以越来越多的数字命名。
现在我遇到以下情况:在两个独立的分支上开发了两个功能(让他们称之为A和B),这两个功能都需要更改数据库。两个开发人员都为其分支创建了数据库的迁移脚本。当他们几乎同时分出master时,他们都为迁移脚本分配了相同的文件名:V42__migration.sql
。
现在分支A合并为主人。合并分支B时,由于V42__migration.sql
文件导致合并冲突。解决此冲突的正确解决方案是将分支B的迁移脚本重命名为V43__migration.sql
。但是,在合并时,git尝试将两个文件合并为一个,其中我实际上需要两个文件不变,但是一个重命名。
解决这种合并的最佳方法是什么?与git冲突?
答案 0 :(得分:4)
一旦git报告了冲突,您就会提示并完全能够以您需要的任何方式编辑索引,以解决冲突。因此,如果您要合并feature_x
,则可以:
1)获取分支的脚本并将其命名为V43
git checkout feature_X -- V42__migration.sql
mv V42__migration.sql V43__migration.sql
2)从先前合并的提交
获取V42脚本git checkout HEAD -- V42__migration.sql
3)确保索引正确更新并完成合并
git add .
git commit
另一件需要考虑的事情是,你真的不希望git尝试合并这些文件。因此,您可以使用.gitattributes将文件标记为二进制文件,或者将自定义合并类型应用于它们。我假设像whatever/path/to/V*__migration.sql
这样的模式会识别文件。
这个想法是,如果git认为它必须合并这样的路径,它应该自动标记冲突,它应该选择一个或另一个版本作为暂定的解决方案。解决冲突的人只需要放置另一个版本。
逻辑上保持"我们的#34;在合并期间,因为那是最终将获得该文件名的版本。如果将路径标记为二进制,则会发生这种情况。
但如果你保持"他们的"。
,实际上解决方案会更简单mv conflicted_file next_filename
git checkout HEAD -- conflicted_file
因此,您可能希望在gitattributes
文档中查找如何创建自定义合并驱动程序。 (它并不像听起来那么难;驱动程序可能类似于cp %B %A && false
。所以只需要几个配置命令。)
答案 1 :(得分:0)
您的分支A
和B
都包含master
中不存在的同名文件。将A
合并到master
中可以正常工作,当您合并B
时,会出现合并冲突。
$ git checkout master
$ git merge A # OK
$ git merge B # CONFLICT (add/add): Merge conflict in file
这种合并冲突如下所示。
<<<<<<< HEAD
AAA
=======
BBB
>>>>>>> B
现在,您可以再次拆分这些文件,并将文件从分支B
重命名为V43__migrate.sql
,而不是合并这些文件。要删除模式之间的行,sed
可以按如下方式使用。
$ sed '/<<<<<<< HEAD/,/======/d' V42__migration.sql | sed '/>>>>>>> B/d' > V43__migration.sql
$ sed '/======/,/>>>>>>> B/d' V42__migration.sql | sed '/<<<<<<< HEAD/d' > V42__migration.sql
然后你可以提交这些更改。
$ git add V42__migration.sql V43__migration.sql
$ git commit
*NIX Tricks: [sed] Delete the lines lying in between two patterns
答案 2 :(得分:-1)
如果您不依赖于未合并分支上的分割提交,squash所有提交都会提交到单个提交。
您必须强制推送到您的分支git push -f
(旧的提交被覆盖并替换为新的提交)。
重命名未合并分支中的文件,并修改git commit --ammend
您的更改。修改也需要强制推动。
如果你没有压缩提交,这可能会更棘手。