通过重命名其中一个文件

时间:2017-07-05 11:44:45

标签: git merge merge-conflict-resolution

我使用Flyway跟踪数据库更改,并使用git进行版本控制。

Flyway依赖于迁移脚本,每次迁移都会以越来越多的数字命名。

现在我遇到以下情况:在两个独立的分支上开发了两个功能(让他们称之为A和B),这两个功能都需要更改数据库。两个开发人员都为其分支创建了数据库的迁移脚本。当他们几乎同时分出master时,他们都为迁移脚本分配了相同的文件名:V42__migration.sql

现在分支A合并为主人。合并分支B时,由于V42__migration.sql文件导致合并冲突。解决此冲突的正确解决方案是将分支B的迁移脚本重命名为V43__migration.sql。但是,在合并时,git尝试将两个文件合并为一个,其中我实际上需要两个文件不变,但是一个重命名。

解决这种合并的最佳方法是什么?与git冲突?

3 个答案:

答案 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)

您的分支AB都包含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您的更改。修改也需要强制推动。

如果你没有压缩提交,这可能会更棘手。