Git diff --name-only dan salin daftar itu

151

Saya hanya ingin mendapatkan daftar file yang diubah di antara dua revisi, yang sederhana:

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

Tapi, apa yang harus saya tulis, jika saya ingin menyalin semua file yang terdaftar ke tempat lain? Dan saya perlu struktur direktori yang sama sekali identik untuk file yang disalin.

Misalnya, saya telah memodifikasi dan menambahkan file:

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

Saya ingin memiliki /home/changes/semua file yang diubah dan ditambahkan:

/home/changes/protected/texts/file1.txt
/home/changes/protected/scripts/index.php
/home/changes/public/pics/pic1.png
BazZy
sumber
1
saya tidak begitu mengerti apa yang ingin Anda capai ... menyebarkan perubahan ke klon yang berbeda? membuat tambalan? menambal file di luar repositori git?
knittl
Bukan tambalan, tetapi struktur salin yang tepat dari file yang diubah. Suka tambalan, tetapi dengan file padat
BazZy
Dan ya, menambal file di luar repositori git - target terdekat bagi saya :)
BazZy
3
Maaf. APA? Anda ingin menangkap dan memutar ulang perubahan ke file dan perubahan ke pohon? itu tambalan. git format-patchdapat melakukan ini untuk rentang komit.
knittl
1
git diff commit1 commit2 > my.patchdan kemudian cd other/path; patch -p1 < my.patch. Mengapa harus dilakukan dengan salinan lengkap file? Jika itu karena Anda berpikir tambalan itu mungkin tidak berlaku, dan karena itu direktori lain tidak benar-benar dalam commit1keadaan, Anda benar-benar harus menyalin segala sesuatu dari commit2negara ...
Cascabel

Jawaban:

118

Coba perintah berikut, yang telah saya uji:

$ cp -pv --parents $(git diff --name-only) DESTINATION-DIRECTORY
York
sumber
2
Terima kasih atas cp --parentspetunjuknya, saya ingin opsi itu selama bertahun-tahun dan tidak pernah tahu itu ada! .. jelas saya tidak pernah repot untuk mencarinya juga = \
Stephan Henningsen
2
Perhatikan bahwa ini tidak berfungsi pada Mac, karena --parentsopsi cptidak tersedia.
M. Justin
Adakah kiat menggunakan ini jika file memiliki karakter yang tidak biasa? Spasi, karakter nordis.
Halvor Holsten Strand
@ FalconStrand, saya belum mengujinya, tetapi pengaturan IFS=$'\n'pertama mungkin melakukannya. (Lebih disukai dalam subkulit agar tidak mengacaukan nilai IFS asli Anda.)
Wildcard
Saya mendapatkan kesalahan cp: cannot stat 'git diff --name-only': No such file or directorypada git bash di windows. Apa yang saya lakukan salah? Direktori tujuan ada
Shiva
14

Berikut ini akan berfungsi dengan baik:

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

Untuk menjelaskan lebih lanjut:

  • The -zdengan dengan git diff --name-onlyberarti menampilkan daftar file yang dipisahkan dengan byte NUL, bukan baris baru, kalau-kalau nama file Anda memiliki karakter yang tidak biasa di dalamnya.

  • Kata -0to xargsuntuk menafsirkan input standar sebagai daftar parameter yang dipisahkan oleh NUL.

  • The -IREPLACEdiperlukan karena secara default xargsakan menambahkan parameter ke akhir rsyncperintah. Sebaliknya, itu mengatakan untuk menempatkan mereka di mana nanti REPLACE. (Itu tip yang bagus dari jawaban Server Fault ini .)

  • The -aparameter untuk rsyncsarana untuk melestarikan perizinan, kepemilikan, dll jika mungkin. Cara -Runtuk menggunakan jalur relatif penuh saat membuat file di tujuan.

Perbarui: jika Anda memiliki versi lama xargs, Anda harus menggunakan -iopsi sebagai ganti -I. (Yang pertama ditinggalkan dalam versi selanjutnya dari findutils.)

Mark Longair
sumber
Aneh - sistem operasi apa yang Anda gunakan? Jika itu adalah distribusi Linux, yang mana, dan apa artinya xargs --version?
Mark Longair
1
Ah, dalam versi xargs yang perlu Anda gunakan -i, yang sudah usang di versi kemudian - 4.1 sudah cukup lama sekarang. Saya akan memperbarui jawaban saya.
Mark Longair
@ Mark: Saya ingat pernah membaca di suatu tempat bahwa Anda memerlukan ruang setelah -Ibeberapa versi, jadi mungkin cobalah -I REPLACE.
Mikel
Lupakan. Itu juga tidak berhasil. -Ihanya didukung sejak findutils4.2.10, dirilis Desember 2004.
Mikel
Anda harus menambahkan --diff-filter=duntuk mengecualikan file yang dihapus dari daftar. Kalau tidak, Anda akan mendapatkan kesalahan saat mencoba menyalinnya ke folder perubahan. Kalau tidak jawaban yang bagus. Terima kasih!
taymless
11

Inilah satu kalimat:

Daftar file yang diubah & kemas sebagai * .zip:

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

Daftarkan file yang diubah terakhir berkomitmen & kemas sebagai * .zip:

git diff --name-only HEAD~ HEAD | zip patched.zip -@
kolypto
sumber
Jika Anda menggunakan windows, Anda dapat mengunduh zip commandline dari sourceforge.net/projects/gnuwin32/files/zip
Radon8472
@ Radon8472 Itu menginstal sed.exe? Saya masih zipbelum ditemukan di windows.
Shiva
tidak, tautannya menunjuk ke unduhan untuk zip.exe bukan untuk sed. Jika Anda tidak dapat menggunakan zip di commandline, Anda harus menambahkan folder tempat zip.exe diinstal ke PATHvariabel env Anda .
Radon8472
6
zip update.zip $(git diff --name-only commit commit)
Menandai
sumber
2

Ini bekerja dengan sempurna.

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

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

Tidak ada cpioyang menyebutkan yang mudah diketik, membuat tautan keras, dan menangani spasi dalam nama file:

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