En sistemas con muchas dependencias, lanzar una nueva versión puede convertirse en algo muy complejo. Si las especificaciones de dependencias están muy rígidas, puedes correr el riesgo de sufrir una version lock, lo que produce la incapacidad de actualizar un paquete sin tener que liberar nuevas versiones de cada paquete dependiente. Si las dependencias están muy sueltas, las versiones futuras corren el riesgo de ser demasiado compatibles con las versiones anteriores. Cualquiera de las dos situaciones anteriores evitan que puedas avanzar un proyecto de forma segura hacia delante.
Las siguientes reglas están documentadas en semver.org, para que funcionen primero se ha de declarar una API pública. Esto puede consistir en documentación o en la aplicación del mismo código. Sea cual sea la forma, es importante que esté clara y sea precisa. Las versiones se establecen en este formato: MAJOR.MINOR.PATCH, por ejemplo: 3.1.2. Las soluciones de bugs incrementan la versión PATCH del API, cambios o adiciones compatibles con versiones anteriores suponen un incremento de una versión MINOR, y cambios del API incompatibles con versiones anteriores incrementan la versión MAJOR.
Este sistema se denomina Semantic Versioning. Las especificaciones se dictan a continuación:
- Un software que utilice Semantic Versioning debe declarar una API pública.
- Una versión normal ha de ser del estilo X.Y.Z, sin ser números negativos, y sin que les preceda un 0. X es la MAJOR version, Y es la MINOR version, y Z es la PATCH version. Cada elemento debe incrementar de forma numérica: 1.9.0 => 1.10.0 => 1.11.0.
- Una vez que se ha lanzado un paquete, los contenidos de esa versión no deben ser modificados. Cualquier modificación debe ser liberada como una nueva versión.
- Una MAJOR version 0: 0.y.z es para el desarrollo inicial. Cualquier cosa puede cambiar en cualquier momento. La API pública no debería ser considerada estable.
- La versión 1.0.0 define la API pública. La forma en la que el número de la versión se incrementa después de este lanzamiento depende de esta API pública y cómo evoluciona.
- La versión PATCH Z (x.y.Z, con X > 0) debe ser incrementada sólo si los arreglos de bugs son compatibles con versiones anteriores. Un arreglo de bug se define como un cambio interno que soluciona un comportamiento incorrecto.
- La versión MINOR Y (x.Y.x con X > 0) debe incrementarse si nuevas funcionalidades compatibles con versiones anteriores se introducen en la API pública. Debe incrementarse si cualquier funcionalidad de la API pública se ha marcado como DEPRECATED. Puede incrementarse si nuevas funcionalidades o mejoras se introducen dentro del código interno. Puede incluir cambios del nivel de PATCH. La versión PATCH debe resetearse a 0 cuando se incrementa la MINOR version.
- La versión MAJOR X (X.y.z con X > 0) debe incrementarse si se producen cambios incompatibles con versiones anteriores en el API. Puede incluir cambios de nivel MINOR y PATCH, las cuales han de resetearse a 0 cuando la MAJOR incrementa.
- Se puede indicar un pre-lanzamiento (pre-release) con un guión seguido de varios identificadores separados por puntos, que han de ser caracteres alfanuméricos ASCII. Los identificadores numéricos no pueden ir precedidos de un 0. Una versión de pre-release indica que la versión no es estable. Ejemplos: 1.0.0-alpha, 1.0.0-0.4.5, 1.0.0-x.7.z92.
- Se pueden indicar metadatos añadiendo un signo + seguido de identificadores separados por puntos. Ejemplos: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85.
- La precedencia hace referencia a cómo las versiones se comparan unas con otras cuando se ordenan. La precedencia debe calcularse separando la versión en MAJOR, MINOR, PATCH e identificadores pre-release en ese orden (los metadatos no entran). Se comparan de izquierda a derecha, MAJOR, MINOR y PATCH siempre de forma numérica: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1. Cuando MAJOR, MINOR y PATCH son iguales, una versión pre-release tiene una precedencia menor que una versión normal, por ejemplo 1.0.0-alpha < 1.0.0. La precedencia entre dos versiones pre-release con las mismas versiones MAJOR, MINOR y PATCH deben determinarse comparando cada identificador separado por un punto de izquierda a derecha de la siguiente forma: los identificadores que consisten sólo en dígitos se comparan numéricamente, y los identificadores que son letras o guiones se comparan léxicamente en orden ASCII. Los identificadores numéricos siempre tienen una precedencia menor que los identificadores no numéricos. Una versión pre-release más larga tiene más precedencia que uno más pequeño, ejemplos: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0.