Capítulo 32 de 33 12 secciones 8 min

El proyecto final

Junta todo el libro en un repositorio que puedas enseñar

<strong>Un repositorio que se pueda abrir, entender y ejecutar en treinta segundos.</strong> Eso son siete piezas: README con instrucciones, <code>.gitignore</code>, licencia, historia de commits legible, al menos una rama fusionada, una versión etiquetada y una revisión automática. Este capítulo las monta todas sobre el proyecto de ventas que venimos usando, y al final tienes algo que sirve como portafolio de verdad.

Treinta y un capítulos después, toca juntarlo. Y no en un resumen: en un repositorio que puedas mandar por WhatsApp y que hable bien de ti 🏆

Las siete piezas

PiezaCapítuloQué demuestra
README con instrucciones18Que piensas en quien llega
.gitignore9Que sabes qué no va
Licencia16Que sabes lo que estás publicando
Commits legibles5Cómo trabajas
Una rama fusionada10Que no trabajas todo en main
Una versión etiquetada24Que piensas en quien lo usa
Revisión automática31Que compruebas lo que entregas

Paso 1: la base

mkdir ventas-miss-yera
cd ventas-miss-yera
git init -q
printf 'ciudad,monto\nLima,1200\nArequipa,890\nCusco,760\n' > ventas.csv
printf 'API_KEY=no-deberia-estar-aqui\n' > .env
printf '.env\n__pycache__/\n' > .gitignore
git add ventas.csv .gitignore
git commit -q -m "Primeras ventas por ciudad"
git status --short
git ls-files
.gitignore
ventas.csv

Fíjate en que el .env existe en la carpeta y no está en la lista. Primera pieza colocada 🚫

Paso 2: el README y la licencia

cat > README.md <<'FIN'
# Ventas Miss Yera

Calcula el total de ventas por ciudad a partir de un CSV.

## Necesitas
- Bash

## Usar
```
bash total.sh ventas.csv
```

Devuelve el monto total de todas las ciudades.
FIN
printf 'MIT License\n\nCopyright (c) 2026 Gera Flores\n' > LICENSE
git add README.md LICENSE
git commit -q -m "Se agregan el README y la licencia MIT"
git ls-files
.gitignore
LICENSE
README.md
ventas.csv

Paso 3: el trabajo, en su rama

git switch -q -c calcula-el-total
cat > total.sh <<'FIN'
tail -n +2 "$1" | cut -d, -f2 | paste -sd+ | bc
FIN
git add total.sh
git commit -q -m "Se agrega el calculo del total por ciudad

Lee el CSV, se salta la cabecera y suma la segunda columna."
bash total.sh ventas.csv
git log --oneline
2850
409858b Se agrega el calculo del total por ciudad
75bc321 Se agregan el README y la licencia MIT
533e566 Primeras ventas por ciudad

Funciona. Y el commit tiene cuerpo, que es lo que va a leer quien mire tu historia dentro de un año 📖

Paso 4: fusionar dejando rastro

git switch -q main
git merge -q --no-ff -m "Entra el calculo del total por ciudad" calcula-el-total
git branch -d calcula-el-total
git log --oneline
git branch
Deleted branch calcula-el-total (was 409858b).
276beee Entra el calculo del total por ciudad
75bc321 Se agregan el README y la licencia MIT
409858b Se agrega el calculo del total por ciudad
533e566 Primeras ventas por ciudad
* main

El --no-ff deja escrito que hubo una rama, y borrarla después deja la lista limpia. Así se ve un repositorio donde alguien trabajó ordenado 🌿

Paso 5: la revisión automática

mkdir -p .github/workflows
cat > .github/workflows/revisa.yml <<'FIN'
name: Revisa el CSV de ventas

on:
  push:
  pull_request:

jobs:
  revisar:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: |
          tail -n +2 ventas.csv | cut -d, -f2 | grep -q '^$' && exit 1
          echo "CSV correcto"
