Mueva una confirmación de raíz a una posterior, descartando cada historial anterior

Como una continuación de esta pregunta , me gustaría:

  • keep n last commit
  • eliminar todo n + 1 y confirmaciones anteriores del historial
  • make commit n like un repository recién iniciado

Por ejemplo, considere el siguiente tree de commits:

1-2-3-4-5 

Después de la siguiente confirmación, quiero que sea:

 2-3-4-5-6 

Sin embargo, lo que sucede en 1 ya no debe ser rastreado. es decir: 2 debería ser la raíz ahora. Esto es necesario porque habrá una gran cantidad de files binarys involucrados y no quiero que Git almacene lo que ya debería haber desaparecido. El uso de git rebase + squash mantendrá el file en el historial, solo los commits aplastados.

La idea es usar git como un sistema de respaldo periódico, que admite hasta las últimas n confirmaciones. En la realidad, habrá un trabajo cron cometiendo lo que ha cambiado todos los días.

Creo que la mejor manera de get esto es creando una twig huérfana a partir de 2 y luego haciendo una rebase, de esta manera:

 git checkout 2 git checkout --orphan newmaster # creates a new orphan branch with no parents git commit -C 2 # commits all the contents from 2 using same commit message of 2 git rebase --onto HEAD 2 master # rebase all contents from master to this new branch git push -f origin master:refs/heads/master # push the new master branch 

Tenga en count que estamos utilizando -f (force) en el último command, esto debería ser una exception, no la regla y todo esto debe hacerse en un repository "congelado", el compromiso 1 no será accesible ahora y cualquier blob o contenido asociado a esa confirmación será eliminada por git gc si no quedan otras references (puede ejecutar git gc a mano, o se ejecuta automáticamente dependiendo de la configuration de su server de git)

Otra opción: usar git-filter-branch

Si su problema son los files pesados ​​que ocupan demasiado espacio en el repository, no es necesario volver a escribir el historial para eliminar estos files del repository, git-filter-branch es la herramienta diseñada para este tipo de situaciones, este es un ejemplo básico:

 git filter-branch --tree-filter 'rm path/to/heavyfile; true' 

Reconstruye todo el historial de la twig actual (ej. Rama principal), pero ejecuta su command bash para cada confirmación, eliminando / ruta / a / file pesado para todas las confirmaciones en este caso. Por supuesto, puede mejorar el script, por ejemplo, eliminar directorys completos, cambiar el nombre de los files o incluso llamar a sus propios commands externos

Lo mejor de esto es que esta acción se puede deshacer fácilmente en caso de que haya cometido un error, deshacer una twig de filter es tan fácil como:

 git reset --hard [email protected]{1} 

Más sobre git-filter-branch: http://git-scm.com/docs/git-filter-branch

Más sobre reescribir la historia con git: http://git-scm.com/book/es/Git-Tools-Rewriting-History

Creo que le gustaría eliminar los objects blob que no son alcanzables desde los objects commit. Estos objects se llaman objects inalcanzables o colgantes. En realidad, Git ya ha proporcionado un buen mecanismo de limpieza que se llama auto gc . También puede ejecutar git gc manualmente. Comprimirá las versiones de files y eliminará los objects inalcanzables con algunos meses de antigüedad. El trabajo de compression es probablemente mejor de lo que piensas. Según mi testing, almacena las diferencias de versiones de files incluso para files binarys.

Hay algunos commands más relacionados, como git fsck , git prune , git repack y git prune-packed , si desea un comportamiento más manual y personalizado.

Pero mi sugerencia es solo establecer gc.reflogExpireUnreachable y gc.reflogExpire más cortos como 1 día, y ejecutar "git gc" en el transcurso del time, y dejar que git haga el trabajo por usted. Pero no estoy seguro si es práctico ya que no lo he probado.

Algunas references adjuntas.

http://git-scm.com/book/es/Git-Internals-Maintenance-and-Data-Recovery#Mantenimiento

Ocasionalmente, Git ejecuta automáticamente un command llamado "auto gc". La mayoría de las veces, este command no hace nada. Sin embargo, si hay demasiados objects sueltos (objects que no están en un file de package) o demasiados packages de files, Git lanza un command git gc completo. El gc significa recolección de basura, y el command hace varias cosas: reúne todos los objects sueltos y los coloca en files de packages, consolida los files de packages en un gran file de packages y elimina los objects que no son accesibles desde ningún compromiso y tienen algunos meses de edad.

http://git-scm.com/docs/git-gc

git gc ejecuta una serie de tareas domésticas dentro del repository actual, como comprimir revisiones de files (para networkingucir el espacio en disco e incrementar el performance) y eliminar objects inalcanzables que pueden haberse creado a partir de invocaciones anteriores de git add.