Módulo 8: Proyecto final colaborativo y evaluación

Unidad: GIT-10
Nivel: tronco, inicial–intermedio
Duración orientativa: 4–5 horas
Público: alumnado de DAW, DAM, ASIR y grados de informática.
Itinerario: cierre del tronco, tras fundamentos, ramas, remotos, recuperación y entrega.
Prerrequisitos: módulos 1 a 7 completos.
Objetivo observable: entregar, en equipo, un repositorio en GitHub con una versión etiquetada y documentada; cada persona debe poder explicar su historial, la integración de su contribución y una decisión segura de recuperación.
Fuente técnica: documentación oficial de Git, especialmente branches, merge, push y tag, y la documentación de pull requests de GitHub.

Reto

Construid un pequeño proyecto colaborativo: una aplicación o sitio estático de agenda de actividades. El valor funcional es secundario: se evalúa el uso razonado de Git, no la calidad del producto.

El repositorio debe incluir:

  • README.md con objetivo, instalación/uso, estructura, integrantes y flujo de trabajo.
  • .gitignore adecuado al editor, al sistema y a la tecnología empleada (módulo 4).
  • Al menos tres funcionalidades separables en ramas de tarea.
  • Una integración mediante merge con un conflicto real, resuelto y explicado (módulo 5).
  • Un tag anotado v1.0.0 publicado (módulo 7).
  • Un historial legible, sin commits de archivos generados, secretos ni dependencias instaladas.
  • Evidencia individual de contribución y explicación técnica.

No son requisito ni Git LFS, ni hooks, ni CI/CD, ni rebase, ni push --force. Pueden usarse solo como ampliación documentada, y los tres primeros se tratan en los módulos 10 y 11.

Organización

Equipos de 2–4 personas. Cada integrante asume una funcionalidad y rota, al menos una vez, el papel de integrador/a: quien revisa y acepta el trabajo de otra persona. Las tareas se registran como issues en GitHub.

Flujo mínimo por tarea:

  1. Poner main al día: git switch main && git fetch origin && git merge origin/main.
  2. Crear una rama: feat/nombre-corto, fix/nombre-corto o docs/nombre-corto.
  3. Hacer commits pequeños, coherentes y verificables.
  4. Publicar la rama con git push -u origin <rama> y abrir una pull request en GitHub.
  5. Otra persona revisa, comenta y aprueba.
  6. Integrar y borrar la rama.

Al final del proyecto: preparar el README, crear el tag anotado y publicar la versión.

Git aporta ramas, commits, remotos y merges. La pull request, las aprobaciones y la protección de ramas son funciones de GitHub, no de Git (módulo 5).

Preparar el repositorio en GitHub

Una persona del equipo crea el repositorio y añade al resto como colaboradores. Después, cada integrante lo clona:

git clone https://github.com/<organizacion>/<repositorio>.git
cd <repositorio>
git config user.name "Nombre Apellido"
git config user.email "correo@ejemplo.es"

Configurar la identidad por repositorio (sin --global) evita el error clásico de entregar commits firmados con el nombre de otra persona o con el del ordenador del aula. Compruébalo antes del primer commit:

git config user.name
git log -1 --format="%an <%ae>"

Se recomienda proteger main en la configuración del repositorio para que solo se pueda modificar mediante pull request. Es opcional para el proyecto y se trata a fondo en el módulo 11.

Demostración práctica

La siguiente secuencia usa un remoto local para poder ensayar el flujo completo sin depender de la red. En el proyecto real, ../agenda-remoto.git se sustituye por la URL de GitHub y el paso de integración por una pull request.

Arranque y primera funcionalidad

mkdir proyecto-agenda
cd proyecto-agenda
git init -b main

printf "# Agenda de actividades\n" > README.md
printf "node_modules/\n.env\n.DS_Store\n" > .gitignore
git add README.md .gitignore
git commit -m "chore: crea estructura inicial"

git init --bare ../agenda-remoto.git
git remote add origin ../agenda-remoto.git
git push -u origin main

git switch -c feat/listado-actividades
printf "<h1>Próximas actividades</h1>\n" > index.html
git add index.html
git commit -m "feat: añade listado de actividades"
git push -u origin feat/listado-actividades
[main (root-commit) ebdeab7] chore: crea estructura inicial
 2 files changed, 4 insertions(+)
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.
[feat/listado-actividades 76085b4] feat: añade listado de actividades
 1 file changed, 1 insertion(+)
 * [new branch]      feat/listado-actividades -> feat/listado-actividades