FIN
git add .github
git commit -q -m "Se revisa el CSV en cada push"
tail -n +2 ventas.csv | cut -d, -f2 | grep -q '^$' && exit 1
echo "la revision pasa"
la revision pasa

Paso 6: la primera versión

git tag -a v1.0 -m "Primera version del reporte por ciudad"
git tag
git describe --tags
git log --oneline --decorate -1
v1.0
v1.0
a518f4e (HEAD -> main, tag: v1.0) Se revisa el CSV en cada push

Paso 7: publicarlo

cd ..
git init -q --bare servidor.git
cd ventas-miss-yera
git remote add origin ../servidor.git
git push -q -u origin main
git push -q origin --tags
git ls-remote origin
a518f4e618f8c79df5dee7b9adf0920e4534f523	HEAD
a518f4e618f8c79df5dee7b9adf0920e4534f523	refs/heads/main
b5770ff08550961371f61e0bdd160c1b9d8cb470	refs/tags/v1.0
a518f4e618f8c79df5dee7b9adf0920e4534f523	refs/tags/v1.0^{}

Con GitHub la única diferencia es la dirección, y ahí lo que sigue es entrar a la web, comprobar que el repositorio esté como quieres y decidir si va público o privado. Todo lo demás ya está hecho 🚀

La revisión final

echo "== que se publica ==" && git ls-files
echo "== historia ==" && git log --oneline
echo "== versiones ==" && git tag
echo "== nada suelto ==" && git status --short && echo "limpio"
== que se publica ==
.github/workflows/revisa.yml
.gitignore
LICENSE
README.md
total.sh
ventas.csv
== historia ==
a518f4e Se revisa el CSV en cada push
276beee Entra el calculo del total por ciudad
75bc321 Se agregan el README y la licencia MIT
409858b Se agrega el calculo del total por ciudad
533e566 Primeras ventas por ciudad
== versiones ==
v1.0
== nada suelto ==
limpio

Siete archivos, historia legible, una versión marcada y nada pendiente. Eso es un repositorio que se puede enseñar 🎓

La trampa

Terminas tu proyecto, lo subes a GitHub y lo pones en tu currículum. Nadie lo abre dos veces.

$ git ls-files
analisis.py
datos.csv
notebook.ipynb
prueba2.py
prueba_final.py
prueba_final_v2.py
Qué está mal

Un repositorio sin README y con tres pruebas finales 😬

Quien entra a tu proyecto le da treinta segundos. En esos treinta segundos tiene que entender qué hace, ver que se puede ejecutar y llevarse la impresión de que trabajas ordenado.

Los nombres prueba_final_v2 cuentan justo lo contrario, y son exactamente el problema del capítulo 1 que este libro vino a resolver.

Un proyecto de portafolio necesita tres cosas: README con instrucciones, historia de commits legible y nada de archivos sueltos. Eso pesa más que el código.

Comprueba que se entendió

Comprueba que lo tienes

Vas a poner un repositorio en tu currículum. ¿Qué mira primero quien lo abra?

  • El README y si se entiende qué hace
  • La cantidad de commits
  • El lenguaje que aparece arriba
  • Las estrellas que tenga

Ejercicios

1. Arranca tu repositorio con lo que no va

Base del catálogo, con .gitignore desde el primer commit.

cd ..
mkdir catalogo-bodegas
cd catalogo-bodegas
git init -q
printf 'bodega,ciudad,monto\nBodega Inti,Cusco,760\n' > bodegas.csv
printf 'API_KEY=fuera\n' > .env
printf '.env\n' > .gitignore
git add bodegas.csv .gitignore
git commit -q -m "Catalogo inicial de bodegas"
git ls-files
git status --short
.gitignore
bodegas.csv

El .env ni aparece. Así se empieza 🚫

2. Ponle portada y licencia

Las dos piezas que se miran primero.

cat > README.md <<'FIN'
# Catalogo de bodegas

Lista de bodegas por ciudad con su venta mensual.

