Git diff - solo nome e copia quell'elenco


151

Voglio solo ottenere un elenco di file modificati tra due revisioni, il che è semplice:

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

Ma cosa devo scrivere se voglio copiare tutti i file elencati in un altro posto? E ho bisogno di una struttura di directory completamente identica per i file copiati.

Ad esempio, ho modificato e aggiunto file:

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

Voglio avere in /home/changes/tutti quei file modificati e aggiunti:

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

1
non capisco bene cosa stai cercando di ottenere ... propagando le modifiche a diversi cloni? creare patch? patch file al di fuori di un repository git?
Knittl

Non patch, ma struttura esatta della copia dei file modificati. Come patch, ma con file solidi
BazZy

E sì, patch file al di fuori del repository git - target più vicino per me :)
BazZy,

3
spiacente. CHE COSA? si desidera acquisire e riprodurre le modifiche ai file e le modifiche agli alberi? questa è una patch. git format-patchpuò farlo per gli intervalli di commit.
Knittl

1
git diff commit1 commit2 > my.patche poi cd other/path; patch -p1 < my.patch. Perché deve essere fatto con copie complete dei file? Se è perché pensi che la patch potrebbe non essere applicabile, e quindi l'altra directory non è davvero nello commit1stato, dovresti davvero copiare tutto dallo commit2stato ...
Cascabel,

Risposte:


118

Prova il seguente comando, che ho testato:

$ cp -pv --parents $(git diff --name-only) DESTINATION-DIRECTORY

2
Grazie per il cp --parentssuggerimento, ho desiderato quell'opzione per anni e non ho mai saputo che esistesse! ... ovviamente non mi sono mai preso la briga di cercarlo = \
Stephan Henningsen

2
Nota che questo non funziona su Mac, in quanto l' --parentsopzione di cpnon è disponibile.
M. Justin,

Qualche consiglio su come usare questo se i file hanno caratteri insoliti? Spazi bianchi, caratteri nordici.
Halvor Holsten Strand,

@HalvorStrand, non l'ho provato, ma l'impostazione IFS=$'\n'prima potrebbe farlo. (Preferibilmente in una subshell per non rovinare il valore IFS originale.)
Carattere jolly

Ricevo un errore cp: cannot stat 'git diff --name-only': No such file or directorysu Git Bash su Windows. Che cosa sto facendo di sbagliato? La directory di destinazione esiste
Shiva il

14

Quanto segue dovrebbe funzionare bene:

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

Per spiegare ulteriormente:

  • Il -zto with git diff --name-onlyconsente di visualizzare un elenco di file separati da byte NUL anziché newline, nel caso in cui i nomi dei file contengano caratteri insoliti.

  • Il -0to xargsdice di interpretare l'input standard come un elenco di parametri separato da NUL.

  • Il -IREPLACEè necessaria poiché per default xargssarebbe aggiungere i parametri alla fine del rsynccomando. Invece, questo dice di metterli dove si trova il dopo REPLACE. (Questo è un bel consiglio da questa risposta di errore del server .)

  • Il -aparametro rsyncsignifica significa conservare autorizzazioni, proprietà, ecc. Se possibile. I -Rmezzi per utilizzare il percorso relativo completo durante la creazione dei file nella destinazione.

Aggiornamento: se hai una versione precedente di xargs, dovrai usare l' -iopzione invece di -I. (Il primo è deprecato nelle versioni successive di findutils.)


È strano - che sistema operativo stai usando? Se si tratta di una distribuzione Linux, quale e cosa xargs --versiondice?
Mark Longair,

1
Ah, in quella versione di xargs devi usare -iinvece, che è deprecato nelle versioni successive - la 4.1 ora è piuttosto vecchia. Aggiornerò la mia risposta.
Mark Longair,

@Mark: ricordo di aver letto da qualche parte che -Iin alcune versioni hai bisogno di uno spazio , quindi forse prova -I REPLACEinvece.
Mikel

Non importa. Neanche questo funziona. -Iè supportato solo dal findutils4.2.10, rilasciato a dicembre 2004.
Mikel

È necessario aggiungere --diff-filter=dper escludere i file eliminati dall'elenco. Altrimenti finirai per ricevere errori mentre provi a copiarli nella cartella delle modifiche. Altrimenti ottima risposta. Grazie!
martedì

11

Ecco un one-liner:

Elenca i file modificati e li comprime come * .zip:

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

Elenca gli ultimi file modificati impegnati e li comprime come * .zip:

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

Se si utilizza Windows, è possibile scaricare zip della riga di comando da sourceforge.net/projects/gnuwin32/files/zip
Radon8472

@ Radon8472 Che si installa sed.exe? Non riesco ancora zipa trovarlo su Windows.
Shiva,

no, il link punta al download per zip.exe non per sed. Se non è possibile utilizzare zip nella riga di comando, è necessario aggiungere la cartella in cui zip.exe è installato nella PATHvariabile env.
Radon8472,

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


2

Funziona perfettamente.

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

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

1

Nessuno ha mai detto cpioche è facile da scrivere, crea collegamenti reali e gestisce gli spazi nei nomi dei file:

git diff --name-only $from..$to  | cpio -pld outdir
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.