Revisar antes de integrar

Este es el trabajo del integrador, y el detalle importa:

git fetch origin
git log --oneline --graph --decorate --all
git diff --stat main...origin/feat/listado-actividades

Tres puntos, no dos. main...rama compara la rama contra el punto en que ambas se separaron, que es la pregunta de una revisión: «¿qué ha hecho esta rama?». Con dos puntos obtendrías además, invertidos, los cambios que main haya sumado por su cuenta. En una revisión real eso aparece como si la contribución borrase archivos que nunca tocó:

# git diff --stat main..origin/feat/inscripciones   ← DOS puntos, engañoso
 README.md        | 4 ----
 inscripcion.html | 1 +

# git diff --stat main...origin/feat/inscripciones  ← TRES puntos, correcto
 inscripcion.html | 1 +

fetch descarga referencias sin modificar tu rama (módulo 5). No trates git pull como una acción opaca: es fetch más una integración.

Integrar y publicar la versión

git switch main
git merge --no-ff feat/listado-actividades -m "merge: integra listado de actividades"
git tag -a v1.0.0 -m "Versión inicial de Agenda"
git push origin main --tags
git ls-remote --tags origin
Merge made by the 'ort' strategy.
 index.html | 1 +
   ebdeab7..7979a5a  main -> main
 * [new tag]         v1.0.0 -> v1.0.0
5104d6d61d6ce3c460213b3ece000cce93f93525	refs/tags/v1.0.0
7979a5a2218e30661f75998add2b6caae9a9e1df	refs/tags/v1.0.0^{}

--no-ff deja constancia en el historial de que hubo una rama, que es lo que se quiere en un proyecto evaluado. Las dos líneas del tag en ls-remote son la firma de un tag anotado (módulo 7).

El conflicto obligatorio

El enunciado exige un conflicto real. La forma limpia de provocarlo es que dos ramas modifiquen la misma línea:

git switch -c feat/horarios
printf "<h1>Próximas actividades</h1>\n<p>Horario: mañanas</p>\n" > index.html
git add index.html && git commit -m "feat: añade horario de mañanas"

git switch main
printf "<h1>Próximas actividades</h1>\n<p>Horario: tardes</p>\n" > index.html
git add index.html && git commit -m "feat: añade horario de tardes"

git merge feat/horarios
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

La resolución es una decisión de equipo, no una elección mecánica entre las dos versiones:

printf "<h1>Próximas actividades</h1>\n<p>Horario: mañanas y tardes</p>\n" > index.html
git add index.html
git commit

Aquí ninguna de las dos versiones era correcta: la agenda abre en ambos turnos. Esa justificación es lo que se evalúa, más que el comando.

Qué cambia en cada paso:

Comando Efecto
git add Actualiza el área de preparación
git commit Crea historial local
git push Publica commits y referencias en el remoto
git merge Integra en el historial local; el remoto no cambia hasta el push
git tag -a Crea la etiqueta local
git push --tags Publica las etiquetas

Errores frecuentes

  • Trabajar directamente en main: comprueba con git branch --show-current antes de tocar archivos. Si ya has hecho commits, git switch -c feat/tarea los conserva (módulo 5).
  • Commits con la identidad equivocada: en un aula con equipos compartidos es lo más habitual. Configura user.name y user.email por repositorio y verifica con git log -1 --format="%an <%ae>" antes de acumular trabajo. La rúbrica evalúa la contribución individual y se lee del historial.
  • Subir archivos innecesarios o sensibles: si git status muestra node_modules, .env o archivos generados, faltan reglas en .gitignore. Añádelas antes del primer commit de esos archivos: una vez confirmado un secreto, el revert no lo borra del historial (módulo 6).
  • Intentar publicar sin integrar: el push se rechaza con (fetch first). git fetch, revisar, integrar y volver a publicar (módulo 5).
  • Revisar con git diff main..rama: usa tres puntos. Con dos, la revisión muestra como borrados los cambios que main sumó por su cuenta.
  • Resolver un conflicto a ciegas: lee las dos versiones, comprueba el resultado y justifica la decisión. Si no tienes información, git merge --abort y pregunta.
  • Usar reset --hard para corregir la entrega: puede descartar trabajo sin confirmar. Prefiere restore, revert o una rama de seguridad; si pierdes un commit, git reflog (módulo 6).
  • Usar push --force sobre una rama compartida: sobrescribe trabajo ajeno. No se permite en el proyecto final salvo autorización expresa del profesorado, y con justificación de recuperación.

