# Clase git
## Conceptos básicos
Commits son inmutables
Commits contienen
- SHA1
- Mensaje
- Cambios del Working Tree
- Referencia al Parent
- Signature (opcional)
Los commits se referencian de forma única con el SHA1
Refs son simplemente referencias con un nombre human-friendly que apuntan al SHA1 de un commit para que sea más fácil gestionarlo. Básicamente todo lo que hay con un nombre en un repositorio es una ref (ramas, tags, etc) Resumiendo: una ref es un “puntero” a un SHA1 con un nombre chulo. Git actualiza las refs automáticamente. Por ejemplo si estás en master y haces un commit, git actualiza la ref ‘master’ para que apunte a ese último commit que has hecho. Pero también nosotros también podemos cambiar el SHA1 de una ref manualmente si queremos. Cualquier operación que acepte un SHA1 de un commit acepta una ref.
Son refs a commits como hemos dicho. Por tanto son casi idénticos. Las ramas son para el trabajo diario, y están pensadas para ser reintegradas al trabajo principal Los tags por el contrario son simplemente “marcapáginas” a un commit concreto de la historia que queremos recordar, por lo que el uso habitual es para marcar versiones. Esto significa que no se suele reintegrar tags, sin embargo puede hacerse ya que siguen siendo refs (como las ramas) Los tags y las ramas se listan de forma separada con comandos diferentes: git branch git tag
Los tags difieren de las ramas, además de su uso y dónde se listan, en que pueden tener información adicional
- un mensaje asociado (e.g. “tag para versión 1.8”)
- una firma para asegurar que nadie cambia el SHA1 al que referencia el tag
HEAD es una ref que apunta a la ref dónde estás trabajando actualmente. Es decir es una especie de referencia a otra referencia. HEAD está pensado para apuntar a otra ref y no a un SHA1. Sin embargo sigue siendo una ref así que podemos hacer que apunte a un SHA1 directamente. Cuando HEAD apunta a un commit concreto en vez de a otra ref es cuando estamos en el modo “Detached HEAD”, con el que hay que tener cuidado y veremos en la sección de problemas. Por último cuando veáis en la documentación que algo “cambia el HEAD” lo que quiere decir es que cambia a la ref a la que está apuntando HEAD en ese momento.
Stage es un área temporal donde colocamos los ficheros que realmente vamos a comitear. También podemos colocar lineas especificas en vez de el fichero completo (hay un comando para ello, ignorarlo y usar source tree). Todos sabéis usarlo más o menos, solo hay que tener en cuenta una cosa: en la documentación oficial de git el stage area se conoce también como index, ni idea de por qué esa doble nomenclatura, pero si alguna vez os da por hacer un git help o buscarlo por internet y hablan del index, que sepáis que se refiere a esto.
La la documentación de git define así al estado del directorio de trabajo en un momento concreto. Cuando se diga que se cambia el working tree es que se cambia el directorio actual, por ejemplo al actualizar el repositorio se cambia el working tree (cambiar de rama, etc)
## Comandos básicos git-branch
Gestión de ramas listado de ramas (locales y remotas) crear/borrar/mover ramas locales
git-checkout Cambia a un commit/ref.
git-reset
Este comando tiene dos formas de uso:
- resetea lo que haya en el index y lo mueve al working tree. En otras palabras saca cosas del stage area
- cambia el commit al que apunta el HEAD, por lo que cambia el working tree actual El primer caso requiere ficheros como parametros. El segundo no los requiere pero los acepta, así, por ejemplo, podemos cambiar sólo un fichero a la versión de otro commit. Por ejemplo podría ser util para recuperar una versión antigua de un prefab del que hemos perdido las referencias para ver cómo estaba montado ;)
El segundo caso tiene tres opciones que define qué pasa con los cambios que existen entre el commit actual y entre el commit al que cambias. Estas opciones aparecen también en SourceTree:
- -soft guarda los cambios en el stage
- -mixed (defecto) guarda los cambios en el working tree
- -hard no guarda ningún cambio
git-stash
git stash [-u | --include-untracked] Mete en el stash los ficheros que no están trackeados git stash --keep-index No mete en el stash lo que tengas en el stage
git-revert
Dado un commit, coge sus cambios, los invierte, y crea un commit nuevo. Esencialmente “elimina” un commit. Esta es la manera que tenemos de borrar commits sin reescribir la historia, y es la forma que hay que hacer cuando queramos deshacer un cambio en una rama compartida (master/develop/art)
git-log
Muestra la historia de commits. Este comando tiene un huevo de opciones y es super potente, da para una clase por si solo
## Merge Cuando haces un merge se crea es un commit de merge cuya particularidad es que tienen dos padres
Como opinión personal deberíamos intentar que los commits de merge no tengan cambios: si los tienen normalmente es por que al hacer el merge han ocurrido conflictos, los has solucionado y entonces se ha hecho el merge, por lo que ese commit contiene los cambios realizados para corregir los conflictos. Sin embargo precisamente lo que hay que evitar son los conflictos al hacer el merge (más sobre esto en workflows y rebase)
fast-forward son los merges que no tienen conflictos y mantienen la historia lineal. Por defecto? (consultar si en la versión actual de git es el comportamiento por defecto) se hace un rebase, pero se puede forzar que siempre se cree un commit de merge Se puede form
## Rebase Qué hace? Diferencias con merge
Warning: Rebase reescribe la historia
- git-remote
- git-pull
- git-push
- git-fetch
Introducir un poco los rebases para gestionar la historia
## Problemas y cómo solucionarlos
- Detached HEAD
- git reflog
- git log -g
TODO: Para la 2ª formación
- Workflows
- Rebase interactivo