Une façon de faire est l'inverse: supprimez tout sauf le fichier que vous souhaitez conserver.
En gros, faites une copie du référentiel, puis utilisez git filter-branch
pour supprimer tout sauf le fichier / les dossiers que vous souhaitez conserver.
Par exemple, j'ai un projet dont je souhaite extraire le fichier tvnamer.py
vers un nouveau référentiel:
git filter-branch --tree-filter 'for f in *; do if [ $f != "tvnamer.py" ]; then rm -rf $f; fi; done' HEAD
Cela permet git filter-branch --tree-filter
de parcourir chaque commit, d'exécuter la commande et de réitérer le contenu des répertoires résultant. Ceci est extrêmement destructeur (vous ne devriez donc le faire que sur une copie de votre référentiel!), Et peut prendre un certain temps (environ 1 minute sur un référentiel avec 300 commits et environ 20 fichiers)
La commande ci-dessus exécute simplement le script shell suivant sur chaque révision, que vous devrez bien sûr modifier (pour le faire exclure votre sous-répertoire au lieu de tvnamer.py
):
for f in *; do
if [ $f != "tvnamer.py" ]; then
rm -rf $f;
fi;
done
Le plus gros problème évident est qu'il laisse tous les messages de validation, même s'ils ne sont pas liés au fichier restant. Le script git-remove-empty-commits corrige ce problème.
git filter-branch --commit-filter 'if [ z$1 = z`git rev-parse $3^{tree}` ]; then skip_commit "$@"; else git commit-tree "$@"; fi'
Vous devez utiliser l' -f
argument force run à filter-branch
nouveau avec tout ce qui se trouve dans refs/original/
(qui essentiellement une sauvegarde)
Bien sûr, ce ne sera jamais parfait, par exemple si vos messages de commit mentionnent d'autres fichiers, mais c'est à peu près aussi proche qu'un git current le permet (pour autant que je sache de toute façon).
Encore une fois, ne l'exécutez que sur une copie de votre référentiel! - mais en résumé, pour supprimer tous les fichiers sauf "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'