How to manage Migrations in a project with multiple branches?
There is a much better solution for handling entity framework migration merge conflicts on a similar question.
All you need to do after a merge is to re-scaffold the meta data of the migration in the target branch. That is you do not rescaffold the up/down code, just the state in the resx-file.
add-migration [the_migration_to_rescaffold_metadata_for]
This almost always works. The procedure will fail if a different migration in the merge have changed the database in such a way that the migration is no longer runnable or gives an unexpected result. That being said - I believe that to be a very rare case as most migrations should be auto-generated, or at least not be dependent on other tables that are not changed in the migration itself as well.
One such case where rescaffold state would fail could be:
Column foo is an int and rows contain [0, 1, 2]
Migration A from branch A change foo to boolean (0 will become false automatically and > 0 will become true)
Migration B from branch B change foo to string. It expects it to be an int but it is a boolean, the migration will succeed though. Data will be lost since when migration B was created the rows would contain ["0", "1", "2"]. When migration A altered column to boolean (and did so successfully and with expected result) the rows will now contain ["0", "1", "1"] instead and Migration B will have a different end result than what was observed in Branch B.
There are probably more edge cases where things could go wrong with the solution. But if migrations up/down code is not dependent on things changed by another migration in the merge it should work well to just update the metadata in the migrations.
Edit: a colleague of mine discovered an easier with to do this, I left my original answer at the bottom for completeness.
(VERY IMPORTANT) migrations in live environment must not conflict with ones in your current branch, otherwise you need to redo all your migrations and resolve data model change conflicts by hand.
- restore your development database with live environment data
- run
update-database
, it should run migrations from your branch, and complain about 'unable to update database to match the current model blah blah..' - run
add-migration MergeBranchBToMaster -ignoreChanges
, this will create an empty migration. - run
update-database
again - push your changes
The magic in step 3 basically tells EF to shutup about mismatched models, hence be very sure that your migrations do not conflict with ones in live environment. If they do, you can always create SQL scripts for pushing the missing migrations (which is actually the preferred method).
Original Answer
I have found a fairly straight-forward solution based on @Ladislav Mrnka's answer. This will work with live environment[1], you just have to be careful not to change any deployed migrations.
Before Merge, take note of the migration you added (MyMigration), and its previous migration (BaseMigration)
Merge branches in git
Open Package Manager Console, and run: UPDATE-DATABASE -TargetMigration:BaseMigration. This will revert your database to the state before any of the conflicted migrations are applied
Delete your local migration (MyMigration)
Run: UPDATE-DATABASE. This will apply all newer migrations done in other branches.
Run: ADD-MIGRATION MyMigration. This will re-generate your local migration based on current state of database, like git -rebase.
Run: UPDATE-DATABASE. Update database with you local migration.
This also works if you have multiple local migrations, but it will merge them all into a single one.
[1] by working with live environment, I mean that the generated migration can be applied to live environment which may already have some/all of the other branches' migrations applied. The steps themselves are purely for development purpose.
Merging migrations is IMHO manual task. Part of migration code is auto-generated and we usually don't merge auto-generated code - instead we run autogeneration again after the merge.
Until ADO.NET team provides some recommendation I would follow simple principle:
- Before you do the merge revert the master database to the version used prior to branching
- Merge your branches
- Exclude migration classes created after branching from merged assembly
- Add a new migration for merged code base which will migrate your database in the state prior to branching to the state after merging branches
- If your excluded migration classes contain some customization merge them to the new migration class
- Run migration to migrate your database to current merged version
If your branches contained multiple migration steps (version) you will lose them and you will end with two versions - prior to branching and after merging.
Edit:
It will not work in live environment. The problem here would be the development process itself. If you have live environment you should keep its branch untouched (except minor bug fixes). If you continue development in that branch with production deployment and in the same time you build another version in separate branch without continuous integration (= continuous merging changes back to the main branch to integrate your new development with the main code base) you have a big problem. I think migrations in general cannot handle this.
The only option in such case would probably be removing all migrations from merged solution and deleting MigrationHistory
table from the database. Than you can enable migrations on the project again and add initial migration to use your current database as starting point = no way back to previous version because no information about previous migrations will exist.