# Convención Git
Al igual que otras guías de estilo de programación, los temas tratados abarcan
no sólo cuestiones estéticas de formato, sino también otros tipos de
convenciones o estándares de codificación. Sin embargo, este documento se centra
principalmente en las reglas estrictas y rápidas que seguimos universalmente y
evita dar consejos que no sean claramente aplicables (ya sea por humanos o
herramientas).

Este documento sirve como la definición completa de los estándares de GIT para
El Tiempo ADS. Un Repositorio se podrá describir como
_**Estilo CEET**_ si y sólo si se adhiere a las reglas en este documento.
## Tabla de contenido
[Toc]
## Branches
* Usa nombres cortos y descriptivos.
* El nombre descriptivo de la rama debe ser imperativo.
* Los identificadores de problemas, bugs, Historias de Usuario o tickets podrán
ser referenciadas en el nombre de sus ramas.
* Nombra tus ramas en minúscula, a excepción de identificadores externos.
* Usa guiones para separar las palabras.
```bash
# bien
git checkout -b ADP15-migración-del-api
git checkout -b ADP15-mejorar-performance-componente-x
git checkout -b ADP15-refactor-redux-of-auth-module
# mal - Poco descriptivo
git checkout -b arreglo_sencillo
git checkout -b ADP15-solucionar-bug
```
* En caso de que varios desarrolladores colaboren en una misma característica,
es conveniente tener ramas personales para cada miembro del equipo y una para
el equipo entero. en tales casos usar la siguiente convención.
```bash
git checkout -b ADP15-feature-x/master # Branch del equipo entero
git checkout -b ADP15-feature-x/maria # Branch personal de María
git checkout -b ADP15-feature-x/nick # Branch personal de Nick
```
Se pueden hacer integraciones o `merges` desde las `branches` personales
al `branch` del equipo (
ver ["Merging"](#Merging)). Eventualmente, el `branch` del equipo será integrado
a "master".
Elimina tú `branch` del repositorio remoto después de haber sido integrado a
menos que haya una razón especifica de no hacerlo.
_Consejo: Usa el comando a continuación desde "master" para mostrar branches
integrados:_
```bash
git branch --merged | grep -v "\*"
```
## Commits
* **Cada commit debe de estar compuesto por un sólo cambio lógico**
No debes de tener varios cambios lógicos en un commit. Por ejemplo, si un cambio
corrige un error y, a la vez, optimiza el rendimiento de un aspecto de la
aplicación, debes separarlo en dos commits.
_Consejo: Usa `git add-p` para interactivamente montar/stage partes específicas
de los archivos modificados._
* **No separes un sólo cambio lógico en varios commits**
Por ejemplo, una nueva implementación junto con sus pruebas o tests
correspondientes deben de estar en el mismo commit.
* **Realiza commits temprano y frecuentemente**
Commits que son pequeños y autónomos son más fáciles de entender y revertir si
algo sale mal.
* **Los commits deben de ser ordenados lógicamente**
Por ejemplo, si el commit A depende de los cambios hechos en commit B, entonces,
el commit B debe de realizarse antes del commit A.
_Nota: En caso de estar trabajando sólo en un branch local que (no se ha
integrado*, es totalmente aceptable de usar commits para capturar el estado de
tu trabajo. Sin embargo, sigue siendo cierto que los reglas descritas
previamente aplican antes de su integración.)_
### Mensajes
* **Usa tu editor y no tu terminal cuando escribes un mensaje para el commit**
Realizar commits desde la terminal fomenta la mentalidad de que es necesario
hacer que quepa todo en una sola linea lo cual usualmente resulta en mensajes
ambiguos y poco informativos.
```bash
# bien
git commit
# mal
git commit -m "Corrección rápida"
```
#### Estructura del mensaje
Tenemos reglas muy precisas sobre cómo se pueden formatear nuestros mensajes de
confirmación de git. Esto conduce a mensajes más legibles que son fáciles de
seguir al revisar el historial del proyecto . Pero también, usamos los mensajes
de confirmación de git para generar el registro de cambios.
> La especificación de [Conventional Commits][Conventional-Commits] es una
convención liviana que se aplica a los mensajes de los commits.
Esta especificación proporciona un conjunto fácil de reglas para crear un
historial de commits explícito ajustada a [SemVer](http://semver.org/),
al describir las características, correcciones y cambios que rompen la
compatibilidad en los mensajes de los commits.
>
> [Conventional Commits v1.0.0][Conventional-Commits]
##### Formato de mensaje de confirmación
Cada mensaje de confirmación consta de un encabezado , un cuerpo y un pie de
página. El encabezado tiene un formato especial que incluye un tipo , un alcance
y un asunto:
```tex=
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
Ejemplos:
* [Ejemplos Conventional Commits][Conventional-Commits-Examples]
* [Ejemplos Angular Commits][Angular-Commits]
##### Revert
Si el commit revierte un commit anterior, debe comenzar con `revert:`, seguido
del asunto del commit revertido. En el cuerpo deberá
decir: `Esto revierte el commit <hash>` donde el hash es el `SHA` del commit que
se revierte.
##### Tipos
Dependiendo del contexto de las aplicaciones pueden haber más o menos que los
señalados a continuación:
* **fix:** DEBE ser usado cuando el commit soluciona un error en el código de la
aplicación.
* **feat:** DEBE ser usado cuando un commit agrega una nueva característica a la
aplicación.
* **build:** DEBE ser usado cuando los cambios afecta el sistema de compilación
o dependencias de la aplicación.
* **ci:** DEBE ser usado cuando los cambios afectan los archivos de
configuración relacionados con sistema de
**integración continua**.
* **docs:** DEBE ser usado cuando los cambios afectan únicamente a la
documentación.
* **perf:** DEBE ser usado cuando los cambios mejoran el rendimiento.
* **refactor:** DEBE ser usado cuando el código **no** corrige un error, **ni**
agrega una característica.
* **style:** DEBE ser usado cuando los cambios no afectan el significado del
código (espacios en blanco, puntos y comas, formato... etc).
* **test:** DEBE ser usado para agregar pruebas unitarias adicionales, o
corregir pruebas existentes.
Todos los tipos antes mencionados PUEDEN ser acompañados de un alcance para su
mejor comprensión.
###### Alcance
Es el nombre del Módulo afectado (cómo lo percibe la persona que lee el registro
de cambios a partir de los commits)
A continuación, se muestra una lista de posibles alcances:
* Authentication
* Authorization
* Utils
* Commons
* Core
* Users
* Permissions
* Roles
* Lang
* Campaigns
* Advertisers
* Advertisements
* Docs: Se puede usar para cambios relacionados con la documentación oficial
dentro del directorio del proyecto o librería.
###### Asunto
La primera linea del mensaje de commit, debe ser descriptiva y concisa.
Idealmente, esta línea no debe de tener más de 50 caracteres. Debe de ser
capitalizada y escrita en el imperativo. No es necesario que termine en punto
final, puesto que sirve como el título del commit.
```tex=
# bien - modo imperativo, usa mayúsculas y tiene menos de 50 caracteres
Marcar registros como obsoletos tras falla
# malo
arreglé ActiveModel::Mensajes de error cuando AR fue usado correctamente
```
###### Cuerpo
Después del título debe ir una línea en blanco seguida por una descripción más
completa del commit. Cada línea debe de tener 72 caracteres o menos y debe de
explicar la razón por la cual el cambio es necesario, cómo rectifica el problema
y qué efectos secundarios puede tener.
También debe proporcionar cualquier recurso relacionado (por ejemplo, un enlace
al issue correspondiente en el bug tracker):
Al final cuando escribes el mensaje de un commit, piensa sobre qué necesitarías
saber si te encuentras con este commit después de un año.
###### Dependencias
Si un commit A depende de commit B, la dependencia debe de ser escrita en el
mensaje de commit A refiriéndote a commit B por su respectivo hash de SHA1.
Del mismo modo, si un commit A corrige un error introducido por commit B, este
también se debe de indicar en el mensaje de commit A.
Si un commit ha de entrar al proceso de squash con respecto a otro commit, usa
--squash y --fixup respectivamente, con el fin que la intención sea clara:
_Consejo: Usa `--autosquash` al realizar un rebase.(Los commits marcados
entrarán al proceso de squash automáticamente.)*_
##### Ejemplo
```tex=
docs: Resumen corto de no más de 50 caracteres.
Texto opcional detallando aspectos del cambio en el commit donde
cada linea debe tener un máximo de 72 caracteres. En ciertas
situaciones, la primera linea del mensaje se trata como el asunto de
un correo electrónico y el resto del mensaje como su cuerpo. La
línea en blanco que separa el resumen del cuerpo es crítica (a menos
que se omita el cuerpo en su totalidad), ya que herramientas como
rebase se pueden llegar a confundir si ambas partes están juntas.
Párrafos adicionales vienen después de líneas en blanco.
- Se pueden crear listas las cuales consisten de un guión o un
asterisco seguido por un sólo espacio y con lineas en blanco entre sí.
Vínculos a recursos relacionados pueden ser agregados al final del
mensaje:
Corrige: #APD56, #78
Véase también: #ADP12, #34
Fuente http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
```
## Merging
* **No reescribas el historial ya publicado**
El historial de un repositorio es muy valioso, ya que muy importante poder saber
qué ocurrió exactamente en un momento dado. Alteraciones al historial es una
fuente común de errores para todos aquellos trabajando en el proyecto.
Sin embargo, existen casos legítimos en los cuales reescribir el historial es
aceptable. Estos casos son cuando:
* Tú eres el único trabajando en la branch y la branch no será revisada.
* Tú quieres reorganizar tu branch (p. ej. squash commits) y/o hacer un rebase
de tu branch con respecto a "master".
Dicho esto, nunca reescribas la historia del branch "master" o de cualquier otro
branch especial como aquellos usados en producción o en los servidores de
control de calidad.
* **Mantén el historial limpio y simple**
Antes de someter tu branch a un merge:
* Asegúrate que se acomoda a la guía de estilo escogida para el proyecto y
realiza las acciones necesarias en caso de que no se acomode.
* Haz un rebase con respecto al branch que ha de recibir el merge:
```bash
[mi-branch] $ git fetch
[mi-branch] $ git rebase origin/master
# Ahora haz el merge
```
Esto resulta en un branch que puede ser directamente aplicado al final del
branch "master" lo cual simplifica el historial del proyecto.
_Nota: Esta estrategia es más adecuada para proyectos con branches de corta
duración. Si no es así, es posible que sea mejor ocasionalmente hacer un merge
en vez de un rebase con la branch "master"._
* Si tu branch incluye más de un commit, no hagas un merge con fast-forward:
```bash
# bien - asegura que un commit del merge sea creado
git merge --no-ff mi-branch
# mal
git merge mi-branch
```
## Notas adicionales
* Existen varios estilos, flujos de trabajo o workflows y cada uno tiene sus
fortalezas y debilidades. El hecho de que un workflow encaje con un proyecto
en específico depende del equipo, de aspectos del proyecto en sí y de tus
procesos de desarrollo.
Dicho esto, es importante elegir y mantener un workflow específico.
* El tener un estilo constante en el repositorio hace que sea fácil entender lo
que está pasando a través del log o registro.
* Prueba/crea tests antes del push. No hagas un push con un trabajo no
terminado.
* Usa Tags Anotadas para marcar lanzamientos/releases u otros puntos importantes
en el historial.
* Usa Tags Ligeras para uso personal, como para marcar commits y facilitar su
búsqueda en el futuro.
* Mantén tus repositorios en buenas condiciones al hacerles mantenimiento
ocasionalmente:
* [git-gc(1)](http://git-scm.com/docs/git-gc)
* [git-prune(1)](http://git-scm.com/docs/git-prune)
* [git-fsck(1)](http://git-scm.com/docs/git-fsck)
## Referencias
* [Conventional Commits][Conventional-Commits]
* [Guía de contribución de Angular][Conventional-Commits]
* [Guia de estilos GIT por jeko2000][Jeko2000]
* [Guia de estilos GIT Reaction Commerce][Reaction Commerce]
* [Palabras clave para usar en RFC para indicar niveles de requisitos][RFC2119]
[Conventional-Commits]: https://www.conventionalcommits.org "Conventional commits"
[Conventional-Commits-Examples]: https://www.conventionalcommits.org/es/v1.0.0-beta.3/#ejemplos
"Conventional commits example"
[Angular-contributing-guide]: https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md "Guía de contribución de Angular"
[Angular-Commits]: https://github.com/angular/angular/commits/master "Commits Angular"
[Jeko2000]: https://github.com/jeko2000/git-style-guide/#mensajes "git-style-guide"
[RFC2119]: https://www.ietf.org/rfc/rfc2119.txt "Palabras clave para usar en RFC para indicar niveles de requisitos"
[Udacity]: https://udacity.github.io/git-styleguide/ "Udacity Git Style guide"
[Reaction Commerce]: https://docs.reactioncommerce.com/docs/git-style-guide