¿Cómo eliminar el historial anterior después de ejecutar git filter-branch?

Supongamos que tengo tal tree:

... -- a -- b -- c -- d -- ... \ e -- a -- k 

y quiero que se convierta en solo

 ... -- a -- b -- c -- d -- ... 

Sé cómo adjuntar el nombre de la sucursal a "e". Sé que lo que voy a hacer cambiará la historia, y esto es malo. También creo que necesito usar algo como rebase o filter-branch. Pero ¿cómo exactamente? Estoy perdido.

De acuerdo. La situación es la siguiente: ahora tengo un tree bastante grande (como este)

  s -- p -- r / a -- b -- c -- d -- e --- g -- w \ \ t -- p -- ly -- k 

pero en mi uno de los primeros commits (como por ejemplo "b") agregué files binarys, lo que hace que el repo completo sea muy pesado. Así que decidí llevármelas. Lo hice con filter-branch. Y ahora tengo 2 twigs largas de commits idénticas entre sí desde el segundo commit.

  s -- p -- r / a -- b -- c -- d -- e --- g -- w \ \ \ \ t -- p -- ly -- k \ \ s'-- p'-- r' \ / b'-- c'-- d'-- e'--- g'-- w' \ \ t'-- p'-- l' y'-- k' 

donde b 'se confirma sin file binary. Entonces no puedo hacer una fusión. No quiero que todo este tree esté duplicado en el historial.

Después de importar un repository de Subversion con varios años de historia, me encontré con un problema similar con la hinchazón de muchos activos binarys. En git: contracción de la import de Subversion , describo el recorte de mi git repo de 4.5 GiB a alnetworkingedor de 100 MiB.

Suponiendo que desea eliminar de todos los commits los files eliminados en "Eliminar files multimedia" (6fe87d) , puede adaptar el enfoque desde mi publicación de blog a su repository:

  $ git filter-branch -d / dev / shm / git --index-filter \
   "git rm --cached -f --ignore-unmatch media / Optika.1.3.?. *; \
    git rm --cached -f --ignore-unmatch media / lens.svg;  \
    git rm --cached -f --ignore-unmatch media / lens_simulation.swf;  \
    git rm --cached -f --ignore-unmatch media / v.html "\
   --tag-name-filter cat --prune-empty - --all 

Su repo de github no tiene ninguna label, pero incluyo un filter de nombre de label en caso de que tenga tags privadas.

La documentation de git filter-branch cubre la opción --prune-empty .

--prune-empty
Algunos types de filters generarán commits vacíos que dejan el tree intacto. Este interruptor permite a git-filter-branch ignorar dichos commits …

Usar esta opción significa que su historial reescrito no contendrá una confirmación de "Eliminar files multimedia" porque ya no afecta al tree. Los files multimedia nunca se crean en el nuevo historial.

En este punto, verá la duplicación en su repository debido a otro comportamiento documentado .

Los refs originales, si son diferentes de los reescritos, se almacenarán en el espacio de nombres refs/original/ .

Si está satisfecho con el nuevo historial reescrito, elimine las copys de security.

  $ git for-each-ref --format = "% (refname)" refs / original / |  \
   xargs -n 1 git actualización-ref -d 

Git está atenta a la protección de su trabajo, por lo que incluso después de toda esta reescritura intencional y eliminación del reflog es mantener vivos los viejos commits. Purgarlos con una secuencia de dos commands:

  $ git reflog expire --verbose --expire = 0 --todo
 $ git gc --prune = 0 

Ahora su repository local está listo, pero debe enviar las actualizaciones a GitHub. Podrías hacerlos uno a la vez. Para una sucursal local, digamos maestro, correría

  $ git push -f origin master 

Digamos que ya no tiene una twig local de issue5. Su clon todavía tiene una reference llamada origin / issue5 que rastrea dónde está en su repository de GitHub. Ejecutar git filter-branch modifica todos los refs de origen también, por lo que puede actualizar GitHub sin una bifurcación.

  $ git push -f origin origin / issue5: issue5 

Si todas sus sucursales locales coinciden con sus respectivos commits en el lado de GitHub ( es decir , sin commits sin pérdidas), entonces puede realizar una actualización masiva.

  $ git for-each-ref --format = "% (refname)" refs / remotes / origin / |  \
   grep -v 'HEAD $' |  perl -pe 's, ^ refs / remotes / origin / ,,' |  \
   xargs -n 1 -I '{}' git push -f origen 'refs / remotes / origin / {}: {}' 

El resultado de la primera etapa es una list de refnames:

  $ git for-each-ref --format = "% (refname)" refs / remotos / origen /
 refs / remotos / origen / HEAD
 refs / remotes / origin / issue2
 refs / remotes / origin / issue3
 refs / remotes / origin / issue5
 refs / remotos / origen / maestro
 refs / remotos / origen / section_merge
 refs / remotos / origen / side-media-icons
 refs / remotes / origin / side-pane-splitter
 refs / remotos / origen / side-popup
 refs / remotes / origin / v2 

No queremos el pseudo ref de HEAD y lo grep -v con grep -v . Por lo demás, usamos Perl para quitar los refs/remotes/origin/ prefix y para cada uno ejecutamos un command de la forma

  $ git push -f origen refs / remotos / origen / SUCURSAL: SUCURSAL 

Tratar:

git branch -d nombre

Puede que necesite usar esto en su lugar:

git branch -D nombre

Puede eliminar las twigs con git branch -D branch_name y eliminar las sucursales remotas con git push remote_name :branch_name .

Las confirmaciones permanecerán sin references en su repository durante un time (consulte git gc doc ), pero solo usarán espacio en disco en caso de que se dé count más tarde de que cometió un error.

Y como eliminó las twigs remotas, un nuevo git clone no debería recuperar las confirmaciones sin reference.

Puede usar git filter-branch nuevamente , pero esta vez con la opción –parent-filter. Con esto puedes desvincular los commits al configurar las references de sus padres a nada. Creo que puede usar la opción –commit-filter para el mismo propósito. Esto dejará una gran cantidad de objects sueltos diferentes en su repository, por lo que debe hacer git gc –prune = now.

Aquí hay un ejemplo de cómo se puede usar el –parent-filter para eliminar a los padres http://git.661346.n2.nabble.com/purging-unwanted-history-td1507638.html

De tu ejemplo, ¿podrías probar git rebase b b' ?