Este es un tema que curiosamente para mi muchos equipos no tienen incorporado como práctica. A mi parecer en la actualidad la estrategia más común para esto es lo que desde hace años comenzó a hacer Ruby on Rails:
- escribir los scripts incrementales de actualización de la base siguiendo una convención de naming incremental (números secuenciales o timestamp invertidos). Estos scripts al ser texto plano se pueden almacenar naturalmente en el repositorio de código junto al código de la aplicación
- por otro lado se agrega una tabla en la propia base de datos para llevar registro de los scripts aplicados lo cual determina la versión de la base de datos.
En el caso de Ruby on Rails, uno debe encargarse de escribir los scripts (para escribir los puede usar un DSL en lugar de sql) y luego el propio framework brinda funcionalidades para crear la tabla de versión, ejecutar los scripts y llevar control de su ejecución. No estoy seguro si Rails fue el primer framework en implementar esta estrategia pero en la actualidad existen diversas herramientas en distintos lenguajes que la implementan como ser: FluentMigrator (con foco en C#), LiquidBase (con foco en Java/Grails).
Una herramienta que implementa esta estrategia y con la que he estado trabajando este último tiempo es Flyway, les comparto un video que muestra su uso y explica algunos detalles.
En mi trabajo usamos «Liquibase» y nos está dando buenos resultados.