-
1. Inicio - Sobre el Control de Versiones
-
2. Fundamentos de Git
-
3. Ramificaciones en Git
-
4. Git en el Servidor
- 4.1 Los Protocolos
- 4.2 Configurando Git en un servidor
- 4.3 Generando tu clave pública SSH
- 4.4 Configurando el servidor
- 4.5 El demonio Git
- 4.6 HTTP Inteligente
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Git en un alojamiento externo
- 4.10 Resumen
-
5. Git en entornos distribuidos
-
6. GitHub
-
7. Herramientas de Git
- 7.1 Revisión por selección
- 7.2 Organización interactiva
- 7.3 Guardado rápido y Limpieza
- 7.4 Firmando tu trabajo
- 7.5 Buscando
- 7.6 Reescribiendo la Historia
- 7.7 Reiniciar Desmitificado
- 7.8 Fusión Avanzada
- 7.9 Rerere
- 7.10 Haciendo debug con Git
- 7.11 Submódulos
- 7.12 Agrupaciones
- 7.13 Replace
- 7.14 Almacenamiento de credenciales
- 7.15 Resumen
-
8. Personalización de Git
-
9. Git y Otros Sistemas
- 9.1 Git como Cliente
- 9.2 Migración a Git
- 9.3 Resumen
-
10. Los entresijos internos de Git
-
A1. Apéndice A: Git en otros entornos
- A1.1 Interfaces gráficas
- A1.2 Git en Visual Studio
- A1.3 Git en Eclipse
- A1.4 Git con Bash
- A1.5 Git en Zsh
- A1.6 Git en Powershell
- A1.7 Resumen
-
A2. Apéndice B: Integrando Git en tus Aplicaciones
- A2.1 Git mediante Línea de Comandos
- A2.2 Libgit2
- A2.3 JGit
-
A3. Apéndice C: Comandos de Git
- A3.1 Configuración
- A3.2 Obtener y Crear Proyectos
- A3.3 Seguimiento Básico
- A3.4 Ramificar y Fusionar
- A3.5 Compartir y Actualizar Proyectos
- A3.6 Inspección y Comparación
- A3.7 Depuración
- A3.8 Parcheo
- A3.9 Correo Electrónico
- A3.10 Sistemas Externos
- A3.11 Administración
- A3.12 Comandos de Fontanería
7.9 Herramientas de Git - Rerere
Rerere
La funcionalidad del "git rerere" es una característica oculta. El nombre se refiere a "reuse recorded resolution" y, como el nombre lo insinúa, te permite pedirle a Git que recuerde cómo resolviste un conflicto de hunk. Así la próxima vez que vea el mismo conflicto, Git puede resolverlo automáticamente por ti.
Hay una serie de escenarios en los cuales esta funcinalidad podría ser realmente útil. Uno de los ejemplos mencionado en el manual es, si te quieres asegurar de que una rama temática longeva se unirá limpiamente, pero no quieres tener un montón de “commits” de unión por la mitad. Con "rerere" encendido, puedes unir ocasionalmente, resolver los conflictos, y luego revertir la unión. Si haces esto continuamente, entonces la unión final debería ser fácil porque "rerere" puede hacer todo por ti automáticamente.
Esta misma táctica puede ser usada si quieres mantener una rama con “rebase”, de esta manera no tienes que lidiar con los mismos conflictos de “rebase” cada vez que lo haces. O si quieres tomar una rama que uniste y arreglar un montón de conflictos y entonces decidir hacer “rebase” en su lugar - probablemente no tengas que solucionar todos los mismos conflictos de nuevo.
Otra situación es, cuando unes un montón de ramas temáticas en evolución juntas en una HEAD de pruebas ocasionalmente, como el mismo proyecto Git hace con frecuencia. Si las pruebas fallan, puedes rebobinar las uniones y rehacerlas sin la rama temática que hace fallar a las pruebas sin tener que re-resolver los conflictos de nuevo.
Para activar la funcionalidad "rerere", simplemente tienes que ejecutar este ajuste de configuración:
$ git config --global rerere.enabled true
Puedes encenderlo también creando el directorio ".git/rr-cache" en un repositorio específico, pero el ajuste de configuración es limpiador y puede ser hecho globalmente.
Ahora veamos un ejemplo simple, similar al anterior. Digamos que tenemos un archivo que luce de esta manera:
#! /usr/bin/env ruby
def hello
puts 'hello world'
end
En una rama, cambiamos la palabra "hello" por "hola", entonces, en otra rama cambiamos el "world" por "mundo", justo como antes.
Cuando unimos las dos ramas juntas, tendremos un conflicto de unión:
$ git merge i18n-world
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Recorded preimage for 'hello.rb'
Automatic merge failed; fix conflicts and then commit the result.
Deberías notar la nueva línea "Recorded preimage for FILE" ahí adentro. Si no, debería verse exactamente como un conflicto de unión normal. En este punto, "rerere" puede decirnos algunas cosas. Normalmente, podrías ejecutar git status
en este punto para ver todo lo que entró en conflicto:
$ git status
# On branch master
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add <file>..." to mark resolution)
#
# both modified: hello.rb
#
Sin embargo, "git rerere" también te dirá lo que ha registrado el estado pre-unión con git rerere status
:
$ git rerere status
hello.rb
Y git rerere diff
mostrará el estado actual de la resolución - con lo que comenzaste a resolver y lo que has resuelto.
$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,11 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
+<<<<<<< HEAD
puts 'hola world'
->>>>>>>
+=======
+ puts 'hello mundo'
+>>>>>>> i18n-world
end
Además (y esto no está realmente relacionado a "rerere"), puedes usar ls-files -u
para ver los archivos que están en conflicto y las versiones anteriores, izquierda y derecha:
$ git ls-files -u
100644 39804c942a9c1f2c03dc7c5ebcd7f3e3a6b97519 1 hello.rb
100644 a440db6e8d1fd76ad438a49025a9ad9ce746f581 2 hello.rb
100644 54336ba847c3758ab604876419607e9443848474 3 hello.rb
Ahora puedes resolverlo para hacer simplemente puts 'hola mundo'
y puedes ejecutar el comando rerere diff
de nuevo para ver lo que "rerere" recordará:
$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,7 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
- puts 'hola world'
->>>>>>>
+ puts 'hola mundo'
end
Eso básicamente dice: cuando Git ve un conflicto de hunk en un archivo "hello.rb" que tiene "hello mundo" en un lado y "hola world" en el otro, lo resolverá como "hola mundo".
Ahora podemos marcarlo como resuleto y hacerle “commit”:
$ git add hello.rb
$ git commit
Recorded resolution for 'hello.rb'.
[master 68e16e5] Merge branch 'i18n'
Ahora podemos ver que "Recorded resolution for FILE" (Registró solución para ARCHIVO).
Ahora, deshagamos esa unión y luego hagámosle “rebase” en la cima de nuestra rama maestra en su lugar. Podemos tener nuestra rama de vuelta usando reset
como vimos en Reiniciar Desmitificado.
$ git reset --hard HEAD^
HEAD is now at ad63f15 i18n the hello
Nuestra unión no está hecha. Ahora hagámos “rebase” a la rama temática.
$ git checkout i18n-world
Switched to branch 'i18n-world'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: i18n one word
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Resolved 'hello.rb' using previous resolution.
Failed to merge in the changes.
Patch failed at 0001 i18n one word
Ahora, tenemos el mismo conflicto de unión que esperábamos, pero échale un vistazo a la línea "Resolved FILE using previous resolution". Si miramos el archivo, veremos que ya está resuleto, ya no hay marcas de conflicto de unión en él.
$ cat hello.rb
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
Además, git diff
te mostrará cómo fué re-resuleto automáticamente:
$ git diff
diff --cc hello.rb
index a440db6,54336ba..0000000
--- a/hello.rb
+++ b/hello.rb
@@@ -1,7 -1,7 +1,7 @@@
#! /usr/bin/env ruby
def hello
- puts 'hola world'
- puts 'hello mundo'
++ puts 'hola mundo'
end
Puedes también recrear el archivo en conflicto con el comando “checkout”:
$ git checkout --conflict=merge hello.rb
$ cat hello.rb
#! /usr/bin/env ruby
def hello
<<<<<< ours
puts 'hola world'
======
puts 'hello mundo'
>>>>>> theirs
end
Vimos un ejemplo de esto en Fusión Avanzada. Por ahora, resolvámoslo sólo ejecuntando "rerere" de nuevo:
$ git rerere
Resolved 'hello.rb' using previous resolution.
$ cat hello.rb
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
Hemos re-resuelto el archivo automáticamente usando la resolución en caché "rerere". Ahora puedes añadir y continuar el “rebase” para completarlo.
$ git add hello.rb
$ git rebase --continue
Applying: i18n one word
Entonces, si haces muchas re-uniones, o quieres mantener una rama temática actualizada con tu rama maestra sin un montón de uniones, o haces “rebase” a menudo, puedes encender "rerere" para ayudar un poco a tu vida.