CLASE 10
Herramientas de Git
Organizacion InteractivaGit viene con unos cuantos scripts que hacen que algunas tareas de linea de comando sean mas faciles de usar. Aqui veremos unos cuantos comandos interactivos que te ayudaran a preparar tus commits para incluir solo ciertas combinaciones y partes de los archivos.
Estas herramientas son muy utiles si modificas unos cuantos archivos y decides que esos cambios esten en varios commits enfocados,
en lugar de en un gran commit problematico.
Si ejecutas git add con -i o --interactive,
Git entra en un modo de celda interactiva:
git add -i
staged unstaged path
1: unchanged +0/-1 TODO
2: unchanged +1/-1 index.html
3: unchanged +5/-1 lib/simplegit.rb
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
Puedes ver que este comando te muestra una vista muy diferente de tu area de ensayo:
la misma informacion que git status pero mas informativa.
Muestra los cambios que has realizado a la izquierda y los cambios que no has preparado a la derecha.
Si tecleas 2 o u en el prompt What now>,
el modo interactivo te pregunta que archivos quieres organizar:
What now> 2
staged unstaged path
1: unchanged +0/-1 TODO
2: unchanged +1/-1 index.html
3: unchanged +5/-1 lib/simplegit.rb
Update>>
Para organizar TODO e index.html, tecleas los numeros:
Update>> 1,2
staged unstaged path
* 1: unchanged +0/-1 TODO
* 2: unchanged +1/-1 index.html
3: unchanged +5/-1 lib/simplegit.rb
Update>>
El * antes de cada archivo indica que esta seleccionado para ser organizado.
Al pulsar Enter sin escribir nada, Git organiza todo lo seleccionado:
updated 2 paths
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 1
staged unstaged path
1: +0/-1 nothing TODO
2: +1/-1 nothing index.html
3: unchanged +5/-1 lib/simplegit.rb
Para desorganizar un archivo, usas la opcion 3 o r (revert).
Para ver las diferencias de lo que has organizado, usas la opcion 6 o d (diff).
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> 6
staged unstaged path
1: +1/-1 nothing index.html
Review diff>> 1
diff --git a/index.html b/index.html
index 4d07108..4335f49 100644
--- a/index.html
+++ b/index.html
@@ -16,7 +16,7 @@ Date Finder
<p id="out">...</p>
-<div id="footer">contact : support@github.com</div>
+<div id="footer">contact : email.support@github.com</div>
<script type="text/javascript">
Lo que realmente es potente en Git es que puedes organizar partes de archivos en lugar de archivos enteros.
Por ejemplo, si tienes dos cambios en lib/simplegit.rb y quieres organizar uno pero no el otro, es muy facil hacerlo.
Desde el prompt interactivo, tecleas 5 o p (patch).
Git te preguntara que archivos quieres organizar parcialmente y, para cada seccion de los archivos seleccionados,
mostrara bloques del archivo diferencial preguntandote si los quieres organizar uno por uno:
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..57399e0 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -22,7 +22,7 @@ class SimpleGit
end
def log(treeish = 'master')
- command("git log -o 25 #{treeish}")
+ command("git log -n 30 #{treeish}")
end
...
Stage this hunk [y,n,a,d,/,j,J,g,e,?]?
| Comando | Acción | Descripción detallada |
|---|---|---|
y | Organizar | Organiza el bloque actual. |
n | No organizar | Omite el bloque actual sin organizarlo. |
a | Organizar todo | Organiza este bloque y todos los bloques restantes de forma automática. |
d | No organizar nada más | Omite este bloque y todos los que quedan en el archivo. |
g | Ir a | Te permite seleccionar un bloque específico para saltar a él. |
/ | Buscar | Busca un bloque que coincida con una expresión regular (regex). |
j | Siguiente sin decidir | Deja este bloque pendiente y salta al siguiente bloque que no hayas decidido. |
J | Siguiente bloque | Deja este bloque pendiente y salta al bloque inmediatamente posterior. |
k | Anterior sin decidir | Deja este bloque pendiente y vuelve al anterior bloque que no hayas decidido. |
K | Bloque anterior | Deja este bloque pendiente y vuelve al bloque inmediatamente anterior. |
s | Dividir | Divide el bloque actual en bloques más pequeños para un control más preciso. |
e | Editar | Permite editar manualmente el contenido del bloque actual. |
Generalmente, teclearas y o n para cada bloque. Cuando termines, Git crea un script de organizacion interactivo y ejecuta git commit para confirmar los archivos parcialmente organizados.
No necesitas estar en el modo interactivo para hacer la organizacion parcial de archivos. Puedes iniciar el mismo script con
git add -pogit add --patchdirectamente en la linea de comando. Tambien puedes usarreset --patchpara desorganizar parcialmente,checkout --patchpara descartar partes de archivos, ystash save --patchpara guardar solo partes.
tar -xzf 12-organizacion-interactiva.tar.gzcd 12-organizacion-interactiva/code .) y lee el README.mdHerramientas de Git
Guardado Rapido y LimpiezaMuchas veces, cuando has estado trabajando en una parte de tu proyecto, las cosas se encuentran desordenadas y quieres cambiar de ramas para trabajar en algo mas.
El problema es que no quieres hacer un commit de un trabajo a medias. La respuesta a este problema es el comando git stash.
El guardado rapido toma el desorden de tu directorio de trabajo — es decir, tus archivos controlados por la version modificados y cambios almacenados en el area de ensayo — y lo guarda en una pila de cambios sin terminar que puedes volver a usar en cualquier momento.
Supongamos que estas trabajando en un par de archivos y posiblemente en tu etapa uno de cambios.
Si ejecutas git status, puedes ver tu estado sucio:
git status
Changes to be committed:
(use "git restore --staged..." to unstage)
modified: index.html
Changes not staged for commit:
(use "git add..." to update what will be committed)
(use "git checkout --" to discard changes in working directory)
modified: lib/simplegit.rb
Ahora quieres cambiar de rama, pero no quieres hacer commit del trabajo que has estado haciendo. Para crear un nuevo guardado rapido de tus archivos:
git stash
Saved working directory and index state \
"WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
(To restore them type "git stash apply")
Tu directorio de trabajo esta limpio:
git status
# On branch master
nothing to commit, working directory clean
En este punto, puedes facilmente cambiar de ramas y hacer trabajo en otro lugar. Tus cambios estan guardados en tus archivos. Para ver que guardados rapidos has almacenado, puedes usar git stash list:
git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051 Revert "added file_size"
stash@{2}: WIP on master: 21d80a5 added number to log
Para volver a aplicar el que acabas de guardar, puedes ejecutar el comando que aparece en la salida del comando original git stash. Si quieres hacer entrada a uno de los guardados rapidos anteriores, puedes especificarlo poniendo su nombre de esta manera: git stash apply stash@{2}. Si no especificas un guardado, Git adopta el guardado mas reciente e intenta hacerlo entrada:
git stash apply
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
#
# modified: index.html
# modified: lib/simplegit.rb
Puedes ver que Git vuelve a aplicar los cambios guardados en el stash directamente sobre tus archivos.
En este caso, tenias un directorio de trabajo limpio e intentaste aplicar el stash en la misma rama donde lo habias creado. Sin embargo, no es obligatorio que el directorio este limpio, ni tampoco que estes en la misma rama para poder recuperar tus cambios con exito.
De hecho, puedes crear un stash en una rama, cambiarte a otra y aplicar los cambios alli. Tambien puedes recuperar un stash aunque tengas cambios locales sin confirmar en tu directorio de trabajo, en ese caso, si los cambios chocan, Git simplemente generara un conflicto de fusion para que lo resuelvas.
Los cambios en tus archivos se han vuelto a aplicar, pero el estado del area de preparacion no se restauro. Para lograr eso, tienes que ejecutar el comando git stash apply con la opcion --index, la cual le indica a Git que intente reaplicar tambien los cambios que ya tenias listos para confirmar (staged). Si lo hubieras ejecutado de esta manera, habrias recuperado tu espacio de trabajo exactamente en su posicion original.
Ten en cuenta que usar la opcion --index no elimina el stash de tu lista, solo mantiene los cambios en tus archivos. Para remover ese stash de forma permanente, debes ejecutar el comando git stash drop seguido del identificador del guardado que deseas eliminar:
git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051 Revert "added file_size"
stash@{2}: WIP on master: 21d80a5 added number to log
git stash drop stash@{0}
Dropped stash@{0} (364e91f3f268f0900edec309ff7f3be04aeeef2)
Hay algunas variantes del guardado rapido que pueden ser utiles tambien.
La primera opcion que es muy popular, --keep-index le dice a Git que no guarde nada que tu ya hayas almacenado con el comando git add:
git status -s
M index.html # index.html preparado
M lib/simplegit.rb # simplegit.rb sin preparar
#
git stash --keep-index # guardado rapido de todo lo que no esta preparado
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file
#
git status -s
M index.html # index.html preparado
Esto puede ser util cuando ya has hecho un buen numero de cambios, pero solo quieres aplicar permanentemente algunos de ellos y luego regresar al resto de cambios en una siguiente ocasion.
Otra cosa comun que puede que quieras hacer con tus guardados es hacer un guardado rapido de los archivos que no estan bajo seguimiento (untracked) junto a los que estan bajo seguimiento (tracked).
Por defecto, git stash solamente guardara archivos que ya esten en el area de preparacion.
Si especificas --include-untracked o -u, Git tambien hara un guardado rapido de cualquier archivo que no este bajo seguimiento (untracked):
git status -s
M index.html # index.html preparado
M lib/simplegit.rb # simplegit.rb sin preparar pero bajo seguimiento
?? new-file.txt # nuevo archivo, no esta bajo seguimiento
#
git stash -u # guardado rapido de absolutamente todo
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file
#
git status -s
# Todo quedo en el guardado rapido
Finalmente, si especificas la flag --patch, Git no hara guardado rapido instantaneamente,
sino que te preguntara interactivamente cuales de los cambios guardar y cuales mantener en tu trabajo directamente:
git stash --patch # Guardado rapido interactivo
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 66d332e..8bb5674 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -16,6 +16,10 @@ class SimpleGit
return `#{git_cmd} 2>&1`.chomp
end
end
+
+ def show(treeish = 'master')
+ command("git show #{treeish}")
+ end
#
end
test
Stash this hunk [y,n,q,a,d,/,e,?]? y
#
Saved working directory and index state WIP on master: 1b65b17 added the index file
Si almacenas algun trabajo, lo dejas ahi por un tiempo y continuas trabajando en la misma rama, puede que tengas problemas rehaciendo la entrada al trabajo: es posible tener conflictos de fusion y deberas resolverlos.
Si quieres una forma mas facil de probar los cambios guardados, puedes ejecutar git stash branch,
el cual crea una nueva rama con el trabajo del guardado rapido para que puedas probarlo y luego realizar una fusion devuelta a la rama original:
git stash branch testchanges
Switched to a new branch 'testchanges'
# On branch testchanges
# Changes to be committed:
# (use "git restore --staged..." to unstage)
#
# modified: index.html
#
# Changed but not updated:
# (use "git add..." to update what will be committed)
#
# modified: lib/simplegit.rb
Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)
Este es un buen metodo rapido para recuperar el trabajo guardado, trabajando en una nueva rama sin conflictos.
A veces no quieres guardar tu trabajo temporal en un stash, sino que simplemente deseas deshacerte de los archivos sobrantes en tu directorio de trabajo. El comando git clean sirve exactamente para eso.
Algunos escenarios comunes para usarlo son eliminar archivos residuales, o borrar archivos compilados y caches que se crean al ejecutar el proyecto.
Debes tener mucho cuidado con este comando, ya que esta diseñado para eliminar de forma permanente los archivos de tu directorio de trabajo que no estan bajo seguimiento por Git.
Si cambias de opinion despues de usarlo, por lo general no hay forma de recuperar el contenido de esos archivos. Una opcion mucho mas segura es ejecutar git stash --all, lo cual limpia todo tu directorio pero respalda los archivos en un stash por si acaso.
Si estas seguro de que quieres eliminar la basura y limpiar tu directorio, puedes usar git clean.
Para borrar todos los archivos y carpetas que no estan bajo seguimiento,
debes ejecutar git clean -f -d. Aqui, el parametro -d incluye los subdirectorios y el parametro -f significa forzar (force), necesario porque Git bloquea este comando por defecto para evitar accidentes.
Si alguna vez quieres revisar que archivos se borrarian antes de ejecutar el comando real, puedes usar la opcion -n para hacer una simulacion:
git clean -d -n # limpiar espacio de trabajo incluyendo carpetas en modo simulacion
Would remove test.o # test.o seria eliminado
Would remove tmp/ # carpeta tmp/ seria eliminada
Por defecto, el comando git clean solo removera archivos que no estan bajo seguimiento y que no estan ignorados.
Cualquier archivo que empareje un patron de tu .gitignore u otros archivos ignorados no seran removidos.
Si quieres eliminar esos archivos tambien, como para remover todos los .o generados por una version,
para tener una version completamente limpia, puedes añadir un -x al comando:
git clean -n -d -x # limpiar espacio de trabajo incluyendo carpetas y archivos ignorados en modo simulacion
Would remove build.TMP # build.TMP seria eliminado
Would remove test.o # test.o seria eliminado
Would remove tmp/ # carpeta tmp/ seria eliminada
Si no sabes lo que el comando git clean va a hacer, siempre ejecutalo con un -n primero para estar seguro antes de cambiar el -n (simluacion) al -f (forzar) y hacerlo de verdad.
La otra forma en la que puedes ser cuidadoso con el proceso es ejecutarlo con el -i (interactivo):
git clean -x -i # limpiar espacio de trabajo incluyendo archivos ignorados en modo interactivo
Would remove the following items:
build.TMP test.o
*** Commands ***
1: clean 2: filter by pattern 3: select by numbers 4: ask each 5: quit
6: help
What now>
De esta manera puedes decidir por cada archivo individualmente o especificar los patrones para la eliminacion de forma interactiva.
tar -xzf 13-stash-y-limpieza.tar.gzcd 13-stash-y-limpieza/code .) y lee el README.md7.2 — organización interactiva.7.3 — guardado rápido y limpieza.