# Merges

## El primer conflicto

```
git merge lisa
```

El anterior comando trae el branch mencionado (lisa) y lo combina con el que se está seleccionado (master, en este caso). En nuestro ejemplo el archivo **recipes/apple\_pie.txt** tiene el contenido diferente en ambos branch, por lo tanto git nos muestra un mensaje como:

```
Auto-merging recipes/apple_pie.txt
CONFLICT (content): Merge conflict in recipes/apple_pie.txt
Automatic merge failed; fix conflicts and then commit the result.
```

El mensaje nos indica que se encontró un conflicto en el archivo **recipes/apple\_pie.txt**, que el merge automático falló y que debemos ajustar las diferencias y luego hacer un nuevo commit.

Si abrimos el archivo que tiene el conflicto git lo ha modificado para que nosotros identifiquemos las diferencias y ajustemos el contenido definitivo:

```
<<<<<<< HEAD
pre-made pastry
1/2 cup butter
3 tablespoons flour
1 cup sugar
8 Granny Smith apples
=======
Pre-made pastry
1/2 cup butter
3 tablespoons flour
1 cup sugar
1 tbsp cinnamon
10 Granny Smith apples
>>>>>>> lisa
```

Ajustando manualmente:

```
Apple pie

pre-made pastry
1/2 cup butter
3 tablespoons flour
1 cup sugar
1 tbsp cinnamon
9 Granny Smith apples
```

Tendríamos que adicionar los cambios a staging y luego commit:

```
git add recipes/apple_pie.txt
git commit
```

git ya entiende que estamos resolviendo un conflicto de un merge y arma un mensaje preestablecido que describe el merge:

```
Merge branch 'lisa'
```

podemos consultar el nuevo commit (es es el commit de un merge)

```
git log
```

```
commit 67f9162f89d3ab70024b05c23b2c4eb99688bc01 (HEAD -> master)
Merge: af8204b dc4b41e
Author: userName <userName@userNamecompute.loc>
Date:   Mon Oct 2 10:50:06 2017 -0500

    Merge branch 'lisa'

...
...
```

```
git cat-file -p 67f9162f89d3ab70024b05c23b2c4eb99688bc01
```

El merge es solo un commit con la diferencia que tiene **dos** campos parent, es decir como parents tiene los últimos commit de cada rama que estuvieron en el merge, por supuesto que puede tener tantos parent como ramas que haya hecho merge.

```
tree a17dbd4d9896f1ba6545287fb91fd39a16d52228
parent af8204b31b56fa4859c301959f6311b638964691
parent dc4b41e453c09a123842ece192665dae5fb9a5e9
author userName <userName@userNamecompute.loc> 1506959406 -0500
committer userName <userName@userNamecompute.loc> 1506959406 -0500

Merge branch 'lisa'
```

![](https://151692080-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LoQv9TWpDFWC4qENtD_%2F-LoQvB-gvUJ3jQ_ALANV%2F-LoQvBxXm06RL3ta_Udt%2Fmerge1.png?generation=1568131568765365\&alt=media)

Por otro lado la rama lisa, aun conserva su versión de "recetas", si se quiere actualizar se realiza un merge pero a diferencia del anterior este no requiere un commit:

```
git merge master
```

```
Updating dc4b41e..67f9162
Fast-forward
 recipes/apple_pie.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
```

Nótese el mensaje de avance rápido: fast forward.

Este comando no genera conflictos puesto que git sabe que ya fueron solucionados en el commit anterior, lo que hace git es simplemente pasar el apuntador de el branch lisa al último commit:

![](https://151692080-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LoQv9TWpDFWC4qENtD_%2F-LoQvB-gvUJ3jQ_ALANV%2F-LoQvBxZ2idPlqtAF-7B%2Flisa_master_updated.png?generation=1568131568770356\&alt=media)

## Perdiendo la cabeza

Ademas de poder movernos entre ramas con el comando

```
git checkout master
```

también git permite moverse entre commits, por ejemplo:

```
git checkout 67f9162f89d3ab70024b05c23b2c4eb99688bc01
```

git nos advierte que estamos en modo: You are in 'detached HEAD' state. Y si consultamos el branch actual:

```
git branch
```

```
* (HEAD detached at 67f9162)
  lisa
  master
```

entonces hemos "perdido la cabeza".

### Para que es util perder la cabeza?

Si realizamos un cambio en recipes/apple\_pie.txt y le hacemos un nuevo commit commit podremos ver que el HEAD se mantiene con este último commit:

![](https://151692080-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LoQv9TWpDFWC4qENtD_%2F-LoQvB-gvUJ3jQ_ALANV%2F-LoQvBxakFVB4UoMAB7d%2Fdetached_head_commit.png?generation=1568131568757359\&alt=media)

y si realizamos otro commit adicional:

![](https://151692080-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LoQv9TWpDFWC4qENtD_%2F-LoQvB-gvUJ3jQ_ALANV%2F-LoQvBxcTbtSC1Lq8cdG%2Fdetaches2_commits.png?generation=1568131568859262\&alt=media)

retornando a el branch master:

```
git checkout mster
```

![](https://151692080-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LoQv9TWpDFWC4qENtD_%2F-LoQvB-gvUJ3jQ_ALANV%2F-LoQvBxeVXyQOv8Lr3aQ%2Fcheckout_master.png?generation=1568131568759238\&alt=media)

hasta acá todo normal, excepto que los commit que se hicieron detached (sin branch) de alguna manera se hacen inalcanzables a menos que tomemos atenta nota del hash para volver a ellos si se requiere, puesto que estos commit están sin ninguna rama.

Sin embargo con el paso del tiempo es posible que git corra su **garbage collector** y estos commit se hallan eliminado, git actúa un poco como algunos lenguajes de programación e identifica lo que esta consumiendo espacio en disco (no necesario) y lo elimina.

Estando a tiempo de salvar los commit , primero debemos ir hacia el commit:

```
git checkout da4acd4359b81bbd33330163ff7de59537092b7a
```

y desde allí creamos una nuevo branch:

```
git branch nogood
```

ya solo tendríamos que volver a master y hacer merge del nuevo branch si es lo que se desea.

Muy útil si queremos experimentar con algo y decidir si realmente lo queremos vincular con una rama principal, no olvidar poner un branch antes de hacer merge.
