73 votes

Comment déplacer un répertoire dans un repo Git pour tous les commits ?

Disons que j'ai un dépôt qui comprend cette structure de répertoire :

repo/
  blog/
    _posts/
      some-post.html
  another-file.txt

Je veux bouger _posts au niveau supérieur du repo, de sorte que la structure ressemblera à ceci :

repo/
  _posts/
    some-post.html
  another-file.txt

C'est assez simple avec git mv mais je veux faire en sorte que l'histoire ait l'air d'être _posts toujours existait à la racine du dépôt, et je veux être capable d'obtenir l'historique entier de some-post.html via git log -- _posts/some-post.html . J'imagine que je peux utiliser un peu de magie avec git filter-branch pour y parvenir, mais je n'ai pas encore trouvé comment le faire exactement. Avez-vous des idées ?

103voto

Ramkumar Ramachandra Points 1739

Vous pouvez utiliser le filtre de sous-répertoire pour réaliser ceci

 $ git filter-branch --subdirectory-filter blog/ -- --all

EDIT : Si vous ne voulez pas faire efficacement _posts la racine, utilisez plutôt un filtre d'arbre :

 $ git filter-branch --tree-filter 'mv blog/_posts .' HEAD

EDIT 2 : Si blog/_posts n'existait pas dans certains des commits, l'opération ci-dessus échouera. Utilisez ceci à la place :

 $ git filter-branch --tree-filter 'test -d blog/_posts && mv blog/_posts . || echo "Nothing to do"' HEAD

4 votes

C'est aussi beaucoup plus rapide à utiliser --index-filter puisqu'il n'a pas à vérifier l'arbre.

7 votes

Oui, index-filter est plus rapide, mais il ne fonctionnera pas parce que les commandes indiquées font pas affectent l'indice. Vous ne devez effectuer des manipulations d'index que si vous souhaitez utiliser un filtre d'index (par ex. git rm --cached au lieu de rm )

0 votes

Je peux aussi garder les étiquettes ? Il semble qu'ils aient disparu dans mon cas.

38voto

theduke Points 578

Bien que la réponse de Ramkumar soit très utile et valable, elle ne fonctionnera pas dans de nombreuses situations. Par exemple, lorsque vous voulez déplacer un répertoire avec d'autres sous-répertoires vers un nouvel emplacement.

Pour cela, la page de manuel contient la commande parfaite :

git filter-branch --index-filter \
  'git ls-files -s | sed "s-\t\"*-&NEWSUBDIR/-" |
   GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
   git update-index --index-info &&
   mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

Remplacez simplement NEWSUBDIR par le nouveau répertoire que vous souhaitez. Vous pouvez également utiliser des répertoires imbriqués comme dir1/dir2/dir3/-"

12 votes

Et puisque ce n'est pas immédiatement évident en regardant cette commande ou les erreurs qui en résultent, la fonction \t ne fonctionne pas avec la version de sed de os x. Il y a de nombreuses façons de contourner ce problème, mais la plus rapide est peut-être de supprimer le fichier \t et le remplacer par une tabulation littérale en tapant ctrl-v, <tab>.

4 votes

Comment spécifier le dossier d'origine, ou cela déplace-t-il simplement la branche entière ? Lorsque j'essaie d'exécuter cette opération à partir d'un dossier que j'aimerais déplacer, j'obtiens les résultats suivants You need to run this command from the toplevel of the working tree

1 votes

Que fait le sed commande font ? J'essaie de le faire sous Windows et j'ai besoin d'une alternative.

2voto

Jonas Berlin Points 719

Création d'un script générique pour les déplacements/renommages arbitraires : https://gist.github.com/xkr47/f766f4082112c086af63ef8d378c4304

Exemples :

git filter-mv 's!^!subdir/!'

déplace tous les fichiers vers un sous-répertoire "subdir/" dans tous les commits de la branche courante

git filter-mv 's!^foo/bar.txt$!foo/barbar.txt!'

renomme foo/bar.txt en foo/barbar.txt dans tous les commits de la branche courante

1voto

Constantine Points 21

Git filter-branch est découragée. Vous pouvez utiliser git filter-repo est beaucoup plus pratique :

git filter-repo --path-rename blog/_posts:_posts

Voir aquí .

Notez également que l'installation est en quelque sorte brisé et vous devez l'installer à partir de pip et ajouter git-filter-repo a $PATH

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X