Qué ocurre exactamente al eliminar una sucursal en Git

He estado buscando una respuesta a esta pregunta desde hace un time, pero todavía no estoy completamente seguro de su respuesta. La mayoría de la información que encontré sobre la eliminación de sucursales no era más que una copy de lo que dice el manual (por ejemplo, aquí en SO ). Creo que un problema central es que no sé exactamente qué es una sucursal en Git (aunque hay muchos artículos que dicen que lo explican). La única información algo útil que encontré estaba en esta respuesta SO y en los documentos instalados con git.

Mi pregunta:

Cuando ejecuto git branch -d BRANCH_NAME ,

  1. ¿Qué pasa debajo del capó?
  2. qué cambia externamente, es decir, cómo cambia mi interacción con el repository?
  3. ¿Puede alguno de estos cambios considerarse un cambio en la historia?

y, además, las mismas preguntas secundarias para git branch -D BRANCH_NAME .

Mi comprensión actual:

Primero mi percepción de una twig: dependiendo del context, la twig de término se refiere a un puntero a una determinada confirmación (estrictamente llamada la cabeza de la twig), o la list de compromisos previos a esa

Lo que creo que sucede (pero no estoy seguro), para git branch -d BRANCH_NAME :

  1. se quita el puntero a la cabeza de la twig, y ​​no más
  2. Ya no puedo ver la twig en ninguna list y no puedo cambiarla ni ramificarme más (aunque creo que podría crear una nueva twig en esa confirmación, para lograr esas cosas de manera efectiva)
  3. probablemente no: las confirmaciones aún están allí, ¿ya no están labeldas con el nombre de la sucursal?

Lo que creo que sucede, para git branch -D BRANCH_NAME :

  1. se elimina el puntero al encabezado de la bifurcación y se borran todos los commits que no están en otra twig
  2. Ya no puedo ver la twig en ninguna list y ya no puedo cambiarla ni ramificarme, ni recuperar el código de ninguna manera
  3. sí: los commits en la twig se pierden

Independientemente de si elimina con git branch -d o git branch -D , git elimina no las confirmaciones, sino solo la twig de reference. Sigue leyendo para ver lo que eso significa.

Primero, configuraremos un historial de demostración simple.

 $ touch initial ; git add initial ; git commit -m 'Initial commit' [master (root-commit) 2182bb2] Initial commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 initial $ git checkout -b mybranch Switched to a new branch 'mybranch' 

En este punto, tanto master como mybranch apuntan a la misma confirmación, que podemos verificar al less de dos maneras.

 $ git lola * 2182bb2 (HEAD -> mybranch, master) Initial commit 

Tenga en count que git lola es un alias no estándar pero muy útil, equivalente a

 $ git log --graph --decorate --pretty=oneline --abbrev-commit --all * 2182bb2 (HEAD -> mybranch, master) Initial commit 

La otra forma la veremos después de crear una nueva confirmación en mybranch .

 $ touch mybranch ; git add mybranch ; git commit -m 'My branch' [mybranch 7143aa4] My branch 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 mybranch 

Después de hacer esto, de hecho tenemos múltiples commits en múltiples twigs.

 $ git lola * 7143aa4 (HEAD -> mybranch) My branch * 2182bb2 (master) Initial commit 

Ahora podemos ver parte de cómo git implementa esto bajo el capó.

 $ ls -R .git/refs .git/refs: heads tags .git/refs/heads: master mybranch .git/refs/tags: 

Es curioso que haya files con los mismos nombres que nuestras sucursales. Mirando dentro de ellos, vemos

 $ cat .git/refs/heads/master .git/refs/heads/mybranch 2182bb2d5a0a7f57d0b74e95d37e208dac41f95b 2182bb2d5a0a7f57d0b74e95d37e208dac41f95b 

Así que git implementa refs como files en una location determinada cuyos nombres coinciden con los nombres de las twigs y que contienen hashes SHA1 de ciertas confirmaciones. Observe que el hash abreviado en la salida de git lola ( 2182bb2 ) es el prefijo principal de la salida de cat anterior.

Piense en las references de git como indicadores simples que le otorgan nombres legibles a las confirmaciones específicas en la historia de su repository.

Ahora si volvemos a master y zap mybranch

 $ git checkout master ; git branch -D mybranch Switched to branch 'master' Deleted branch mybranch (was 7143aa4). 

vemos que el árbitro se ha ido

 $ ls -R .git/refs .git/refs: heads tags .git/refs/heads: master .git/refs/tags: 

pero el compromiso todavía está allí.

 $ git show --pretty=oneline 7143aa4 7143aa477735382e7a0ed11c9e4b66c1f27583df My branch diff --git a/mybranch b/mybranch new file mode 100644 index 0000000..e69de29 

Si quieres que mybranch regrese, solo necesitas ejecutar

 $ git checkout -b mybranch 7143aa4 Switched to a new branch 'mybranch' 

o

 $ git branch mybranch 7143aa4 

dependiendo de, como lo indique la diferencia en sus respectivas salidas, si desea cambiar a la twig o no. En el último caso, donde te quedaste en tu sucursal actual, parece que git lola

 $ git lola * 7143aa4 (mybranch) My branch * 2182bb2 (HEAD -> master) Initial commit 

Sí, tus compromisos se quedan por poco time incluso después de eliminar los indicadores que los mantienen con vida. Esto puede ser tremendamente útil en casos de eliminación accidental. Ver también git reflog y git gc .


Tenga en count que los valores hash SHA1 serán diferentes en su repository porque su nombre y dirección de correo electrónico, al less, serán diferentes de los que usé.

Para completar, la diferencia entre -d y -D es que la versión en minúsculas es ligeramente más segura.

-d
--delete

Eliminar una twig La twig debe fusionarse por completo en su twig ascendente, o en HEAD si no se estableció en sentido ascendente con --track o --set-upstream .

-D

--delete --force directo para --delete --force .

-f
--force

Restablecer nombre de twig a punto de inicio si ya existe nombre de twig . Sin -f git branch se niega a cambiar una twig existente. En combinación con -d (o --delete ), permite eliminar la twig independientemente de su estado fusionado …

Las confirmaciones continúan allí después de la eliminación de la sucursal, hasta la próxima recolección de basura. git branch -d (y -D ) imprime el hash de confirmación abreviado, puede usarlo como argumento para git log o git checkout o git branch , que le da la posibilidad de restaurar la twig eliminada.

La única diferencia entre -d y -D es que git branch -d no te permitirá eliminar una twig no fusionada (es decir, perder potencialmente commits).