informatica:programacion:cursos:control_version_git_avanzado:commits
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| informatica:programacion:cursos:control_version_git_avanzado:commits [2023/05/31 10:55] – [Introducción] tempwin | informatica:programacion:cursos:control_version_git_avanzado:commits [2023/06/16 17:11] (actual) – tempwin | ||
|---|---|---|---|
| Línea 2: | Línea 2: | ||
| Sección perteneciente al curso [[informatica: | Sección perteneciente al curso [[informatica: | ||
| + | |||
| ===== Introducción ===== | ===== Introducción ===== | ||
| Línea 7: | Línea 8: | ||
| También veremos cómo ver commits del pasado y cómo deshacerlos. | También veremos cómo ver commits del pasado y cómo deshacerlos. | ||
| + | |||
| ===== Preparación de un commit por etapas ===== | ===== Preparación de un commit por etapas ===== | ||
| ==== Trabajando con el stage ==== | ==== Trabajando con el stage ==== | ||
| + | |||
| + | Tanto para añadir nuevos archivos al repositorio (empezar a // | ||
| + | |||
| + | < | ||
| + | git add < | ||
| + | </ | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | Para inicializar un repositorio, | ||
| + | </ | ||
| + | |||
| + | Cuando queremos "subir al stage" un archivo: | ||
| + | |||
| + | < | ||
| + | git add archivo | ||
| + | </ | ||
| + | |||
| + | Si queremos añadir más de un archivo: | ||
| + | |||
| + | < | ||
| + | git add archivo1 archivo2 archivo3 | ||
| + | </ | ||
| + | |||
| + | Si queremos añadir un tipo de ficheros: | ||
| + | |||
| + | < | ||
| + | git add *.html | ||
| + | </ | ||
| + | |||
| + | Para subir todos los archivos y modificaciones pendientes de pasar al stage y que estén en la carpeta actual (y todas las carpetas hijas): | ||
| + | |||
| + | < | ||
| + | git add . | ||
| + | </ | ||
| + | |||
| + | Para ver información sobre las 3 zonas que usamos en Git, usamos el siguiente comando: | ||
| + | |||
| + | < | ||
| + | '' | ||
| + | </ | ||
| + | |||
| + | Podemos ver un resumen de los ficheros que están en el stage y los que no están siendo controlados (versionados) por git. Los primeros aparecen en color verde y los segundos en color rojo. Otra forma de decirlo sería que lo que está en verde es lo que está en el stage y lo que está en rojo es lo que está en el working directory. | ||
| + | |||
| + | <WRAP center round todo 60%> | ||
| + | Poner captura con ejemplo de lo anterior | ||
| + | </ | ||
| + | |||
| + | <WRAP center round tip 60%> | ||
| + | '' | ||
| + | </ | ||
| + | |||
| + | |||
| + | Si queremos **quitar modificaciones del stage** (por algún error): | ||
| + | |||
| + | < | ||
| + | git reset HEAD < | ||
| + | </ | ||
| + | |||
| + | Por ejemplo, si queremos quitar el fichero '' | ||
| + | |||
| + | < | ||
| + | git reset HEAD archivo1 | ||
| + | </ | ||
| + | |||
| + | <WRAP center round tip 60%> | ||
| + | También se puede emplear '' | ||
| + | </ | ||
| + | |||
| + | |||
| + | Si queremos quitar todos los cambios que haya en el stage: | ||
| + | |||
| + | < | ||
| + | git reset HEAD . | ||
| + | </ | ||
| + | |||
| + | <WRAP center round tip 60%> | ||
| + | En realidad, el comando '' | ||
| + | </ | ||
| + | |||
| + | Para deshacer cambios en el working directory, es decir, para que Git deje los archivos modificados como estaban en el último commit: | ||
| + | |||
| + | < | ||
| + | git checkout -- < | ||
| + | </ | ||
| + | |||
| + | Por ejemplo, si queremos volver al estado anterior de todos los archivos del working directory: | ||
| + | |||
| + | < | ||
| + | git checkout -- . | ||
| + | </ | ||
| + | |||
| + | <WRAP center round important 60%> | ||
| + | Esta operación es irreversible, | ||
| + | </ | ||
| + | |||
| + | Finalmente, si queremos borrar un archivo tenemos dos opciones. Si el borrado lo hacemos mediante las operaciones del sistema operativo, Git lo entiende como una modificación del proyecto y podremos subirlo al stage para luego hacer un commit con ese borrado. | ||
| + | |||
| + | Si usamos el método Git: | ||
| + | |||
| + | < | ||
| + | git rm < | ||
| + | </ | ||
| + | |||
| + | Git lo borra del sistema de ficheros y añada esa modificación al stage, ahorrándonos un paso respecto a la versión usando el sistema operativo. | ||
| + | |||
| + | Si queremos quitar un archivo del repositorio sin borrarlo del working directory: | ||
| + | |||
| + | < | ||
| + | git rm --cached < | ||
| + | </ | ||
| + | |||
| + | Esto es útil cuando llegado un momento queremos empezar a ignorar un fichero que antes estábamos siguiendo (el '' | ||
| + | |||
| + | Tras " | ||
| ==== Realizando el commit ==== | ==== Realizando el commit ==== | ||
| + | |||
| + | Un commit siempre necesita un mensaje descriptivo (es obligatorio): | ||
| + | |||
| + | < | ||
| + | git commit -m " | ||
| + | </ | ||
| + | |||
| + | Si queremos que abra el editor por defecto para que luego añadamos el comentario: | ||
| + | |||
| + | < | ||
| + | git commit | ||
| + | </ | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | El commit siempre se hace sobre lo que hay en el **stage** | ||
| + | </ | ||
| + | |||
| + | Como recomendación, | ||
| + | |||
| + | < | ||
| + | git log --oneline --branches --graph | ||
| + | </ | ||
| + | |||
| + | Si queremos **modificar el último commit** (solo el último) que hemos hecho: | ||
| + | |||
| + | < | ||
| + | git commit --amend | ||
| + | </ | ||
| + | |||
| + | Esto lo haremos tras añadir cambios al stage. | ||
| + | |||
| + | Al ejecutar el comando anterior, se abrirá el mensaje del último commit (el que queremos modificar) dándonos la posibilidad de modificarlo, | ||
| + | |||
| + | <WRAP center round important 60%> | ||
| + | Si el commit ya se había subido al repositorio remoto, no se debe hacer '' | ||
| + | </ | ||
| + | |||
| + | Otra cosa que suele pasar mucho es que hayamos hecho un commit con un mensaje incorrecto o incompleto. Si queremos corregir este mensaje, pero no tenemos más cambios, no hace falta subir nada al stage, basta con ejecutar el siguiente comando: | ||
| + | |||
| + | < | ||
| + | git commit --amend -m "Nuevo mensaje" | ||
| + | </ | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | Si no le pasamos el mensaje por línea de comandos, git abrirá el editor por defecto. | ||
| + | </ | ||
| + | |||
| + | Esta modificación cambia el hash del commit. Esto es normal porque este hash se genera a partir del contenido del título y otras cosas. | ||
| + | |||
| ==== Ejemplos de commits por etapas ==== | ==== Ejemplos de commits por etapas ==== | ||
| + | |||
| + | <WRAP center round todo 60%> | ||
| + | Añadir capturas de pantalla con las zonas de git y cómo se mueven los archivos cuando se preparan los commits. | ||
| + | </ | ||
| + | |||
| + | Iniciamos un repositorio git: | ||
| + | |||
| + | < | ||
| + | git init | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | git status | ||
| + | </ | ||
| + | |||
| + | Subiremos al stage el fichero '' | ||
| + | |||
| + | < | ||
| + | git add despedidas-en.json | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | git status | ||
| + | </ | ||
| + | |||
| + | Hacemos commit: | ||
| + | |||
| + | < | ||
| + | git commit -m " | ||
| + | </ | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | Es práctica habitual incluir el mensaje " | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | git log --oneline --branches | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | git status | ||
| + | </ | ||
| + | |||
| + | Subimos el fichero '' | ||
| + | |||
| + | < | ||
| + | git add saludos-en.json | ||
| + | </ | ||
| + | |||
| + | Hacemos el commit: | ||
| + | |||
| + | < | ||
| + | git commit -m " | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | git log --oneline --branches | ||
| + | </ | ||
| + | |||
| + | Modificamos el fichero '' | ||
| + | |||
| + | < | ||
| + | git status | ||
| + | </ | ||
| + | |||
| + | Subimos el fichero al stage: | ||
| + | |||
| + | < | ||
| + | git add saludos-en.json | ||
| + | </ | ||
| + | |||
| + | Hacemos el commit: | ||
| + | |||
| + | < | ||
| + | git commit -m " | ||
| + | </ | ||
| + | |||
| + | Vemos el log: | ||
| + | |||
| + | < | ||
| + | git log --oneline --branches | ||
| + | </ | ||
| + | |||
| + | Creamos un nuevo fichero en el working directory: '' | ||
| + | |||
| + | < | ||
| + | git status | ||
| + | </ | ||
| + | |||
| + | Añadiremos al stage solo dos ficheros: | ||
| + | |||
| + | < | ||
| + | git add lugares-en.json despedidas-en.json | ||
| + | </ | ||
| + | |||
| + | Hacemos commit: | ||
| + | |||
| + | < | ||
| + | git commit -m " | ||
| + | </ | ||
| + | |||
| + | Vemos el log: | ||
| + | |||
| + | < | ||
| + | git log --oneline --branches | ||
| + | </ | ||
| + | |||
| + | Subimos al stage '' | ||
| + | |||
| + | < | ||
| + | git add saludos-en.json | ||
| + | </ | ||
| + | |||
| + | Pero nos arrepentimos, | ||
| + | |||
| + | < | ||
| + | git reset HEAD saludos-en.json | ||
| + | </ | ||
| + | |||
| + | Git nos dirá que aún está pendiente el cambio de ese fichero en el working directory: | ||
| + | |||
| + | < | ||
| + | git status | ||
| + | </ | ||
| + | |||
| + | Pero si queremos volver a la versión del último commit del fichero '' | ||
| + | |||
| + | < | ||
| + | git checkout -- . | ||
| + | </ | ||
| + | |||
| + | <WRAP center round important 60%> | ||
| + | Recordad que este último comando es irreversible | ||
| + | </ | ||
| ===== Partes de un commit ===== | ===== Partes de un commit ===== | ||
| + | |||
| + | Hasta ahora hemos visto qué es un commit. Ahora veremos los datos que llevan asociados los commits: | ||
| + | |||
| + | * **Autor** / " | ||
| + | * **Fecha y hora** | ||
| + | * **Mensaje** | ||
| + | * **Padre**/ | ||
| + | * **Hash** de 40 caracteres: se obtieen al aplicar SHA-1 al autor, fecha, mensaje y contenido del commit. | ||
| + | |||
| + | < | ||
| + | git log | ||
| + | </ | ||
| + | |||
| + | <WRAP center round todo 60%> | ||
| + | Poner ejemplo de todo lo anterior | ||
| + | </ | ||
| ===== El log ===== | ===== El log ===== | ||
| + | |||
| + | El log es el listado de commits a lo largo del tiempo. | ||
| ==== Comandos para trabajar con el log ==== | ==== Comandos para trabajar con el log ==== | ||
| + | |||
| + | Ver el histórico de commits: | ||
| + | |||
| + | < | ||
| + | git log [rama] | ||
| + | </ | ||
| + | |||
| + | Si no se indica la rama, '' | ||
| + | |||
| + | Para ver el log de forma compacta: | ||
| + | |||
| + | < | ||
| + | git log --oneline | ||
| + | </ | ||
| + | |||
| + | Así veremos un commit por línea. No mostrará autor ni fecha. | ||
| + | |||
| + | Ver el log de todas las ramas: | ||
| + | |||
| + | < | ||
| + | git log --branches | ||
| + | </ | ||
| + | |||
| + | Ahora podemos mezclar los modificadores para ver el log en formato compacto y de todas las ramas: | ||
| + | |||
| + | < | ||
| + | git log --oneline --branches | ||
| + | </ | ||
| + | |||
| + | Al trabajar con ramas, es útil tener una representación gráfica de las divergencias, | ||
| + | |||
| + | < | ||
| + | git log --graph --branches | ||
| + | </ | ||
| + | |||
| + | Podemos crear **alias** para comandos largos que usemos habitualmente: | ||
| + | |||
| + | < | ||
| + | git config --global alias.milog "log --oneline --branches --graph" | ||
| + | </ | ||
| + | |||
| + | Habremos creado un alias llamado '' | ||
| + | |||
| + | < | ||
| + | git milog | ||
| + | </ | ||
| + | |||
| + | Para ver el contenido de un commit: | ||
| + | |||
| + | < | ||
| + | git show < | ||
| + | </ | ||
| + | |||
| + | <WRAP center round todo 60%> | ||
| + | Poner ejemplo del comando anterior | ||
| + | </ | ||
| + | |||
| + | Con el comando anterior podremos ver las diferencias con el commit anterior. El formato que es usa es el de los parches (//patch//) | ||
| + | |||
| + | Podemos referenciar un commit de varias maneras: | ||
| + | |||
| + | * Por su identificador hash SHA-1 (lo que vimos anteriormente) | ||
| + | * Su posición respecto al HEAD | ||
| + | * Por el nombre de una rama | ||
| + | * Por su posición en el listado de reflog: '' | ||
| + | |||
| + | < | ||
| + | git show HEAD | ||
| + | </ | ||
| + | |||
| + | Commit anterior al commit apuntado por HEAD: | ||
| + | |||
| + | < | ||
| + | git show HEAD~1 | ||
| + | </ | ||
| + | |||
| + | Es lo mismo que | ||
| + | < | ||
| + | git show HEAD~ | ||
| + | </ | ||
| + | |||
| + | Dos commits antes: | ||
| + | |||
| + | < | ||
| + | git show HEAD~2 | ||
| + | </ | ||
| + | |||
| + | Es lo mismo que | ||
| + | < | ||
| + | git show HEAD~~ | ||
| + | </ | ||
| + | |||
| + | Esto es muy útil cuando queremos deshacer commits. | ||
| + | |||
| + | Si un commit tiene más de un padre, usamos la notación siguiente: | ||
| + | |||
| + | < | ||
| + | git show HEAD^1 | ||
| + | </ | ||
| + | |||
| + | Haremos referencia al primer padre. | ||
| + | |||
| + | < | ||
| + | git show HEAD^2 | ||
| + | </ | ||
| + | |||
| + | Haremos referencia al segundo padre. | ||
| + | |||
| + | Referenciando un commit por la rama que apunta: | ||
| + | |||
| + | < | ||
| + | git show nombre_rama | ||
| + | </ | ||
| + | |||
| + | '' | ||
| + | |||
| + | < | ||
| + | git checkout HEAD@{1} | ||
| + | </ | ||
| + | |||
| + | Nos habremos ido al commit al que apuntaba HEAD en cierto momento. | ||
| + | |||
| + | <WRAP center round todo 60%> | ||
| + | Poner gráfico con detached HEAD | ||
| + | </ | ||
| ==== Saltos entre commits, reset y reflog ==== | ==== Saltos entre commits, reset y reflog ==== | ||
| + | |||
| + | Saltar a otro commit o rama: | ||
| + | |||
| + | < | ||
| + | git checkout <COMMIT o RAMA> | ||
| + | </ | ||
| + | |||
| + | Para el nombre el commit podemos usar las referencias que vimos en el apartado anterior. | ||
| + | |||
| + | El '' | ||
| + | |||
| + | Para " | ||
| + | |||
| + | < | ||
| + | git reset < | ||
| + | </ | ||
| + | |||
| + | Realmente no se borran, sencillamente desaparecen de nuestra vista. Esto permite que podamos recuperarlos en cualquier momento (si no ha pasado demasiado tiempo y ha pasado el recolector de basura de Git). | ||
| + | |||
| + | Por ejemplo, si quremos deshacer los últimos 3 commits: | ||
| + | |||
| + | < | ||
| + | git reset HEAD~3 | ||
| + | </ | ||
| + | |||
| + | El comando '' | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | Cuando desarrollamos en un equipo y queremos ver quién fue la última persona que hizo cada cambio: | ||
| + | |||
| + | < | ||
| + | git blame < | ||
| + | </ | ||
| + | |||
| + | Es útil para seguir una traza y poder encontrar quién hizo qué cosa. | ||
| ===== Apartar cambios con stash ===== | ===== Apartar cambios con stash ===== | ||
| + | |||
| + | **stash** sirve para apartar cambios (en el working directory o en el stage) temporalmente. | ||
| + | |||
| + | <WRAP center round tip 60%> | ||
| + | Esto es muy útil cuando Git no nos deja cambiarnos de rama o commit ('' | ||
| + | </ | ||
| + | |||
| + | **stash** es una pila, lo que entra queda en la parte superior. | ||
| + | |||
| + | '' | ||
| + | |||
| + | Para coger unos cambios y meterlos en la pila de " | ||
| + | |||
| + | < | ||
| + | git stash [push -m " | ||
| + | </ | ||
| + | |||
| + | Listar todo lo que hay en el stash: | ||
| + | |||
| + | < | ||
| + | git stash list | ||
| + | </ | ||
| + | |||
| + | <WRAP center round todo 60%> | ||
| + | Poner ejemplos del comando anterior | ||
| + | </ | ||
| + | |||
| + | Si queremos ver el contenido | ||
| + | |||
| + | < | ||
| + | git stash show [stash@{n}] [-p] | ||
| + | </ | ||
| + | |||
| + | Para sacar los cambios del stash y colocarlos en el working directory (git stash siempre los colocará ahí): | ||
| + | |||
| + | < | ||
| + | git stash apply [stash@{n}] | ||
| + | </ | ||
| + | |||
| + | El comando anterior no quita el stash de la pila. Si además queremos quitarlo de la pila, usaremos este otro comando: | ||
| + | |||
| + | < | ||
| + | git stash pop [stash@{n}] | ||
| + | </ | ||
| + | |||
| + | Si queremos borrar de la pila un stash sin aplicarlo: | ||
| + | |||
| + | < | ||
| + | git stash drop [stash@{n}] | ||
| + | </ | ||
| ===== Cómo deshacer ===== | ===== Cómo deshacer ===== | ||
| + | |||
| + | Algo muy importante de Git es que casi todo se puede deshacer. Todo lo que vaya a un commit quedará para la historia (hasta que llegue el recolector de basura). | ||
| + | |||
| + | Repasemos varias maneras de deshacer cambios. | ||
| + | |||
| + | ==== Cambios en el working directory ==== | ||
| + | |||
| + | Deshacer cambios en el **working directory** (todos los cambios): | ||
| + | |||
| + | < | ||
| + | git checkout -- . | ||
| + | </ | ||
| + | |||
| + | <WRAP center round important 60%> | ||
| + | Recordemos que el anterior comando es de las pocas cosas en git que no se pueden deshacer. | ||
| + | </ | ||
| + | |||
| + | ==== Cambios en el stage ==== | ||
| + | |||
| + | Deshacer lo que haya en el **stage**: | ||
| + | |||
| + | < | ||
| + | git reset HEAD . | ||
| + | </ | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | Ahora sabemos que el uso principal de '' | ||
| + | </ | ||
| + | |||
| + | ==== Deshacer commits ==== | ||
| + | |||
| + | < | ||
| + | git reset < | ||
| + | </ | ||
| + | |||
| + | Deshacer un '' | ||
| + | |||
| + | < | ||
| + | git reflog | ||
| + | </ | ||
| + | |||
| + | Así vemos los commits ocultos porque vemos los movimientos de HEAD. Cuando lo hayamos identificado, | ||
| + | |||
| + | < | ||
| + | git checkout < | ||
| + | </ | ||
| + | |||
| + | Esto nos pondrá en el modo " | ||
| + | |||
| + | < | ||
| + | git branch -f master | ||
| + | </ | ||
| + | |||
| + | Suponiendo que la rama '' | ||
| + | |||
| + | < | ||
| + | git checkout master | ||
| + | </ | ||
| + | |||
| + | Podemos pensar que para recuperar un commit " | ||
| + | |||
| + | ==== Deshacer un reset ==== | ||
| + | |||
| + | Tras hacer un reset, los commits desaparecen de nuestra vista, pero podemos recuperarlos. Los podemos ver con: | ||
| + | |||
| + | < | ||
| + | git reflog | ||
| + | </ | ||
| + | |||
| + | E identificamos el último commits de los que queremos recueprar. | ||
| + | |||
| + | Ahora nos llevaremos HEAD y master del momento actual a ese último commit que queremos recuperar: | ||
| + | |||
| + | < | ||
| + | git checkout < | ||
| + | </ | ||
| + | |||
| + | Ahora llevaremos la rama: | ||
| + | |||
| + | < | ||
| + | git branch -f master | ||
| + | </ | ||
| + | |||
| + | Para enlazar HEAD con master (y salir de " | ||
| + | |||
| + | < | ||
| + | git checkout master | ||
| + | </ | ||
| + | |||
| + | <WRAP center round todo 60%> | ||
| + | Poner ejemplos de todo lo anterior | ||
| + | </ | ||
| + | |||
| + | ==== Resolver problemas derivados del detached HEAD ==== | ||
| + | |||
| + | Cuando por ejemplo estamos haciendo commits en estado " | ||
| + | |||
| + | < | ||
| + | git log --oneline --graph | ||
| + | </ | ||
| + | |||
| + | No ponemos '' | ||
| + | |||
| + | Para solucionarlo, | ||
| + | |||
| + | < | ||
| + | git branch -f master | ||
| + | </ | ||
| + | |||
| + | Nos quedaría la asociación de HEAD con master, es decir pasar de '' | ||
| + | |||
| + | < | ||
| + | git checkout master | ||
| + | </ | ||
| + | |||
| + | <WRAP center round todo 60%> | ||
| + | Poner ejemplos de todo lo anterior | ||
| + | </ | ||
| + | |||
| + | Otra situación que se nos puede dar es que hagamos un commit en un estado anterior al commit en el que está la rama master. | ||
| + | |||
| + | Eso origina un nuevo itinerario, pero es un itinerario que está fuera de la rama master (no tiene ninguna referencia de rama asociada). Si nos cambiamos de rama, el itinerario anterior quedará oculto a la vista. | ||
| + | |||
| + | Para recuperar, nos ayudamos de: | ||
| + | |||
| + | < | ||
| + | git reflog | ||
| + | </ | ||
| + | |||
| + | Identificamos el commit que nos interesa y | ||
| + | |||
| + | < | ||
| + | git checkout commit | ||
| + | </ | ||
| + | |||
| + | Hemos vuelto al " | ||
| + | |||
| + | < | ||
| + | git branch experimento | ||
| + | </ | ||
| + | |||
| + | Ahora ya aparece el itinerario en los logs. | ||
| + | |||
| + | Seguimos en " | ||
| + | |||
| + | < | ||
| + | git checkout experimento | ||
| + | </ | ||
| + | |||
| + | ==== Ignorar archivos que ya están siendo versionados ==== | ||
| + | |||
| + | Borrar del repositorio, | ||
| + | |||
| + | < | ||
| + | git rm --cached < | ||
| + | </ | ||
| + | |||
| + | El archivo dejará de estar versionado. Luego podremos añadirlo a un '' | ||
| ===== Conclusión ===== | ===== Conclusión ===== | ||
| + | |||
| + | Hemos visto cómo se preparan los commits: en el stage. Al hacer un commit, " | ||
| + | |||
| + | Los commits no se hacen periódicamente, | ||
| + | |||
| + | '' | ||
| ===== Recursos ===== | ===== Recursos ===== | ||
informatica/programacion/cursos/control_version_git_avanzado/commits.1685523338.txt.gz · Última modificación: por tempwin
