Git diff - only-name und kopiere diese Liste

151

Ich möchte nur eine Liste der geänderten Dateien zwischen zwei Revisionen erhalten, was einfach ist:

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

Aber was soll ich schreiben, wenn ich alle aufgelisteten Dateien an einen anderen Ort kopieren möchte? Und ich brauche eine völlig identische Verzeichnisstruktur für kopierte Dateien.

Zum Beispiel habe ich Dateien geändert und hinzugefügt:

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

Ich möchte in /home/changes/all diesen geänderten und hinzugefügten Dateien:

/home/changes/protected/texts/file1.txt
/home/changes/protected/scripts/index.php
/home/changes/public/pics/pic1.png
BazZy
quelle
1
Ich verstehe nicht ganz, was Sie erreichen wollen ... Änderungen an verschiedenen Klonen zu verbreiten? Patches erstellen? Patchen von Dateien außerhalb eines Git-Repositorys?
Knittl
Kein Patch, aber genaue Kopierstruktur geänderter Dateien. Wie Patch, aber mit soliden Dateien
BazZy
Und ja, Dateien außerhalb des Git-Repositorys patchen - das nächste Ziel für mich :)
BazZy
3
Es tut uns leid. WAS? Sie möchten Änderungen an Dateien und Änderungen an Bäumen erfassen und wiedergeben? Das ist ein Patch. git format-patchkann dies für Festschreibungsbereiche tun.
Knittl
1
git diff commit1 commit2 > my.patchund dann cd other/path; patch -p1 < my.patch. Warum muss es mit vollständigen Kopien der Dateien gemacht werden? Wenn Sie der Meinung sind, dass der Patch möglicherweise nicht angewendet wird und das andere Verzeichnis daher nicht wirklich im commit1Status ist, sollten Sie wirklich alles aus dem commit2Status kopieren ...
Cascabel

Antworten:

118

Versuchen Sie den folgenden Befehl, den ich getestet habe:

$ cp -pv --parents $(git diff --name-only) DESTINATION-DIRECTORY
York
quelle
2
Vielen Dank für den cp --parentsHinweis, ich wollte diese Option seit Jahren und wusste nie, dass es sie gibt! .. offensichtlich habe ich mich auch nie darum gekümmert = \
Stephan Henningsen
2
Beachten Sie, dass dies auf einem Mac nicht funktioniert, da die --parentsOption von cpnicht verfügbar ist.
M. Justin
Irgendwelche Tipps zur Verwendung, wenn Dateien ungewöhnliche Zeichen haben? Leerzeichen, nordische Zeichen.
Halvor Holsten Strand
@HalvorStrand, ich habe es nicht getestet, aber die Einstellung IFS=$'\n'zuerst kann es tun. (Am besten in einer Unterschale, um Ihren ursprünglichen IFS-Wert nicht zu verfälschen.)
Wildcard
Ich erhalte eine Fehlermeldung cp: cannot stat 'git diff --name-only': No such file or directorybei Git Bash unter Windows. Was mache ich falsch? Zielverzeichnis existiert
Shiva
14

Folgendes sollte gut funktionieren:

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

Um es weiter zu erklären:

  • Mit -zto können Sie git diff --name-onlydie Liste der Dateien ausgeben, die durch NUL-Bytes anstelle von Zeilenumbrüchen getrennt sind, nur für den Fall, dass Ihre Dateinamen ungewöhnliche Zeichen enthalten.

  • Das -0to xargssagt, dass die Standardeingabe als NUL-getrennte Liste von Parametern interpretiert werden soll.

  • Das -IREPLACEist notwendig , da standardmäßig xargsdie Parameter an das Ende des hängen würde rsyncBefehls. Stattdessen heißt das, sie dorthin zu bringen, wo sie später REPLACEsind. (Das ist ein guter Tipp aus dieser Serverfehler-Antwort .)

  • Der -aParameter to rsyncbedeutet, Berechtigungen, Besitz usw. nach Möglichkeit beizubehalten. Die -RMöglichkeit, beim Erstellen der Dateien im Ziel den vollständigen relativen Pfad zu verwenden.

Update: Wenn Sie eine alte Version von haben xargs, müssen Sie die -iOption anstelle von verwenden -I. (Ersteres wird in späteren Versionen von veraltet findutils.)

Mark Longair
quelle
Das ist seltsam - welches Betriebssystem verwenden Sie? Wenn es sich um eine Linux-Distribution handelt, welche und was xargs --versionsagt das aus?
Mark Longair
1
Ah, in dieser Version von xargs müssen Sie -istattdessen verwenden, was in späteren Versionen veraltet ist - 4.1 ist jetzt ziemlich alt. Ich werde meine Antwort aktualisieren.
Mark Longair
@Mark: Ich erinnere mich, dass ich irgendwo gelesen habe, dass Sie -Iin einigen Versionen ein Leerzeichen benötigen , also versuchen Sie es vielleicht -I REPLACEstattdessen.
Mikel
Keine Ursache. Das funktioniert auch nicht. -Iwird erst seit findutils4.2.10 unterstützt, veröffentlicht im Dezember 2004.
Mikel
Sie sollten hinzufügen --diff-filter=d, um gelöschte Dateien von der Liste auszuschließen. Andernfalls werden beim Versuch, sie in den Änderungsordner zu kopieren, Fehler angezeigt. Ansonsten tolle Antwort. Vielen Dank!
taymless
11

Hier ist ein Einzeiler:

Liste geänderter Dateien auf und packe sie als * .zip:

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

Listet die zuletzt festgeschriebenen geänderten Dateien auf und packt sie als * .zip:

git diff --name-only HEAD~ HEAD | zip patched.zip -@
kolypto
quelle
Wenn Sie Windows verwenden, können Sie die Befehlszeilen-Zip-
Datei
@ Radon8472 Das installiert sed.exe? Ich werde immer noch zipnicht unter Windows gefunden.
Shiva
nein, der link verweist auf den download für zip.exe nicht für sed. Wenn Sie zip in der Befehlszeile nicht verwenden können, sollten Sie den Ordner, in dem die Datei zip.exe installiert ist, zu Ihrer PATHenv-Variablen hinzufügen .
Radon8472
6
zip update.zip $(git diff --name-only commit commit)
Kennzeichen
quelle
2

Es funktioniert perfekt.

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

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

Niemand hat erwähnt, cpiowas einfach zu tippen ist, harte Links erstellt und Leerzeichen in Dateinamen behandelt:

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