Search code examples
phpdoctrine-ormzend-framework2database-versioning

Are there any best practices using Doctrine 2 migrations on different GIT branches?


I am working on Zend Framework 2 project with Doctrine 2 dependency. Source versioning is handle by GIT. We are using GitFlow as a branching model.

The problematic situation:

Migrations on Develop branch:
001.php
002.php
003.php
004.php

Migrations on Production branch:
001.php
002.php

Let's say I need to patch and I create migration 003.php on Production branch. I also have to cherry-pick the 003.php change to Develop branch that the final result would look like this:

Migrations on Develop branch:
001.php
002.php
*003.php*
003.php
004.php

Migrations on Production branch:
001.php
002.php
*003.php*

But here is the problem. If the current migration on Develop database was 004 and 003 was added so it will not be executed.

What is the best way to handle Doctrine 2 migrations?


Solution

  • I wrote a script to automate the process of migrating back all the diverging migrations in the current branch and migrating back up to the new branch you are checking out.

    The above link is for Symfony, but here it is modified for ZF2 (untested as I don't use ZF2):

    doctrine-checkout.sh

    #!/bin/bash
    
    # Commit ref of current HEAD
    start_commit="$(git rev-parse HEAD)"
    
    # Commit ref of what is to be checked out
    dest_commit="$1"
    
    # First common ancestor commit between the two branches
    ancestor="$(git merge-base HEAD "$dest_commit")"
    
    # Shorthand for `sudo -u nginx /home/user/project/public/index.php`
    # Modify this if you don't run `php public/index.php` as `nginx`
    appconsole="sudo -u nginx php $(git rev-parse --show-toplevel)/public/index.php"
    
    # Checkout the ancestor commit to find the first common migration between the
    # two branches.  Migrate backwards to this version.
    git checkout "$ancestor"
    ancestor_migration="$($appconsole migrations:latest)"
    git checkout "$start_commit"
    $appconsole migrations:migrate "$ancestor_migration"
    
    # Checkout the destination branch and migrate back up
    
    git checkout "$dest_commit"
    $appconsole migrations:migrate
    

    To use this, when you need to switch between feature branches, instead of running git checkout another-branch, do doctrine-checkout.sh another-branch.

    If you rebase your branches so they contain commits with migrations which were previously in another branch, this will cause difficulties checking out that branch again from another branch, since it may have more recently dated migrations some commits behind the migrations the branch adds. You can git rebase -i within your feature branch and edit the commit which adds a migration to rename the migration if this is the case.