2011-04-09 2 views
105

Je veux juste obtenir une liste des fichiers modifiés entre deux révisions, ce qui est simple:Git diff --name seule et copier cette liste

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

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

Par exemple, je l'ai modifié et les fichiers ajoutés:

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

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

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

Je ne comprends pas tout à fait ce que vous essayez d'atteindre ... la propagation des modifications à différents clones? créer des correctifs? patcher des fichiers en dehors d'un dépôt git? – knittl

+0

Pas de patch, mais la structure de copie exacte des fichiers modifiés. Comme patch, mais avec des fichiers solides – BazZy

+0

Et oui, patcher les fichiers en dehors de git repository - cible la plus proche pour moi :) – BazZy

Répondre

86

Essayez la commande suivante, que je l'ai testé:

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

Merci pour l'indice '' cp --parents'', j'ai voulu cette option depuis des années et je n'ai jamais su qu'elle existait! Il est évident que je n'ai jamais pris la peine de le chercher non plus = –

+1

Notez que cela ne fonctionne pas sur Mac, car l'option '--parents' de' cp' n'est pas disponible. –

+0

Des conseils sur l'utilisation de cette option si les fichiers ont des caractères inhabituels? Espace blanc, caractères nordiques. –

9

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 -z à git diff --name-only avec des moyens pour sortir la liste des fichiers séparés avec NUL octets au lieu de nouvelles lignes, juste au cas où vos noms ont des caractères inhabituels en eux.

  • Le -0 à xargs indique d'interpréter l'entrée standard comme une liste de paramètres séparés par NUL. Le -IREPLACE est nécessaire car, par défaut, xargs ajoute les paramètres à la fin de la commande rsync. Au lieu de cela, cela dit de les mettre où le plus tard REPLACE est. (C'est une bonne astuce de this Server Fault answer.)

  • Le paramètre -a à signifie conserver les autorisations, la propriété, etc. si possible. 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 obsolète dans les versions ultérieures de findutils.)

+0

J'ai une erreur : xargs: option invalide - I – BazZy

+0

C'est étrange - quel système d'exploitation utilisez-vous? Si c'est une distribution Linux, laquelle, et que dit 'xargs --version'? –

+0

GNU xargs version 4.1 – BazZy

5

Voici un one-liner:

Liste les fichiers modifiés les emballer & comme * .zip:

git diff --name-only | zip patched.zip [email protected] 

Liste dernière engagés fichiers modifiés & les emballer comme *.zip:

git diff --name-only HEAD~ HEAD | zip patched.zip [email protected] 
+0

Si vous utilisez Windows, vous pouvez télécharger zip de ligne de commande à partir de https://sourceforge.net/projects/gnuwin32/files/zip/ – Radon8472

3
zip update.zip $(git diff --name-only commit commit) 
1

Il fonctionne parfaitement.

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

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

Personne ne l'a mentionné cpio qui est facile à saisir, crée des liens durs et gère les espaces dans les noms de fichiers:

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