Entrega

Cada equipo entrega la URL del repositorio de GitHub con la versión etiquetada v1.0.0 publicada. Cada integrante adjunta una nota breve —máximo 200 palabras— que responda:

  1. Qué rama creó y qué aportó.
  2. Qué commit considera más representativo y por qué.
  3. Qué integración o conflicto revisó o resolvió, y con qué criterio.
  4. Qué comando usaría ante un error propio ya publicado, y por qué ese y no otro.

La cuarta pregunta es la que separa el aprobado del notable: la respuesta correcta es revert, y hay que saber decir por qué no reset (módulo 6).

Rúbrica

Criterio Evidencia Puntos
Estructura y documentación README útil, .gitignore pertinente y proyecto reproducible 1,5
Historia local Commits pequeños, mensajes comprensibles y cambios revisables 2,0
Ramas e integración Ramas de tarea, merge correcto y conflicto resuelto y explicado 2,0
Remoto y sincronización Publicación de ramas, uso correcto de fetch/push y sin sobrescrituras 1,5
Entrega de versión Tag anotado v1.0.0 publicado y estado final coherente 1,0
Seguridad y recuperación Decisión razonada entre restore, revert, reset o reflog 1,0
Defensa individual Explica con precisión su contribución y el estado local/remoto 1,0

Total: 10 puntos. Criterio de superación: 5/10, sin obtener 0 en historia local, en ramas e integración ni en seguridad y recuperación. La calificación es individual, aunque el repositorio sea compartido.

Cómo se comprueba cada criterio

Para que la evaluación sea reproducible, estas son las comprobaciones sobre el repositorio entregado:

git log --oneline --graph --all          # ramas, merges y legibilidad
git log --format="%an" | sort | uniq -c  # reparto real de la contribución
git ls-remote --tags origin              # tag publicado
git log -S "<<<<<<<" --oneline           # marcadores de conflicto confirmados
git log --diff-filter=A --name-only --format="" | sort -u   # qué se llegó a añadir

La cuarta detecta el error más penalizado de todos: confirmar un archivo con los marcadores de conflicto dentro. La quinta revela dependencias o secretos que llegaron al historial aunque después se borraran.

Qué debe saber hacer el alumnado

Al terminar, debe poder organizar un trabajo en ramas, revisar e integrar contribuciones ajenas, sincronizar un remoto sin sobrescribir trabajo, preparar una versión etiquetada y justificar una decisión segura ante un error propio ya publicado.

Estado editorial: listo.

Registro de revisión técnica

Revisado el 4 de agosto de 2026 con Git 2.47.1. La demostración se ha reproducido íntegra desde una carpeta vacía, con identidad de práctica y configuración aislada. Se ha comprobado que:

  • La secuencia de arranque, publicación de la rama, merge --no-ff, tag anotado y git push origin main --tags funciona tal cual: un solo comando publica la rama y la etiqueta, y git ls-remote --tags devuelve las dos líneas propias de un tag anotado.
  • El conflicto de integración se provoca de forma fiable haciendo que las dos ramas escriban la misma línea de index.html, y se cierra con git add + git commit.

Corrección aplicada. El borrador indicaba revisar la contribución con git diff main..origin/feat/listado-actividades, con dos puntos. Reproducido con main avanzada por su cuenta, ese comando informa de README.md | 4 ----: presenta como si la rama borrara un archivo que nunca tocó, que es justo el falso negativo capaz de hundir una revisión. Con tres puntos (main...rama) el resultado es el correcto, solo inscripcion.html. Se ha corregido y explicado en el propio módulo y en los errores frecuentes, en coherencia con lo que ya enseña el módulo 5.

Decisiones incorporadas. La forja es GitHub, así que se han sustituido las referencias genéricas a «la forja elegida» por instrucciones concretas: creación del repositorio, alta de colaboradores, clonado y flujo de pull request. Se ha añadido la configuración de identidad por repositorio, que en aulas con equipos compartidos es la causa habitual de que la contribución individual no se pueda leer del historial —y la rúbrica la califica individualmente—. Se han añadido también los comandos de comprobación de la rúbrica y enlaces cruzados a los módulos 4, 5, 6 y 7.

Pendiente al disponer del repositorio del curso: ensayar el flujo completo de pull request con dos cuentas y decidir si la protección de main se exige o se deja como recomendación.