Git diff - salt ad ve listeyi kopyala


151

Sadece iki düzeltme arasında değişen dosyaların bir listesini almak istiyorum, bu basit:

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

Ancak, listelenen tüm dosyaları başka bir yere kopyalamak istersem ne yazmalıyım? Ve kopyalanan dosyalar için tamamen aynı dizin yapısına ihtiyacım var.

Örneğin, dosyaları değiştirdim ve ekledim:

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

Ben olmasını istediğiniz /home/changes/tüm bu değişti ve eklenen dosyalar:

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

1
Neyi başarmaya çalıştığınızı tam olarak anlamıyorum… değişiklikleri farklı klonlara yayarak? yamalar oluşturuluyor mu? bir git deposu dışındaki dosyalar yama?
knittl

Düzeltme eki değil, değiştirilen dosyaların tam kopya yapısı. Yama gibi, ancak katı dosyalarla
BazZy

Ve evet, git deposu dışındaki dosyaları düzeltme eki - benim için en yakın hedef :)
BazZy

3
afedersiniz. NE? dosya ve ağaç değişikliklerini yakalamak ve yeniden oynatmak mı istiyorsunuz? bu bir yama. git format-patchbunu taahhüt aralıkları için yapabilir.
knittl

1
git diff commit1 commit2 > my.patchve sonra cd other/path; patch -p1 < my.patch. Neden dosyaların tam kopyalarıyla yapılması gerekiyor? Eğer yama geçerli olmayabilir düşünüyorum ve bu nedenle diğer dizin gerçekten değil çünkü öyle olursa commit1devlet, gerçekten kopyalamak gerektiğini şeyi dan commit2... devlet
Cascabel

Yanıtlar:


118

Test ettiğim şu komutu deneyin:

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

2
cp --parentsİpucu için teşekkürler , bu seçeneği yıllarca istedim ve var olduğunu asla bilmiyordum! Açıkçası ben de aramak için hiç rahatsız etmedim = \
Stephan Henningsen

2
--parentsSeçeneği cpmevcut olmadığından , bunun Mac'te çalışmadığını unutmayın .
M. Justin

Dosyaların olağandışı karakterleri varsa bunu kullanmayla ilgili ipucu var mı? Boşluk, nordic karakterler.
Halvor Holsten Strand

@HalvorStrand, test etmedim, ama IFS=$'\n'ilk olarak ayarlayabilir . (Tercihen orijinal IFS değerinizi bozmamak için bir alt kabukta.)
Wildcard

cp: cannot stat 'git diff --name-only': No such file or directoryWindows'ta git bash üzerinde bir hata alıyorum . Neyi yanlış yapıyorum? Hedef dizini var
Shiva

14

Aşağıdakiler iyi çalışmalıdır:

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

Daha fazla açıklamak için:

  • -zİle karşı git diff --name-onlyNUL ile ayrılmış dosyaların çıkışına vasıtası listesi dosya adları onlara sıradışı karakterler ihtimale karşı yerine satırsonlarının ait bayt.

  • -0İçin xargsparametrelerin bir boş ayrılmış liste olarak standart girdi yorumlamak söylüyor.

  • -IREPLACEVarsayılan olarak beri gereklidir xargssonuna parametreler ekleyecektir rsynckomuta. Bunun yerine, onları daha sonra REPLACEolduğu yere koymak diyor . (Bu Sunucu Hatası yanıtından güzel bir ipucu .)

  • -aParametre rsyncaracı izinleri, mülkiyeti vb mümkünse korumak için. -RHedef dosya oluştururken araçlar tam göreli yolu kullanmak.

Güncelleme: eski bir sürümüne xargssahipseniz, -ibunun yerine seçeneği kullanmanız gerekir -I. (İlki, sonraki sürümlerinde kullanımdan kaldırılmıştır findutils.)


Bu garip - hangi işletim sistemini kullanıyorsunuz? Bu bir Linux dağıtımı ise hangisi ve ne xargs --versiondiyor?
Mark Longair

1
Ah, bu xargs sürümünde kullanmanız gerekiyor, -ibunun yerine sonraki sürümlerde kullanımdan kaldırılıyor - 4.1 şimdi oldukça eski. Cevabımı güncelleyeceğim.
Mark Longair

@Mark: -IBazı versiyonlarda boşluğa ihtiyaç duyduğunuz bir yerde okuduğumu hatırlıyorum , -I REPLACEbunun yerine belki deneyin .
Mikel

Boşver. Bu da işe yaramıyor. -Iyalnızca findutilsAralık 2004'te yayınlanan 4.2.10'dan beri desteklenmektedir .
Mikel

--diff-filter=dSilinen dosyaları listeden hariç tutmak için eklemeniz gerekir . Aksi takdirde, bunları değişiklikler klasörüne kopyalamaya çalışırken hatalarla karşılaşırsınız. Aksi takdirde harika bir cevap. Teşekkürler!
taymless

11

İşte bir astar:

Değiştirilen dosyaları listeleyin ve * .zip olarak paketleyin:

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

Son kaydedilen değiştirilmiş dosyaları listeleyin ve * .zip olarak paketleyin:

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

Windows kullanıyorsanız komut satırı zip dosyasını sourceforge.net/projects/gnuwin32/files/zip adresinden indirebilirsiniz
Radon8472

@ Radon8472 Yükleniyor sed.exemu? Hala zippencerelerde bulunamıyorum.
Shiva

Hayır, bağlantı sed için değil zip.exe için indirme işaret ediyor. Komut satırında zip kullanamıyorsanız, zip.exe dosyasının kurulu olduğu klasörü PATHenv değişkeninize eklemelisiniz .
Radon8472

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


2

Mükemmel çalışıyor.

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

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

1

cpioKolay yazılan, sabit bağlantılar oluşturan ve dosya adlarındaki boşlukları işleyen hiç kimse bahsetmedi :

git diff --name-only $from..$to  | cpio -pld outdir
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.