## Usar
```
bash total.sh bodegas.csv
```
FIN
printf 'MIT License\n\nCopyright (c) 2026 Gera Flores\n' > LICENSE
git add README.md LICENSE
git commit -q -m "Se agregan el README y la licencia MIT"
git ls-files
.gitignore
LICENSE
README.md
bodegas.csv

Cuatro archivos y el proyecto ya se entiende.

3. Trabaja en una rama

El cálculo del total, con su commit bien escrito.

git switch -q -c calcula-el-total
cat > total.sh <<'FIN'
tail -n +2 "$1" | cut -d, -f3 | paste -sd+ | bc
FIN
git add total.sh
git commit -q -m "Se agrega el calculo del total por bodega

Suma la tercera columna del CSV, saltandose la cabecera."
bash total.sh bodegas.csv
git log --oneline
760
ac5fc3a Se agrega el calculo del total por bodega
1c6ca9e Se agregan el README y la licencia MIT
d16ab35 Catalogo inicial de bodegas

Probado antes de fusionar, que es el orden correcto ✅

4. Fusiona dejando rastro

Con --no-ff y limpiando la rama.

git switch -q main
git merge -q --no-ff -m "Entra el calculo del total" calcula-el-total
git branch -d calcula-el-total
git log --oneline
git branch
Deleted branch calcula-el-total (was ac5fc3a).
c8f9270 Entra el calculo del total
1c6ca9e Se agregan el README y la licencia MIT
ac5fc3a Se agrega el calculo del total por bodega
d16ab35 Catalogo inicial de bodegas
* main

La historia cuenta que hubo una rama y la lista queda limpia 🌿

5. Marca la versión

Una etiqueta anotada para la v1.0.

git tag -a v1.0 -m "Primera version del catalogo"
git tag
git describe --tags
git log --oneline --decorate -1
v1.0
v1.0
c8f9270 (HEAD -> main, tag: v1.0) Entra el calculo del total

Ya se puede decir "la v1.0" y que signifique algo 🏷️

6. Publícalo con sus etiquetas

Recuerda que el push normal no se lleva las etiquetas.

cd ..
git init -q --bare catalogo-servidor.git
cd catalogo-bodegas
git remote add origin ../catalogo-servidor.git
git push -q -u origin main
git push -q origin --tags
git ls-remote origin
c8f9270f3a39746c8bffd44a28cd18bd4f3cbab5	HEAD
c8f9270f3a39746c8bffd44a28cd18bd4f3cbab5	refs/heads/main
6cc816b146b13f45ae2b3a534cb1e1191fa8781a	refs/tags/v1.0
c8f9270f3a39746c8bffd44a28cd18bd4f3cbab5	refs/tags/v1.0^{}

La rama y la etiqueta, las dos allá 🚀

7. Haz la revisión final

Lo que miro antes de mandarle un repositorio a alguien.

echo "== que se publica ==" && git ls-files
echo "== historia ==" && git log --oneline
echo "== versiones ==" && git tag
echo "== nada suelto ==" && git status --short && echo "limpio"
== que se publica ==
.gitignore
LICENSE
README.md
bodegas.csv
total.sh
== historia ==
c8f9270 Entra el calculo del total
1c6ca9e Se agregan el README y la licencia MIT
ac5fc3a Se agrega el calculo del total por bodega
d16ab35 Catalogo inicial de bodegas
== versiones ==
v1.0
== nada suelto ==
limpio

Si esas cuatro cosas se ven bien, el repositorio está listo para enseñarse 🎓

8. Intenta guardar cuando ya no queda nada

Con todo commiteado, prueba a hacer otro commit.

git commit -m "Un commit mas"
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

"nothing to commit, working tree clean" es la frase que quieres ver al terminar un proyecto: significa que no dejaste nada suelto ✅

Lo que te llevas

README, gitignore, licencia, commits legibles, una rama, una versión y una revisión. Eso es un repositorio que habla bien de ti.

¿Tienes alguna duda o consulta?