Ingeniería

CHANGELOG.md: qué incluir y cómo mantenerlo al día

6 min de lectura

Un CHANGELOG.md es un archivo Markdown en la raíz de un repositorio que lista, para cada versión publicada, qué cambió en términos sobre los que un usuario del proyecto puede actuar. Lo leen quienes deciden si actualizar, quienes depuran después de actualizar, y los registros de paquetes y las herramientas de release que lo muestran en la página del proyecto. El formato que sigue la mayoría de los proyectos es el descrito en keepachangelog.com: la versión más reciente arriba, una sección Unreleased por encima, y las entradas agrupadas bajo Added, Changed, Deprecated, Removed, Fixed y Security.

SecciónQué va en ellaLínea de ejemplo
UnreleasedCambios fusionados pero todavía sin versión- La exportación ahora es en streaming; los archivos de más de 100 MB ya no agotan el tiempo de espera.
AddedCapacidad nueva al alcance del usuario- El flag \—dry-run` de `deploy` muestra el plan sin aplicarlo.`
ChangedComportamiento existente que ahora funciona distinto- El tiempo de espera por defecto sube de 30 s a 60 s.
DeprecatedSigue funcionando, programado para eliminarse- \legacyAuth()` se eliminará en la 3.0; usa `auth()`.`
RemovedDesaparece en esta versión- Se retira el soporte de Node 16.
FixedUn error con el que un usuario pudo toparse- La búsqueda ya no falla con consultas que contienen un guion.
SecurityCorrecciones por las que el lector debería actualizar hoy- Corregido un path traversal en el manejador de archivos estáticos (CVE pendiente).

¿Qué es un archivo CHANGELOG.md?

Es el historial legible por humanos de un proyecto, versión a versión, guardado junto al código para que viaje con él. Se diferencia de git log en el público y en la selección: el git log registra cada commit para las personas que los escribieron, mientras que el changelog registra los cambios que un usuario notaría, escritos para la persona que no los escribió. Un commit que renombra una variable interna no tiene línea en el changelog. Un commit que cambia un tiempo de espera por defecto sí la tiene, aunque el diff fuera un solo carácter.

El archivo vive en la raíz del repositorio con ese nombre exacto porque las herramientas lo buscan ahí. GitHub lo enlaza desde la página del repositorio, npm y PyPI lo muestran cuando va incluido en el paquete, y herramientas de release como release-please y semantic-release lo leen y lo escriben en el sitio. Un changelog.md en minúsculas o un CHANGES.md también sirven para las personas, pero algunas herramientas solo buscan el nombre canónico.

¿Qué aspecto tiene un CHANGELOG.md completo?

Un ejemplo corto y correcto vale más que una descripción larga. Este sigue la estructura de Keep a Changelog 1.1.0 y el versionado semántico para los números.

# Changelog

Todos los cambios notables de este proyecto se listan aquí.
Formato: Keep a Changelog. Versiones: Semantic Versioning.

## [Unreleased]

### Added
- El flag `--dry-run` de `deploy` muestra el plan sin aplicarlo.

## [2.3.1] - 2026-10-01

### Fixed
- La búsqueda ya no falla con consultas que contienen un guion.
  Roto desde la 2.3.0.

### Security
- Corregido un path traversal en el manejador de archivos
  estáticos. Actualiza hoy si sirves archivos subidos por usuarios.

## [2.3.0] - 2026-09-18

### Added
- Exportación en streaming. Los archivos de más de 100 MB ya no
  agotan el tiempo de espera.

### Deprecated
- `legacyAuth()` sigue funcionando pero se eliminará en la 3.0.
  Usa `auth()`.

[Unreleased]: https://github.com/acme/tool/compare/v2.3.1...HEAD
[2.3.1]: https://github.com/acme/tool/compare/v2.3.0...v2.3.1
[2.3.0]: https://github.com/acme/tool/compare/v2.2.0...v2.3.0

Cuatro detalles aportan la mayor parte del valor. Cada versión lleva una fecha en formato ISO, para que el lector pueda cruzarla con el momento en que empezó su problema. Cada encabezado de versión es un enlace a la vista de comparación, así que el diff completo está a un clic. Una corrección dice qué versión lo rompió. Y la sección Security va aparte, de modo que quien busca “¿tengo que actualizar ahora?” la encuentra en segundos.

¿Cómo se mantiene al día un CHANGELOG.md?

Escribe la línea en el mismo pull request que el cambio, bajo Unreleased, y mueve la sección a un encabezado de versión cuando publiques. Ese es todo el método. El archivo se queda desactualizado cuando la línea la escribe más tarde otra persona, en el momento del release, a partir de una lista de mensajes de commit que no redactó.

