1

Creo un repositorio con dos commits :

~/ttt$ echo 1 > a
~/ttt$ git init
Initialized empty Git repository in /home/jose/ttt/.git/
~/ttt$ git add .
~/ttt$ git commit -m "Primer"
[master (root-commit) fdcbd32] Primer
 1 file changed, 1 insertion(+)
 create mode 100644 a
~/ttt$ git branch inicio
~/ttt$ echo 22 >> a
~/ttt$ git add .
~/ttt$ git commit -m "Segundo"
[master 36cbf1c] Segundo
 1 file changed, 1 insertion(+)

Pero cambio de idea y decido que ya no quiero el segundo commit. Me quedo con el primero solo.

~/ttt$ git checkout inicio
Switched to branch 'inicio'
~/ttt$ git branch -D master
Deleted branch master (was 36cbf1c).
~/ttt$ git checkout master
error: pathspec 'master' did not match any file(s) known to git.

Bien, ya me he cargado ese segundo commit. Su rama master no existe y no puedo acceder a el.... Error. El commit aún está ahí, y se puede llegar con el hash.

~/ttt$ git checkout 36cbf1c
Note: checking out '36cbf1c'.

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 36cbf1c... Segundo
~/ttt$ cat a
1
22

¿Cómo me lo cargo del todo?
rm -rf .git no es una respuesta válida, quiero conservar el otro commit.

Anonymous Coward
  • 6,185
  • 4
  • 31
  • 58

2 Answers2

3

Es un poco brusco borrar la rama master para eliminar un solo commit, pero supongo que era para darle énfasis al ejemplo.

Los commits huérfanos se los lleva el garbage collector eventualmente, en la medida que ya no queden ramas ni tags que lo referencien.

Si quieres gatillar esa limpieza manualmente puedes hacer

git gc --prune=now

Hay un flag que puedes darle que es más radical, y según Linus Torvalds (que además de Linux inventó Git) puede dañar seriamente un repo dependiendo de la profundidad de sus deltas:

git gc --prune=now --aggressive

PD: Encontré el hilo que leí una vez, y menciona

Date: Wed, 5 Dec 2007 22:09:12 -0800 (PST) From: Linus Torvalds Subject: Re: Git and GCC

Absolutely. git --aggressive is mostly dumb. It's really only useful for the case of "I know I have a really bad pack, and I want to throw away all the bad packing decisions I have done".

ffflabs
  • 21,223
  • 25
  • 48
2

Si lo que quieres es borrar el commit "Segundo". El branch que debiste borrar era "inicio" y no master.

Al poner git branch -D master estás borrando master, no "inicio".

Por otro lado, lo importante aquí es entender que los commits no son como files separados, sino que son momentos en la historia de versiones de tu aplicación. Por lo que "borrar un commit" no tiene mucho sentido, pues es muy distinto borrar el último commit, que borrar el commit número 34 de 100.

Lo que uno puede hacer con un commit es borrar los cambios que se hicieron en él. Entonces, por ejemplo, es como si rebobinaras todos los cambios que se hicieron en ese lapso de tiempo (entre el commit anterior y el commit siguiente).

La mejor explicación que he visto en español hasta el momento está aquí mismo:

¿Cómo puedo deshacer el último commit en Git?

sujumayas
  • 21
  • 3
  • Cuando concluyen los comandos que pongo de ejemplo en el primer bloque de código la rama inicio apunta al commit "Primer" y la rama master apunta la commit "Segundo". Es cierto que borrar la rama master no borra el commit "Segundo" (aunque con el tiempo acabaría resultando en eso gracias al garbage collector); pero es falso que debiese borrar la rama inicio puesto que esta rama apunta al commit "Primer" que es el que quiero conservar. Y borrar un commit sí que tiene mucho sentido si es local y nunca lo has publicado. – Anonymous Coward Apr 24 '17 at 06:46
  • Tienes toda la razón. Nunca hiciste Checkout al branch 'inicio', que tiene un solo commit y es 'master' el que tiene los 2 commits. – sujumayas May 03 '17 at 22:27