Close

Git prune

El comando git prune es una utilidad de mantenimiento interno que limpia objetos de Git inaccesibles o "huérfanos". Los objetos inaccesibles son aquellos a los que no puede acceder ninguna referencia. Cualquier confirmación a la que no se pueda acceder a través de una rama o etiqueta se considera inaccesible. git prune generalmente no se ejecuta directamente; se considera un comando de "recolección de basura" y es un comando secundario de git gc.


Descripción general de git prune


Para entender los efectos de git prune, vamos a simular una situación en la que una confirmación se vuelve inaccesible. El siguiente código es una secuencia de ejecuciones de línea de comandos que simulará esta experiencia.

~ $ cd git-prune-demo/
~/git-prune-demo $ git init .
Initialized empty Git repository in /Users/kev/Dropbox/git-prune-demo/.git/
~/git-prune-demo $ echo "hello git prune" > hello.txt
~/git-prune-demo $ git add hello.txt
~/git-prune-demo $ git commit -am "added hello.txt"

La secuencia de comandos anterior creará un nuevo repositorio en un directorio llamado git-prune-demo. Se añade al repositorio una confirmación que consiste en un nuevo archivo llamado hello.text con el contenido básico “hello git prune”. A continuación, modificaremos hello.txt y crearemos una nueva confirmación a partir de esas modificaciones.

~/git-prune-demo $ echo "this is second line txt" >> hello.txt
~/git-prune-demo $ cat hello.txt
hello git prune
this is second line txt
~/git-prune-demo $ git commit -am "added another line to hello.txt"
[main 5178bec] added another line to hello.txt
1 file changed, 1 insertion(+)
bases de datos
Material relacionado

Cómo mover un repositorio de Git completo

Logotipo de Bitbucket
VER LA SOLUCIÓN

Aprende a usar Git con Bitbucket Cloud

Ahora tenemos un historial de 2 confirmaciones en este repositorio de demostración. Podemos verificarlo mediante git log:

~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 14:49:59 2018 -0700

        added another line to hello.txt

commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

        added hello.txt

La salida de git log muestra las 2 confirmaciones y los mensajes de confirmación correspondientes sobre las ediciones realizadas en hello.txt. El siguiente paso es hacer que una de las confirmaciones sea inaccesible. Para ello, utilizaremos el comando git reset. Restablecemos el estado del repositorio a la primera confirmación (“added hello.txt”).

~/git-prune-demo $ git reset --hard 994b122045cf4bf0b97139231b4dd52ea2643c7e
HEAD is now at 994b122 added hello.txt

Si ahora utilizamos git log para examinar el estado del repositorio, podemos ver que solo tenemos una confirmación.

~/git-prune-demo $ git log
commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

        added hello.txt

El repositorio de demostración ahora está en un estado que contiene una confirmación desasociada. La segunda confirmación que hicimos con el mensaje “added another line to hello.txt” ya no aparece en la salida de git log y ahora está desasociada. Puede parecer que hemos perdido o eliminado la confirmación, pero Git es muy estricto en cuanto a no eliminar el historial. Podemos confirmar que todavía está disponible, aunque desasociada, usando git checkout para consultarla directamente:

~/git-prune-demo $ git checkout 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Note: checking out '5178becc2ca965e1728554ce1cb8de2f2c2370b1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

      git checkout -b <new-branch-name>

HEAD is now at 5178bec... added another line to hello.txt
~/git-prune-demo $ git log
commit 5178becc2ca965e1728554ce1cb8de2f2c2370b1
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 14:49:59 2018 -0700

      added another line to hello.txt

commit 994b122045cf4bf0b97139231b4dd52ea2643c7e
Author: kevzettler <kevzettler@gmail.com>
Date:   Sun Sep 30 09:43:41 2018 -0700

      added hello.txt

Cuando extraemos con checkout la confirmación desasociada, Git es lo suficientemente considerado como para mostrarnos un mensaje detallado explicando que estamos en un estado desasociado. Si examinamos el registro aquí, podemos ver que la confirmación “added another line to hello.txt” vuelve a aparecer en la salida del registro. Ahora que sabemos que el repositorio está en un buen estado de simulación con una confirmación desasociada, podemos practicar el uso de git prune. No obstante, volvamos antes de nada a la rama main usando git checkout.

~/git-prune-demo $ git checkout main
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

      5178bec added another line to hello.txt

If you want to keep it by creating a new branch, this may be a good time
to do so with:

     git branch <new-branch-name> 5178bec

Switched to branch 'main'

Al volver a main mediante git checkout, Git vuelve a ser lo suficientemente considerado como para informarnos de que estamos dejando atrás una confirmación desasociada. ¡Ha llegado el momento de eliminarla! Ahora ejecutaremos git prune, pero debemos pasarle algunas opciones. --dry-run y --verbose mostrarán una salida que indica lo que está configurado para eliminarse pero sin eliminarlo realmente.

~/git-prune-demo $ git prune --dry-run --verbose

Lo más probable es que este comando devuelva una salida vacía, lo que implica que git prune no eliminará nada. ¿Por qué podría pasar esto? Bueno, lo más probable es que la confirmación no esté completamente desasociada. Git sigue manteniendo una referencia a ella en algún lugar. Este es un excelente ejemplo de por qué git prune no debe usarse de forma independiente fuera de git gc. También es un buen ejemplo de lo difícil que es perder datos por completo con Git.

Lo más probable es que Git esté almacenando una referencia a nuestra confirmación desasociada en el registro de referencias. Podemos investigar ejecutando git reflog. Deberías ver una salida que describa la secuencia de acciones que hemos llevado a cabo para llegar hasta aquí. Para obtener más información sobre git reflog, visita la página sobre git reflog. Además de conservar el historial en el registro de referencias, Git fija fechas de caducidad internas para determinar cuándo se eliminarán las confirmaciones desasociadas. Como vimos antes, estos son detalles de implementación de los que se encarga git gc, y git prune no debería usarse de forma independiente.

Para concluir nuestra demostración de simulación de git prune, tenemos que borrar el registro de referencias.

~/git-prune-demo $ git reflog expire --expire=now --expire-unreachable=now --all

El comando de arriba forzará la caducidad de todas las entradas del registro de referencias que sean más antiguas que “now” (ahora). Este es un comando brutal y peligroso que nunca deberías tener que usar como usuario casual de Git. Estamos ejecutando este comando para ver cómo funciona git prune cuando se ejecuta correctamente. Con el registro de referencias totalmente borrado, ahora podemos ejecutar git prune.

~/git-prune-demo $ git prune --dry-run --verbose --expire=now
1782293bdfac16b5408420c5cb0c9a22ddbdd985 blob
5178becc2ca965e1728554ce1cb8de2f2c2370b1 commit
a1b3b83440d2aa956ad6482535cbd121510a3280 commit
f91c3433eae245767b9cd5bdb46cd127ed38df26 tree

Este comando debería mostrar una lista de referencias de objetos SHA de Git similar a la de arriba.

Uso


git prune tiene una breve lista de opciones de las que hemos hablado en la sección de descripción general.

-n --dry-run

No ejecuta git prune, solo muestra una salida de lo que hará.

-v --verbose

Muestra una salida con todos los objetos y acciones que lleva a cabo git prune.

--progress

Muestra una salida que indica el progreso de la eliminación con git prune.

--expire <time>

Fuerza la caducidad de los objetos que están en el pasado

<head>…

Si especificas un <head>, conservarás cualquier opción de esa referencia head

Análisis


¿Cuál es la diferencia entre git prune, git fetch --prune y git remote prune?

git remote prune y git fetch --prune hacen lo mismo: borran las referencias a las ramas que no están presentes en el repositorio remoto. Esto es muy conveniente cuando se trabaja en un flujo de trabajo de equipo en el que las ramas remotas se eliminan después de la fusión con main. El segundo comando, git fetch --prune, se conecta al repositorio remoto y recupera el estado remoto más reciente antes de llevar a cabo la eliminación. Se trata esencialmente de una combinación de comandos:

git fetch --all && git remote prune

El comando genérico git prune es completamente diferente. Como vimos en la sección de descripción general, git prune elimina las confirmaciones desasociadas localmente.

¿Cómo limpio las ramas obsoletas?

git fetch --prune es la mejor utilidad para limpiar ramas obsoletas. Se conecta a un repositorio remoto compartido y recupera todas las referencias a ramas remotas. A continuación, elimina las referencias remotas que ya no se usan en el repositorio remoto.

¿El comando git remote prune origin elimina la rama local?

No, git remote prune origin solo elimina las referencias a las ramas remotas que ya no existen. Git almacena referencias locales y remotas. Un repositorio tiene colecciones de referencias local/origin y remote/origin. git remote prune origin solo elimina las referencias en remote/origin. El trabajo local en local/origin no se modifica.

Resumen de git prune


El comando git prune está pensado para invocarse como un comando secundario de git gc. Es muy poco probable que tengas que invocar git prune durante el trabajo diario de ingeniería de software. Hay que conocer otros comandos para entender los efectos de git prune. Algunos de los comandos utilizados en este artículo han sido git log, git reflog y git checkout.


Compartir este artículo
Tema siguiente

Lecturas recomendadas

Consulta estos recursos para conocer los tipos de equipos de DevOps o para estar al tanto de las novedades sobre DevOps en Atlassian.

Gente que colabora utilizando un muro lleno de herramientas

Blog de Bitbucket

Ilustración de Devops

Ruta de aprendizaje de DevOps

Demostraciones de funciones con expertos de Atlassian del Centro de demostraciones

Cómo funciona Bitbucket Cloud con Atlassian Open DevOps

Suscríbete para recibir el boletín de DevOps

Thank you for signing up