256 lines
9.3 KiB
Markdown
256 lines
9.3 KiB
Markdown
# Git Flow
|
|
|
|
Herramienta para establecer un workflow siguiendo [Conventional Commits
|
|
(CC)](https://www.conventionalcommits.org), [Conventional Branch
|
|
(CB)](https://conventional-branch.github.io/), y [SemVer](https://semver.org/).
|
|
|
|
Esta diseñada para facilitar la creación de commits y branches en un formato estandar, que permite
|
|
derivar versiones automaticamente de los merges sobre ramas principales.
|
|
|
|
## Instalación
|
|
|
|
Para instalar Git Flow, se sugiere utilizar [pipx](https://github.com/pypa/pipx) (seguir la
|
|
documentación para instalarlo). Una vez instalado `pipx`, simplemente clonamos el repositorio en una
|
|
carpeta local, y lo instalamos:
|
|
|
|
```sh
|
|
cd ~/Downloads
|
|
git clone ssh://git@git.jonathanteran.dev:59169/jt/git-flow.git
|
|
cd git-flow
|
|
pipx install .
|
|
```
|
|
|
|
Luego podemos verificar que se haya instalado correctamente ejecutando: `git-flow -h`
|
|
|
|
Para actualizarlo, hacemos un pull de los cambios recientes del repositorio, y hacemos el upgrade
|
|
mediante `pipx`:
|
|
|
|
```sh
|
|
cd ~/Downloads/git-flow
|
|
git pull
|
|
pipx upgrade git-flow
|
|
```
|
|
|
|
## Configuración
|
|
|
|
Para poder usar la herramienta en un repositorio, necesitamos inicializarlo:
|
|
|
|
```sh
|
|
git-flow init
|
|
```
|
|
|
|
El comando solicitará 2 opciones:
|
|
|
|
- **Ramas principales**: Ramas que representan los entornos principales del proyecto. Por ejemplo:
|
|
`dev,test,prod`.
|
|
- **Remoto** (opcional): Nombre del remoto que se usará para crear PRs, y taggear merges
|
|
automáticamente. Por el momento, se soportan los siguientes remotos:
|
|
|
|
- [x] Bitbucket
|
|
- [x] Github
|
|
- [x] Gitea
|
|
- [x] Gitlab
|
|
|
|
La configuración del remoto requiere tener un Access Token para poder crear los PRs y tags
|
|
automáticamente. Ver la sección [Remotos soportados](#remotos-soportados) para las instrucciones
|
|
de cómo generar el token en cada proveedor.
|
|
|
|
Una vez generado, el token se debe guardar dentro del repositorio a configurar, en el archivo
|
|
`.repository-token`. De no especificarse, los merges y tags se harán de forma local.
|
|
|
|
## Utilización
|
|
|
|
Git Flow cuenta con los siguientes comandos para guiar el workflow (ver `git-flow <command> -h` para
|
|
más información):
|
|
|
|
- `init`: Inicializa el repositorio para utilizar git-flow (ramas principales y remoto).
|
|
- `new`: Crea una nueva rama siguiendo CB.
|
|
- `commit`: Crea un commit siguiendo CC.
|
|
- `merge`: Mergea la rama actual a una de las ramas principales.
|
|
- `tag`: Crea un tag sobre el ultimo merge siguiendo SemVer (ver [Tag](#tag)).
|
|
- `release`: Prepara la rama actual para pasarse al siguiente entorno configurado.
|
|
- `branch ls`: Lista las ramas del repositorio, agrupadas por entorno objetivo.
|
|
|
|
El workflow para el cual se penso la herramienta es el siguiente:
|
|
|
|
1. Sobre la primer rama principal configurada (por ejemplo, `dev`), se crea una nueva rama con
|
|
`git-flow new`
|
|
2. Se realizan cambios y se commitean los mismos con `git-flow commit` (se repite hasta que se
|
|
considere que la rama esté lista para mergear)
|
|
3. Se ejecuta `git-flow merge` para mergear la rama al entorno que corresponda (en este caso,
|
|
`dev`). En caso de tener un remoto configurado, el comando crea un PR para integrar el cambio. Si
|
|
no, simplemente se ejecuta un `git merge` simple.
|
|
4. Para versionar este último merge, se ejecuta `git-flow tag`, ya sea localmente o desde un
|
|
pipeline para que se ejecute en cada merge.
|
|
5. Una vez que la rama fue correctamente integrada a un entorno (por ejemplo, `dev`), se usa
|
|
`git-flow release` para crear una nueva rama para integrar unicamente los cambios de esa rama
|
|
sobre el siguiente entorno (por ejemplo, `test`). Si la rama original era
|
|
`feature/my-new-feature`, se crea la rama `release/test/feature/my-new-feature` sobre `test` que
|
|
tiene los cambios de la rama original.
|
|
|
|
En cualquier momento se puede usar `git-flow branch ls` para ver en qué entorno está cada rama, y cuáles
|
|
están todavía en progreso (`wip/`) o descartadas (`trash/`).
|
|
|
|
### Tag
|
|
|
|
`git-flow tag [--target=<RAMA>] [--token=<TOKEN>] [--update-changelog]`
|
|
|
|
- `--target`: rama principal sobre la que se taggea. Por defecto, la rama actual. Debe ser una de las
|
|
ramas principales configuradas.
|
|
- `--token`: Access Token del remoto. Si se pasa, se asume que corre en un pipeline: los commits y el
|
|
último tag se obtienen por API del remoto y el tag se crea en el remoto (y también localmente). Si
|
|
no, se usa `.repository-token` y todo se resuelve localmente.
|
|
- `--update-changelog`: genera la entrada correspondiente en `CHANGELOG.md` y la commitea antes de
|
|
taggear (en un pipeline, además hace push del commit).
|
|
|
|
Comportamiento:
|
|
|
|
- El tag se crea sobre el último merge (first-parent) de la rama. Si ese merge ya tiene un tag, no se
|
|
hace nada.
|
|
- La versión se calcula a partir de los tipos de commit (CC) del último merge. Si ningún commit
|
|
implica un salto de versión, se avisa y el comando termina con código de salida 1.
|
|
- Con más de un entorno configurado, cada rama versiona por separado con el nombre del entorno como
|
|
sufijo (por ejemplo, `v1.2.0-prod`). Con un solo entorno no se agrega sufijo.
|
|
|
|
## Remotos soportados
|
|
|
|
Cada remoto necesita un Access Token con permisos para crear Pull/Merge Requests y tags. El token se
|
|
guarda en el archivo `.repository-token` en la raíz del repositorio (una única línea con el valor del
|
|
token), o se pasa por parámetro con `--token=<TOKEN>` al comando `git-flow tag` (útil para no
|
|
commitear el token y usarlo solo desde un pipeline mediante una variable secreta).
|
|
|
|
### Github
|
|
|
|
1. Ir a *Settings* del repositorio (o de la organización) > *Developer settings* > *Personal access
|
|
tokens* > *Fine-grained tokens* > *Generate new token*.
|
|
2. Seleccionar el repositorio sobre el que se va a usar `git-flow`.
|
|
3. En *Repository permissions*, otorgar:
|
|
- **Contents**: Read and write (necesario para crear tags).
|
|
- **Pull requests**: Read and write (necesario para crear PRs).
|
|
4. Generar el token y guardarlo en `.repository-token`.
|
|
|
|
Ejemplo de pipeline (GitHub Actions) para taggear automáticamente en cada push a una rama principal:
|
|
|
|
```yaml
|
|
# .github/workflows/tag.yml
|
|
name: Tag and publish
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
tag:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: astral-sh/setup-uv@v3
|
|
|
|
- run: uv run git-flow tag --token=${{ secrets.GIT_FLOW_TOKEN }}
|
|
|
|
- run: uv build
|
|
- run: uv publish --token=${{ secrets.PYPI_TOKEN }}
|
|
```
|
|
|
|
### Gitlab
|
|
|
|
1. Ir a *Settings* > *Access Tokens* del proyecto (o *Group access tokens* si se quiere usar a nivel
|
|
grupo).
|
|
2. Crear un token con rol **Developer** o superior, y los scopes:
|
|
- **api** (o al menos `write_repository` para tags y `api` para Merge Requests).
|
|
3. Generar el token y guardarlo en `.repository-token`.
|
|
|
|
Ejemplo de pipeline (GitLab CI) para taggear automáticamente en cada push a una rama principal:
|
|
|
|
```yaml
|
|
# .gitlab-ci.yml
|
|
tag:
|
|
image: python:3.14
|
|
rules:
|
|
- if: $CI_COMMIT_BRANCH == "main"
|
|
script:
|
|
- pip install uv
|
|
- uv run git-flow tag --token=$GIT_FLOW_TOKEN
|
|
- uv build
|
|
- uv publish --token=$PYPI_TOKEN
|
|
```
|
|
|
|
El token debe guardarse como variable protegida y enmascarada (`GIT_FLOW_TOKEN`) en *Settings* >
|
|
*CI/CD* > *Variables*.
|
|
|
|
### Bitbucket
|
|
|
|
1. Ir a *Repository settings* > *Access Tokens* > *Create access token* (o *Workspace settings* >
|
|
*Access Tokens* para un token a nivel workspace).
|
|
2. Otorgar permiso de **Write** en *Pull requests* y *Repositories* (necesario para crear tags).
|
|
3. Generar el token y guardarlo en `.repository-token`.
|
|
|
|
Este mismo repositorio usa Git Flow para el taggeo automático usando Bitbucket Pipelines, se puede
|
|
ver el archivo `bitbucket-pipelines.yml` como ejemplo:
|
|
|
|
```yaml
|
|
# bitbucket-pipelines.yml
|
|
image: python:3.14
|
|
|
|
pipelines:
|
|
branches:
|
|
'main':
|
|
- step:
|
|
name: "Tag and publish package"
|
|
caches:
|
|
- pip
|
|
script:
|
|
- pip install uv
|
|
- uv run git-flow tag --token=$BEARER
|
|
- uv build
|
|
- uv publish --token=$PYPI_TOKEN
|
|
```
|
|
|
|
El token se configura como variable segura del repositorio (`BEARER`) en *Repository settings* >
|
|
*Repository variables*.
|
|
|
|
### Gitea
|
|
|
|
1. Ir a *Settings* del usuario (o de la organización) > *Applications* > *Manage Access Tokens* >
|
|
*Generate New Token*.
|
|
2. Otorgar permiso de escritura sobre:
|
|
- **repository** (necesario para crear tags).
|
|
- **issue** (necesario para crear PRs, ya que Gitea expone los PRs bajo el mismo scope).
|
|
3. Generar el token y guardarlo en `.repository-token`.
|
|
|
|
Ejemplo de pipeline (Gitea Actions) para taggear automáticamente en cada push a una rama principal:
|
|
|
|
```yaml
|
|
# .gitea/workflows/tag.yml
|
|
name: Tag and publish
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
tag:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: astral-sh/setup-uv@v3
|
|
|
|
- run: uv run git-flow tag --token=${{ secrets.GIT_FLOW_TOKEN }}
|
|
|
|
- run: uv build
|
|
- run: uv publish --token=${{ secrets.PYPI_TOKEN }}
|
|
```
|
|
|
|
## Taggeo automático por pipeline
|
|
|
|
En todos los casos, `git-flow tag` detecta que se está ejecutando desde un pipeline (no encuentra
|
|
`.repository-token` en el repositorio) y usa el token pasado por `--token=<TOKEN>` tanto para crear
|
|
el tag en el remoto como para pushear el commit del `CHANGELOG.md` generado, en vez de crear el tag
|
|
únicamente en forma local como sucede al ejecutarlo manualmente sin remoto configurado.
|