Skip to content

Instantly share code, notes, and snippets.

@danidiaz
Last active October 28, 2020 10:59
Show Gist options
  • Save danidiaz/c5af145583e81f2bd392440c6842184b to your computer and use it in GitHub Desktop.
Save danidiaz/c5af145583e81f2bd392440c6842184b to your computer and use it in GitHub Desktop.
Las muchas caras de git checkout

Las muchas caras de git checkout

Es bien sabido que la interfaz de línea de comandos de Git es confusa. Por ejemplo,git checkout tiene distintos comportamientos no demasiado relacionados entre sí.

El primero es cambiar a una rama ya existente:

git checkout mirama

También podemos crear una nueva rama local y cambiarnos a ella:

git checkout -b mineuvaramalocal

O bajarnos una rama de un remote y comenzar a seguirla:

git checkout -b unarama --track origin/unarama

Si en vez de pasarle una rama le pasamos el hash de un commit, checkout nos pondrá en el (innecesariamente) temido estado de "detached HEAD":

git checkout f4f031d

"detached HEAD", significa que HEAD no está apuntando a una rama que a su vez apunta a un commit, sino que apunta directamente a un commit.

Por otra parte, checkout también puede utilizarse para descartar los cambios para un archivo concreto en el worktree, sobreescribiéndolos con los contenidos del índice:

git checkout -- /path/to/archive.txt

Si estamos en medio de un merge, podemos usar esta variante de checkout para quedarnos o bien con los cambios de la versión local de un archivo, o con los cambios de la rama que estamos mergeando:

git checkout --ours -- /path/to/archive.txt
git checkout --theirs -- /path/to/archive.txt

Esto funciona porque, cuando hay un merge en curso, el índice almacena tanto la versión local (--ours) como la de la rama que mergeamos (--theirs) de los archivos en conflicto.

checkout no solo nos deja sobreescribir un archivo en el worktree desde el índice. También nos deja sobreescribir un archivo tanto en el worktree como en el índice con una versión del archivo traída de cualquier otra rama o commit:

git checkout f4f031d -- /path/to/archive.txt

Como esta variante del comando (al contrario que la anterior) también sobreescribe el índice, no solo el worktree, hay que hacer git diff --staged para ver los cambios. Ojo, esto no es un cherry-pick, ya que no crea un commit nuevo.

Si solo estamos interesados en traernos parte de los cambios ("hunks") para el archivo desde el otro commit, podemos usar --patch para elegirlos de manera interactiva:

git checkout --patch f4f031d -- /path/to/archive.txt

Poniendo fin a la confusión

Como hemos visto, a veces checkout cambia de rama, y a veces modifica archivos en el worktree (y quizás en el índice) sin cambiar de rama.

Desde la versión 2.23.0 de Git, se han añadido dos nuevos (y todavía experimentales en 2.29.1) comandos a Git: git switch y git restore. Entre los dos se reparten la funcionalidad de git checkout.

git switch abarca la funcionalidad de git checkout relacionada con cambios de rama, mientras que git restore abarca la funcionalidad de manipulación de worktree e índice.

Idealmente, una vez que estos dos nuevos comandos se estabilicen en alguna versión futura de Git, podrían usarse en vez de git checkout, el cual quedaría obsoleto.

What's the difference between git switch and git checkout

What is the git restore command and what is the difference between git restore and git reset?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment