Git diff –name-only et copie cette liste

Je veux juste obtenir une liste des fichiers modifiés entre deux révisions, ce qui est simple:

git diff -–name-only commit1 commit2 > /path/to/my/file 

Mais, que dois-je écrire, si je veux copier tous les fichiers listés à un autre endroit? Et j’ai besoin d’une structure de répertoires complètement identique pour les fichiers copiés.

Par exemple, j’ai modifié et ajouté des fichiers:

 /protected/texts/file1.txt /protected/scripts/index.php /public/pics/pic1.png 

Je veux avoir dans /home/changes/ tous ces fichiers modifiés et ajoutés:

 /home/changes/protected/texts/file1.txt /home/changes/protected/scripts/index.php /home/changes/public/pics/pic1.png 

Essayez la commande suivante, que j’ai testée:

 $ cp -pv --parents `git diff --name-only` DESTINATION-DIRECTORY 

Ce qui suit devrait fonctionner correctement:

 git diff -z --name-only commit1 commit2 | xargs -0 -IREPLACE rsync -aR REPLACE /home/changes/protected/ 

Pour expliquer plus loin:

  • Le git diff --name-only -z à avec git diff --name-only signifie git diff --name-only sortie de la liste des fichiers séparés par des octets NUL au lieu de nouvelles lignes, juste au cas où vos noms de fichiers contiennent des caractères inhabituels.

  • Le -0 à xargs dit interpréter l’entrée standard comme une liste de parameters séparés par NUL.

  • Le -IREPLACE est requirejs car, par défaut, xargs appenda les parameters à la fin de la commande rsync . Au lieu de cela, cela dit de les placer là où se trouve le REPLACE ultérieur. (C’est une bonne astuce de cette réponse de faute de serveur .)

  • Le paramètre -a de rsync signifie si possible conserver les permissions, la propriété, etc. Le -R signifie utiliser le chemin relatif complet lors de la création des fichiers dans la destination.

Mise à jour: si vous avez une ancienne version de xargs , vous devrez utiliser l’option -i au lieu de -I . (Le premier est déconseillé dans les versions ultérieures de findutils .)

Voici un one-liner:

Lister les fichiers modifiés et les emballer comme * .zip:

 git diff --name-only | zip patched.zip -@ 

Lister les derniers fichiers modifiés validés et les emballer en tant que * .zip:

 git diff --name-only HEAD~ HEAD | zip patched.zip -@ 
 zip update.zip $(git diff --name-only commit commit) 
 #!/bin/bash # Target directory TARGET=/target/directory/here for i in $(git diff --name-only) do # First create the target directory, if it doesn't exist. mkdir -p "$TARGET/$(dirname $i)" # Then copy over the file. cp -rf "$i" "$TARGET/$i" done 

https://stackoverflow.com/users/79061/sebastian-paaske-t%c3%b8rholm

Cela fonctionne parfaitement.

 git diff 1526043 82a4f7d --name-only | xargs zip update.zip git diff 1526043 82a4f7d --name-only |xargs -n 10 zip update.zip 

Personne n’a mentionné cpio qui est facile à taper, crée des liens durs et gère les espaces dans les noms de fichiers:

 git diff --name-only $from..$to | cpio -pld outdir