Header Ads

git filter-branch: A rey muerto rey puesto

Si queríamos eliminar archivos grandes de un repositorio de github o similar y de paso hacer limpieza, con los siguientes comandos lo hacíamos:
#!/bin/bash
bigfile="bigfile.tar.gz"
project="/path_to_mygitproject/"
cd $project
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch '"$bigfile"'' --prune-empty --tag-name-filter cat -- --all
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch '"$bigfile"'' HEAD
git clean -nd
git clean -fd
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now --aggressive
O también podríamos limpiar la basura con el script git-gc-all; en fin, sin importar el método que use para limpiar su repositorio, si involucra el comando  git filter-branch sepa que llegó a su fin y al ejecutarlo arroja el siguiente mensaje:
WARNING: git-filter-branch has a glut of gotchas generating mangled history
     rewrites.  Hit Ctrl-C before proceeding to abort, then use an
     alternative filtering tool such as 'git filter-repo'
     (https://github.com/newren/git-filter-repo/) instead.  See the
     filter-branch manual page for more details; to squelch this warning,
     set FILTER_BRANCH_SQUELCH_WARNING=1.
Para solucionarlo, algunos optan por el proyecto  BFG Repo-Cleaner, pero lo que se recomienda en el mensaje anterior es el proyecto  git-filter-repo.
Para usarlo, descargamos el script en python:
echo $PATH
/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
wget https://raw.githubusercontent.com/newren/git-filter-repo/master/git-filter-repo -O /home/user/.local/bin/git-filter-repo
chmod +x /home/user/.local/bin/git-filter-repo
Según la documentacióngit filter-repo simplifica todo, por ejemplo, estos comandos para eliminar archivos:
git filter-branch --tree-filter 'rm filename' HEAD
git filter-branch --tree-filter 'rm -f filename' HEAD
git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
Se convierten en uno solo:
git filter-repo --invert-paths --path filename
Y para nuestro ejemplo sería así:
git filter-repo --force --path /path_to_mygitproject/bigfile.tar.gz --invert-paths
clean git repo
Eso reemplazaría las dos primeras líneas del script bash. Pero si quiere eliminar cualquier archivo de su repositorio, por ejemplo que tenga más de 10 M, entonces con este:
git filter-repo --force --strip-blobs-bigger-than 10M
Como vemos es mucho más simple. Para mayor información sobre otros comandos pulse AQUI
source
Actualización 2023
Algunos comandos cambiaron. Ahora para trabajar con filter-repo hay que instalarlo. 
En Ubuntu 22.04 es:
sudo apt install git-filter-repo
Y se reemplaza:
git filter-repo
Por:
git-filter-repo
Y para regresar a un commit anterior se reemplaza:
git reset --hard HEAD~1
Por:
git reset --hard HEAD@{1}
Con la tecnología de Blogger.