2.1 Un No-Conflicto

Primero veamos como funciona git en una revisión normal, antes de entrar a estudiar lo que sucede cuando hay conflictos al hacer una mezcla. Trabajemos con las ramas del ejemplo 09 (antes de hacer el merge). Inmediatamente después de hacer checkout de example9/branchA, miremos el status:

Listing 2.1:git status sobre un árbol limpio
$ git status 
On branch example9/branchA 
nothing to commit, working tree clean

Como sabe git que no hay cambios en el árbol de trabajo? git compara el árbol de trabajo con el index:

Listing 2.2:git ls-files en un árbol limpio
$ git ls-files -s 
100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0       .gitignore 
100755 ad957360597fb9bd3e83d4bfa869f6e19b7fbf2b 0       example.py 
100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0       module.py

git está listando los permisos, el ID del objeto, el index stage3 y el nombre del archivo de cada uno de los archivos en la revisión actual. git compara los archivos en el árbol de trabajo y ve que nada ha cambiado.

Lo siguiente sería modificar example.py de alguna forma. Luego de modificarlo y guardarlo, git se da cuenta de que el archivo ha cambiado porque ya no se corresponde con lo lo que está en el index. La información del index no va a cambiar hasta que agreguemos el archivo, por supuesto. Así que agreguemos el archivo al index y veamos lo que git ls-files tiene para nosotros:

Listing 2.3:git ls-files con un archivo modificado
$ git add example.py 
$ git status 
On branch example9/branchA 
Changes to be committed: 
  (use "git restore --staged <file>..." to unstage) 
        modified:   example.py 
 
$ git ls-files -s 
100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0       .gitignore 
100755 b30ade699b80860abd0ed6d84cff9df94e801d34 0       example.py 
100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0       module.py

Podemos ver que el id del objeto de example.py cambió4 pero aparte de eso no hay otras diferencias. Como puede saber git los ids de los objetos que había en el index antes de agregarlos? git también tiene esa información de HEAD:

Listing 2.4:git ls-tree sobre example9/branchA
$ git ls-tree -r HEAD 
100644 blob 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f    .gitignore 
100755 blob ad957360597fb9bd3e83d4bfa869f6e19b7fbf2b    example.py 
100644 blob 475f980e6c6e24f8fc4a144e498fa1c1c59da370    module.py

Y podemos ver que los ids de los 3 archivos son los mismos que se tenía originalmente en el index cuando hicimos checkout. Ahora que el id de example.py cambió entre HEAD y lo que hay en el index, git sabe que hay contenido nuevo asociado a example.py en el index que está listo para ser acometido. Por eso nos muestra el archivo en Changes to be committed.

Modifiquemos el archivo una vez más sin agregarlo y veamos lo que sucede:

Listing 2.5:Luego de modificar un archivo ya agregado
$ git status 
On branch example9/branchA 
Changes to be committed: 
  (use "git restore --staged <file>..." to unstage) 
        modified:   example.py 
 
Changes not staged for commit: 
  (use "git add <file>..." to update what will be committed) 
  (use "git restore <file>..." to discard changes in working directory) 
        modified:   example.py 
 
$ git ls-tree -r HEAD 
100644 blob 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f    .gitignore 
100755 blob ad957360597fb9bd3e83d4bfa869f6e19b7fbf2b    example.py 
100644 blob 475f980e6c6e24f8fc4a144e498fa1c1c59da370    module.py 
$ git ls-files -s 
100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0       .gitignore 
100755 b30ade699b80860abd0ed6d84cff9df94e801d34 0       example.py 
100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0       module.py

Esto es interesante. example.py se muestra en Changes to be committed porque el id del archivo cambió entre HEAD e index. Pero también aparece en Changes not staged for commit prque git se da cuenta de que el archivo en el árbol de trabajo no conincide con el objeto en el index. Si lo agregamos de nuevo y verificamos:

Listing 2.6:Luego de agregar el archivo de nuevo
$ git add example.py 
$ git status 
On branch example9/branchA 
Changes to be committed: 
  (use "git restore --staged <file>..." to unstage) 
        modified:   example.py 
 
$ git ls-tree -r HEAD 
100644 blob 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f    .gitignore 
100755 blob ad957360597fb9bd3e83d4bfa869f6e19b7fbf2b    example.py 
100644 blob 475f980e6c6e24f8fc4a144e498fa1c1c59da370    module.py 
$ git ls-files -s 
100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0       .gitignore 
100755 1858db13464ae33329a90cacbe294e749ea9a1a5 0       example.py 
100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0       module.py

Fíjense como el id del objeto asociado a example.py en el index cambió (de b30ade699b8.... a 1858db13464....). Los ids de los objetos son diferentes entre index y HEAD y por eso el archivo parece en Changes to be committed. El contenido del archivo ahora es igual al del index y por eso git sabe que no hay más nada que reportar sobre el archivo. Si creáramos una revisión en este momento, cual sería el resultado?

Listing 2.7:acometiendo
$ git commit -m "Some test" 
[example9/branchA b2f9a40] Some test 
 1 file changed, 6 insertions(+) 
$ git status 
On branch example9/branchA 
nothing to commit, working tree clean 
$ git ls-tree -r HEAD 
100644 blob 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f    .gitignore 
100755 blob 1858db13464ae33329a90cacbe294e749ea9a1a5    example.py 
100644 blob 475f980e6c6e24f8fc4a144e498fa1c1c59da370    module.py 
$ git ls-files -s 
100644 2f78cf5b66514f2506d9af5f3dadf3dee7aa6d9f 0       .gitignore 
100755 1858db13464ae33329a90cacbe294e749ea9a1a5 0       example.py 
100644 475f980e6c6e24f8fc4a144e498fa1c1c59da370 0       module.py

Y ahora el id de example.py cambió en HEAD5 a lo que estaba en el index cuando creamos la revisión(1858db13464ae33329a90cacbe294e749ea9a1a5). Ahora los ids de los archivos son los mismos entre HEAD e index y el archivo en el árbol de trabajo coincide con lo que está en el index, así que git no tiene nada que reportar al respecto en git status.

Hagamos un reset de la rama para jugar con conflictos:

Listing 2.8:Haciendo reset
$ git reset --hard HEAD~ 
HEAD is now at dfde76c A little refactor (moving condition to another function)