Dos cosas hacen que el hábito se mantenga. La primera es una comprobación en CI que haga fallar un pull request que toque src/ sin tocar el changelog, con una etiqueta para saltársela en cambios sin efecto visible para el usuario; exigir una entrada de changelog en CI muestra la versión de cuarenta líneas. La segunda es un paso de release que renombre Unreleased a la versión y la fecha con un solo comando, para que nadie tenga que acordarse de hacerlo a mano. Quién es realmente dueña de una entrada de changelog explica cómo los equipos resuelven de quién es el trabajo de escribir la línea.

¿Debería generarse el changelog a partir de los commits?

La generación te da un borrador completo; no te da un changelog. Las herramientas construidas sobre conventional commits, y la automatización de releases como release-please, leen los prefijos feat:, fix: y BREAKING CHANGE: y producen una lista agrupada con cada pull request enlazado. La lista es tan buena como los asuntos de los commits, y los asuntos de los commits describen el código.

El punto medio que funciona es generar y después editar. Deja que la herramienta cree la sección Unreleased a partir de los commits, y que el pull request de release reescriba las líneas que un usuario va a leer: el síntoma en lugar del nombre de la función, el ajuste que cambió en lugar del archivo que cambió. De conventional commits a changelog recorre el pipeline, y un generador de changelog en el navegador basta para sacar un borrador de un git log pegado sin instalar nada.

¿Qué no debería ir en CHANGELOG.md?

Refactorizaciones internas, actualizaciones de dependencias sin cambio de comportamiento, commits solo de tests, configuración de CI y cambios de formato. Pertenecen al historial de git, donde quien los necesite puede encontrarlos. Incluirlos entierra las líneas que importan y enseña a los lectores a saltarse el archivo.

Lo otro que hay que dejar fuera es la versión de marketing de un cambio. “Exportaciones ultrarrápidas” no le da al lector nada que pueda comprobar. “La exportación ahora es en streaming; los archivos de más de 100 MB ya no agotan el tiempo de espera” sí. El archivo es un documento de referencia, y su tono debe estar a la altura: líneas cortas, sustantivos concretos, una versión o fecha en todo. Keep a Changelog, en la práctica cubre las partes de la especificación que los equipos más a menudo omiten, y formatos de archivo de changelog cubre cuándo una fuente JSON o YAML junto al archivo Markdown se gana su sitio.

¿Un producto con página de changelog sigue necesitando el archivo?

Una librería sí, porque el archivo es lo que muestran los registros de paquetes y lo que un desarrollador lee sin conexión. Un producto SaaS sin artefacto instalable puede arreglarse solo con la página, ya que sus usuarios nunca ven el repositorio. Muchos equipos mantienen ambos: el archivo como registro de ingeniería, y una página de changelog pública que se escribe a partir de él para un público más amplio, con el detalle repartido como describe changelog vs. notas de versión. Si la página se alimenta del archivo, mantén el archivo como fuente de verdad y genera la página, para que haya un solo sitio donde editar.

FAQ

¿Cuál es la diferencia entre CHANGELOG.md y las notas de versión? El changelog es el registro completo y continuo de cada cambio notable, guardado en el repositorio. Las notas de versión son un mensaje sobre un lanzamiento, a menudo más corto y reescrito para un público más amplio. Muchos proyectos publican la sección del changelog de una versión como sus notas de versión.

¿Dónde debería vivir CHANGELOG.md? En la raíz del repositorio, con ese nombre exacto, para que GitHub, los registros de paquetes y las herramientas de release lo encuentren. Un monorepo guarda uno por paquete, junto al manifiesto de cada paquete.

¿Debería generar CHANGELOG.md a partir de los commits de git? Genera el borrador y luego edita las líneas que un usuario va a leer. Los mensajes de commit describen el cambio en el código; el changelog describe lo que nota un usuario. Herramientas como conventional-changelog y release-please dan un buen punto de partida.

¿Cada commit necesita una entrada en el changelog? No. Solo los cambios que un usuario del proyecto podría notar: capacidad nueva, comportamiento cambiado, deprecaciones, eliminaciones, correcciones y parches de seguridad. Las refactorizaciones, los cambios en tests y las ediciones de CI se quedan en el historial de git.


Las afirmaciones técnicas de este artículo no se han revisado de forma independiente. Si algo está mal, avísanos y lo corregiremos.

Relacionado en changeloop: Generador de changelog, Ejemplos de changelog

changeloop
El equipo que crea un changelog que cierra el círculo. Tus usuarios lo piden, tu equipo lo publica y quien lo pidió se entera.