Une façon de procéder est l'inverse : supprimez tout sauf le fichier que vous souhaitez conserver.
En gros, faire une copie du référentiel, puis utilisez git filter-branch
pour supprimer tout sauf les fichiers/dossiers que vous souhaitez conserver.
Par exemple, j'ai un projet duquel 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 utilise git filter-branch --tree-filter
pour passer par chaque commit, exécuter la commande et recommencer le contenu des répertoires résultants. Ceci est extrêmement destructif (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 shell-script suivant sur chaque révision, que vous devrez modifier bien sûr (pour qu'il exclue 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 commit, même s'ils n'ont aucun rapport avec le fichier restant. Le script git-remove-empty-commits , répare ceci..
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 le -f
forcer l'exécution de l'argument filter-branch
à nouveau avec tout ce qui est dans refs/original/
(qui est en fait une sauvegarde)
Bien sûr, cela ne sera jamais parfait, par exemple si vos messages de commit mentionnent d'autres fichiers, mais c'est à peu près ce qu'un courant git permet (pour autant que je sache, en tout cas).
Encore une fois, n'exécutez cette opération que sur une copie de votre référentiel ! - mais en résumé, pour supprimer tous les fichiers sauf "ceci-mon-nom-de-film.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'