2012-08-13 11 views
19

Tengo un repositorio de Git muy grande que solo contiene archivos binarios que se cambian con bastante frecuencia. Naturalmente, el repositorio Git es mucho más grande que los archivos reales en él. Realmente no me importa la historia anterior, solo necesito algo de la historia más reciente para poder revertir algunos cambios incorrectos. Entonces digamos que quiero eliminar todas las confirmaciones, excepto las últimas cinco.Cómo eliminar todas las confirmaciones de Git, excepto las últimas cinco

Naturalmente, quiero hacer esto para mantener el repositorio pequeño para que las confirmaciones eliminadas se eliminen por completo del repositorio.

Y quiero hacer todo esto de forma no interactiva con un solo comando (alias) o script. ¿Cómo puedo hacer esto?

+2

Esto podría ayudar: http://stackoverflow.com/questions/250238/collapsing-a-git-repositorys-history –

+3

¿Seguro que deseas _remove_ todos los viejos commits? Significa también eliminar sus cambios. GIT no almacena el "estado actual" en cada confirmación, solo almacena un cambio. Lo que quieres hacer es aplastar todos los compromisos anteriores en uno, ¿no? – amorfis

Respuesta

8

Aquí hay un alias rebase-last-five para comenzar. Recreará la rama actual, por lo que solo se incluirán en la historia las cinco confirmaciones más recientes. Probablemente sea mejor hacer de esto una secuencia de comandos (git-rebase-last-five.sh) que esté disponible en un directorio en su PATH; Git buscará y usará scripts llamados git-....sh sin necesidad de ninguna configuración especial. La secuencia de comandos debería hacer más comprobación de errores y manejo que este alias simple.

$ git config --global alias.rebase-last-five '!b="$(git branch --no-color | cut -c3-)" ; h="$(git rev-parse $b)" ; echo "Current branch: $b $h" ; c="$(git rev-parse $b~4)" ; echo "Recreating $b branch with initial commit $c ..." ; git checkout --orphan new-start $c ; git commit -C $c ; git rebase --onto new-start $c $b ; git branch -d new-start ; git gc' 

caveat.emptor: No prestar atención a la warnings about changing history. Para obtener más información, consulte las páginas man (git help <command> o online).

Un ejemplo de uso:

$ git --version 
git version 1.7.12.rc2.16.g034161a 
$ git log --all --graph --decorate --oneline 
* e4b2337 (HEAD, master) 9 
* e508980 8 
* 01927dd 7 
* 75c0fdb 6 
* 20edb42 5 
* 1260648 4 
* b3d6cc8 3 
* 187a0ef 2 
* e5d09cf 1 
* 07bf1e2 initial 
$ git rebase-last-five 
Current branch: master e4b2337ef33d446bbb48cbc86b44afc964ba0712 
Recreating master branch with initial commit 20edb42a06ae987463016e7f2c08e9df10fd94a0 ... 
Switched to a new branch 'new-start' 
[new-start (root-commit) 06ed4d5] 5 
1 file changed, 1 insertion(+) 
create mode 100644 A 
First, rewinding head to replay your work on top of it... 
Applying: 6 
Applying: 7 
Applying: 8 
Applying: 9 
Deleted branch new-start (was 06ed4d5). 
Counting objects: 35, done. 
Delta compression using up to 2 threads. 
Compressing objects: 100% (15/15), done. 
Writing objects: 100% (35/35), done. 
Total 35 (delta 4), reused 0 (delta 0) 
$ git log --all --graph --decorate --oneline 
* a7fb54b (HEAD, master) 9 
* 413e5b0 8 
* 638a1ae 7 
* 9949c28 6 
* 06ed4d5 5 
+3

¡Funciona muy bien! ¡Gracias! Pero en lugar de usar simplemente 'git gc' tuve que usar' git reflog expire --expire = now --all; git gc --prune = now' para hacer que el repositorio sea más pequeño. – kayahr

+0

@kayahr Me alegro de que esto te haya ayudado. Gracias por compartir los cambios que realmente funcionaron para usted. –

+0

Muchas gracias, funciona. Debería descomponer la secuencia de comandos en varias líneas en su respuesta. Personalmente prefiero entender lo que estoy haciendo a mi repositorio antes de ejecutar un script externo. – JulienD

8

Ok, si quieres lo que yo creo que usted quiere (ver mi comentario), creo que esto debería funcionar:

  1. Crear rama para guardar todas las confirmaciones (y por si acaso):

    git branch fullhistory

  2. Mientras que aún en maestro, restablecer --hard al comprometerse desea conservar la historia de:

    git reset --hard HEAD~5

  3. Ahora restablecer sin --hard al principio de la historia, esto debería dejar intacto su espacio de trabajo, por lo que permanece en estado HEAD ~ 5.

    git reset --soft <first_commit>

  4. Así que ahora tiene la historia vacío en master, y todos los cambios que necesita en el espacio de trabajo. Simplemente compromételos.

    git commit -m "all the old changes squashed"

  5. Ahora cereza recoger este 4 confirmaciones de fullhistory usted quiere tener aquí:

    git cherry-pick A..B

Donde A es mayor que B, y recuerde un NO está incluido . Por lo tanto, debe ser el padre del compromiso más antiguo que desee incluir.

Cuestiones relacionadas