Saya memiliki dua repositori. Dalam satu, saya membuat perubahan ke file ./hello.test
. Saya melakukan perubahan dan membuat tambalan dari komit itu dengan git format-patch -1 HEAD
. Sekarang, saya memiliki repositori kedua yang berisi file yang memiliki isi yang sama seperti hello.test tapi ditempatkan dalam direktori yang berbeda dengan nama yang berbeda: ./blue/red/hi.test
. Bagaimana cara saya menerapkan tambalan yang disebutkan di atas ke hi.test
file? Saya mencoba git am --directory='blue/red' < patch_file
tetapi tentu saja mengeluh bahwa file tersebut tidak bernama sama (yang menurut saya Git tidak peduli?). Saya tahu saya mungkin bisa mengedit diff untuk diterapkan ke file tertentu itu tetapi saya sedang mencari solusi perintah.
101
Jawaban:
Anda dapat membuat tambalan menggunakan
git diff
dan kemudian menerapkannya menggunakanpatch
utilitas, yang memungkinkan Anda menentukan file yang ingin Anda terapkan diff.Sebagai contoh:
sumber
am
atauapply
, tetapi saya tidak dapat menemukannya. Jika Anda sering menduplikasi perubahan, mungkin ada solusi yang lebih baik menggunakan submodul, atau apa pun bahasa pilihan Anda yang disediakan untuk berbagi kode (misalnya di Ruby Anda dapat mengekstrak kode duplikat sebagai permata).Ada solusi sederhana yang tidak melibatkan pengeditan tambalan manual atau skrip eksternal.
Di repositori pertama (ini juga dapat mengekspor berbagai komit, gunakan
-1
jika Anda ingin memilih hanya satu komit):Di repositori kedua:
Alih-alih menggunakan
--relative
ingit format-patch
, solusi lain adalah menggunakan-p<n>
opsi ingit am
untuk menghapusn
direktori dari jalur tambalan, seperti yang disebutkan dalam jawaban untuk pertanyaan serupa .Dimungkinkan juga untuk dijalankan
git format-patch --relative <committish>
tanpa--stdout
, dan itu akan menghasilkan sekumpulan.patch
file. File-file ini kemudian dapat diumpankan langsung kegit am
withgit am --directory blue/red/ path/to/*.patch
.sumber
--directory
opsi tersebut tampaknya meminta Anda untuk menentukan path lengkap dari direktori relatif terhadap root repo; sesuatu seperti--directory=./
sementara chdir ke subdirektori di repo tidak akan berfungsi.--3way
bantuan dengandoes not exist in index
:git am --3way --directory (relative-path) (patch)
-k
kunci di kedua perintah untuk tidak menghapus baris pertama dari pesan komit.--3way
tidak hanya membantu dengan kesalahan "tidak ada dalam indeks" (seperti yang ditunjukkan oleh @nobar), tetapi juga memungkinkan Anda menangani konflik penggabungan dengan rapi. Alih-alih membiarkan file konflik tidak tersentuh, blok konflik ditambahkan yang kemudian dapat diselesaikan.Menjawab pertanyaan saya sendiri dengan skrip yang hanya melakukan ini: https://github.com/mprpic/apply-patch-to-file
Daripada memodifikasi file patch secara manual, ia meminta pengguna untuk file target, memodifikasi patch, dan menerapkannya ke repo tempat Anda saat ini berada.
sumber
Dibangun berdasarkan jawaban oleh @georgebrock, inilah solusi yang saya gunakan:
Pertama, buat file patch seperti biasa (mis.
git format-patch commitA..commitB
).Kemudian pastikan bahwa repositori target Anda bersih (seharusnya tidak ada file yang diubah atau tidak terlacak) dan terapkan patch seperti ini:
Untuk setiap file patch Anda akan mendapatkan error seperti "error: XYZ tidak ada di indeks". Anda sekarang dapat menerapkan file tambalan ini secara manual:
Anda harus melakukan tiga langkah ini untuk setiap file patch.
Ini akan mempertahankan pesan komit asli dll. Tanpa memerlukan
git format-patch
perintah khusus atau mengedit file tambalan.sumber
git format-patch -1 commitA --stdout > thing.diff
; (2) Edit file patch hingga melakukan apa yang saya butuhkan; (3) Teks untuk komitgit am --3way thing.diff
yang memiliki keuntungan bahwa Anda dapat menerima bagian dari tambalan yang diterapkan dengan bersih, dan menggunakangit
proses resolusi konflik standar untuk bagian yang tidak.Saya memahami bahwa kedua file tersebut persis sama dalam situasi Anda, sehingga patch kemungkinan besar akan berhasil.
Namun, jika Anda ingin menerapkan tambalan ke file yang serupa, tetapi tidak persis sama, atau Anda ingin melakukan tambalan interaktif, Anda akan menggunakan penggabungan tiga cara.
Katakanlah Anda memodifikasi File
A
, mari tunjukkanA~1
sebagai versi sebelumnya, dan Anda ingin menerapkan perbedaan antaraA~1
keA
ke FileB
.Buka alat penggabung tiga arah, misalnya Beyond Compare, jalur panel kiri adalah
A
, panel tengah adalah leluhur yang sama sehingga jalurnya adalahA~1
, jalur panel kanan adalahB
. Kemudian, lebih rendah menunjukkan panel hasil dari penerapan diff antaraA~1
untukA
ke fileB
.Gambar berikut mengilustrasikan ide tersebut.
sumber
FYI: Baru-baru ini saya mengalami masalah saat mencoba mendownload patch dari Github dan menerapkannya ke file lokal (yang merupakan "override" di lokasi baru).
git am
tidak akan menerapkan tambalan karena file itu "tidak ada dalam indeks" atau "kotor". Tapi, saya menemukan bahwapatch
perintah sederhana dapat menerapkan tambalan. Itu meminta saya untuk nama file yang akan ditambal.Tetap menyelesaikan pekerjaan ...
sumber