Una forma de hacerlo es 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 a partir del cual deseo para 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
que utiliza git filter-branch --tree-filter
que pasar por cada confirmación, ejecute el comando y renovar el contenido de directorios resultante . Esto es extremadamente destructivo (¡así 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 simplemente ejecuta el siguiente script de shell en cada revisión, que habría que modificar, por supuesto, (para que sea excluye 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 a todos los mensajes de confirmación, incluso si no están relacionados con el archivo restante. El guión git-remove-empty-commits, soluciona este ..
git filter-branch --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "[email protected]"; else git commit-tree "[email protected]"; fi'
Es necesario utilizar el argumento de la fuerza -f
plazo filter-branch
de nuevo con nada en refs/original/
(que básicamente una copia de seguridad)
Por supuesto, esto nunca será perfecto, por ejemplo, si los mensajes de confirmación mencionan otros archivos, pero es lo más aproximado que permite una corriente de git (hasta donde yo sé).
De nuevo, ¡solo ejecute esto en una copia de su repositorio! - pero en resumen, para eliminar todos los archivos, pero "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 "[email protected]"; else git commit-tree "[email protected]"; fi'
También una muy buena respuesta: http://stackoverflow.com/questions/359424/detach-subdirectory-into-separate-git-repository –