Una forma de hacerlo es a la inversa: elimine todo menos el archivo que desea conservar.
Básicamente, haga una copia del repositorio, luego use git filter-branch
para eliminar todo menos los archivos / carpetas que desea conservar.
Por ejemplo, tengo un proyecto del que deseo extraer el archivo tvnamer.py
a un nuevo repositorio:
git filter-branch --tree-filter 'for f in *; do if [ $f != "tvnamer.py" ]; then rm -rf $f; fi; done' HEAD
Eso suele git filter-branch --tree-filter
pasar por cada confirmación, ejecutar el comando y volver a comprometer el contenido de los directorios resultantes. Esto es extremadamente destructivo (¡por lo que solo debe hacer esto en una copia de su repositorio!), Y puede tomar un tiempo (aproximadamente 1 minuto en un repositorio con 300 confirmaciones y aproximadamente 20 archivos)
El comando anterior solo ejecuta el siguiente script de shell en cada revisión, que tendría que modificar, por supuesto (para que excluya su subdirectorio en lugar de tvnamer.py
):
for f in *; do
if [ $f != "tvnamer.py" ]; then
rm -rf $f;
fi;
done
El mayor problema obvio es que deja todos los mensajes de confirmación, incluso si no están relacionados con el archivo restante. El script git-remove-empty-commits corrige esto ...
git filter-branch --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'
Debe usar el -f
argumento de fuerza para ejecutar filter-branch
nuevamente con cualquier cosa en refs/original/
(que básicamente es una copia de seguridad)
Por supuesto, esto nunca será perfecto, por ejemplo, si sus mensajes de confirmación mencionan otros archivos, pero es lo más cercano que permite una corriente de git (que yo sepa de todos modos).
Nuevamente, ¡solo ejecute esto en una copia de su repositorio! - pero en resumen, para eliminar todos los archivos excepto "thisismyfilename.txt":
git filter-branch --tree-filter 'for f in *; do if [ $f != "thisismyfilename.txt" ]; then rm -rf $f; fi; done' HEAD
git filter-branch -f --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'