Bagaimana cara menghasilkan git patch untuk komit tertentu?

1233

Saya perlu menulis skrip yang membuat tambalan untuk daftar nomor komit SHA1.

Saya mencoba menggunakan git format-patch <the SHA1>, tetapi itu menghasilkan patch untuk setiap komit sejak SHA1 itu. Setelah beberapa ratus tambalan dibuat, saya harus mematikan prosesnya.

Apakah ada cara untuk menghasilkan tambalan hanya untuk SHA1 spesifik?

Elle
sumber

Jawaban:

1991

Mencoba:

git format-patch -1 <sha>

atau

git format-patch -1 HEAD

Menurut tautan dokumentasi di atas, -1bendera memberi tahu git berapa banyak komit yang harus dimasukkan dalam tambalan;

- <n>

     Siapkan tambalan dari komitmen paling atas.


Terapkan tambalan dengan perintah:

git am < file.patch
manojlds
sumber
211
Menerapkan tambalan: git apply --stat file.patch# tampilkan statistik. git apply --check file.patch# periksa kesalahan sebelum mendaftar. git am < file.patchakhirnya terapkan tambalan.
Adrian
3
Tampaknya tidak berfungsi jika komit terakhir merupakan penggabungan dari cabang lain.
Lex Li
2
Untuk menerapkan tambalan pada file menggunakan ujung garis CRLF:git am --keep-cr < mypatch.patch
Michael Schmeißer
40
Gunakan git am -3 < file.patchuntuk menerapkan menggunakan gabungan tiga arah yang akan memungkinkan Anda menyelesaikan konflik menggunakan git mergetoolsesudahnya (atau mengedit secara manual) ditemukan di sini .
Mat
6
Perintah ini juga berfungsi hanya untuk file tertentu dari komit: git format-patch -1 <sha> path/to/file.jsIni akan membuat tambalan hanya berisi diffs untuk file.js
Dombi
281

Untuk menghasilkan tambalan dari komit paling atas dari hash sha1 tertentu:

git format-patch -<n> <SHA1>

10 tambalan terakhir dari kepala dalam satu file tambalan:

git format-patch -10 HEAD --stdout > 0001-last-10-commits.patch
Sriram Murali
sumber
2
bisakah Anda berbaik hati untuk memberikan contoh untuk perintah pertama
Kasun Siyambalapitiya
1
git format-patch -1 HEADakan menghasilkan tambalan untuk komit terbaru
Sriram Murali
1
maafkan saya untuk menanyakan hal ini, jadi ketika itu -2menghasilkan tambalan untuk 2 komitmen terakhir adalah itu, dan satu hal lagi untuk klarifikasi adalah perintahnya got format-patch -2 HEADsama dengan garisgit format-patch HEAD~2
Kasun Siyambalapitiya
85

Katakanlah Anda memiliki komit 2 setelah komit 1, Anda dapat menjalankan:

git diff 2 1 > mypatch.diff

di mana 2 dan 1 adalah hash SHA.

brandon
sumber
Terima kasih dookehster atas balasannya. Itu berarti saya perlu skrip untuk menemukan komit yang mendahului orang-orang yang saya minati. Saya berharap bisa menghindarinya.
Elle
11
@elle, tidak, kamu tidak - git diff hash^ hash. "hash ^" memberikan komit sebelumnya. (tapi, tentu saja, jawaban manojlds lebih baik)
J-16 SDiZ
2
git show HEAD > mypatch.diffketika Anda sedang menjalankan komit, Anda harus melakukan hal yang sama.
andho
1
@dookehester apakah itu benar atau sebaliknya,git diff 1 2
Kasun Siyambalapitiya
1
Ini akan gagal untuk memasukkan file biner dalam diff.
stuckj
55

Perintah ini (seperti yang sudah disarankan oleh @ Naftuli Tzvi Kay ):

git format-patch -1 HEAD

Ganti HEADdengan hash atau rentang tertentu.

akan menghasilkan file tambalan untuk komit terbaru yang diformat menyerupai format kotak surat UNIX.

-<n> - Siapkan tambalan dari komitmen paling atas.

Kemudian Anda dapat menerapkan kembali file tambalan dalam format kotak surat dengan:

git am -3k 001*.patch

Lihat: man git-format-patch.

kenorb
sumber
Terima kasih! Saya pikir perlu dicatat bahwa menerapkan tambalan akan membuat komit dengan pesan komit yang diawali oleh [PATCH]. Itu mudah diperbaiki
Mike S
2
Fenomenal. OP, Anda belum menerima ini, karena ...? @ Mike Tidak, tidak lagi gitseperti patch berformat lainnya , setidaknya jika pengguna menerapkannya dengan cara yang benar.
underscore_d
2
@ Mike Saya tidak benar-benar menyelidiki alasannya, tetapi meninggalkan -kbendera ( git am -3) memperbaiki formulir ini saya (tidak ada PATCH[0/10]pesan komit). Git versi 2.20.1.windows.1
jannis
31
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

Solusi cepat dan sederhana.

zdrsoft
sumber
5
Juga jangan lupa menelepon git apply --check patch-file-namesebelum menerapkan tambalan. Ini akan membantu menghindari masalah.
iamantony
16

Jika Anda ingin memastikan tambalan (komit tunggal) akan diterapkan di atas komit tertentu, Anda dapat menggunakan opsi git 2.9 (Juni 2016) yang baru git format-patch --base

git format-patch --base=COMMIT_VALUE~ -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git format-patch --base=auto -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git config format.useAutoBase true
git format-patch -M -C COMMIT_VALUE~..COMMIT_VALUE

Lihat komit bb52995 , komit 3de6651 , komit fa2ab86 , komit ded2c09 (26 Apr 2016) oleh Xiaolong Ye (``) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam commit 72ce3ff , 23 Mei 2016)

format-patch: tambahkan --baseopsi ' ' untuk merekam info struktur dasar

Maintainers atau penguji pihak ketiga mungkin ingin tahu pohon dasar yang tepat dari seri tambalan berlaku. Ajarkan git format-patch a ' --base' opsi untuk merekam info pohon dasar dan menambahkannya di akhir pesan pertama (baik surat pengantar atau patch pertama dalam seri).

Info pangkalan pohon terdiri dari "komit dasar", yang merupakan komit terkenal yang merupakan bagian dari bagian stabil dari sejarah proyek yang digunakan semua orang, dan nol atau lebih "patch prasyarat", yang terkenal tambalan dalam penerbangan yang belum menjadi bagian dari "komit dasar" yang perlu diterapkan di atas "komit dasar" dalam urutan topologi sebelum patch dapat diterapkan.

"Komit dasar" ditampilkan sebagai " base-commit:" diikuti oleh 40-hex dari nama objek komit.
"Tambalan prasyarat" ditampilkan sebagai " prerequisite-patch-id:" diikuti oleh "tambalan patch" hex-hex, yang dapat diperoleh dengan melewati tambalan melalui perintah " git patch-id --stable".


Git 2.23 (Q3 2019) akan meningkatkan itu, karena " --base" opsi " format-patch" menghitung patch-idstambalan untuk prasyarat dengan cara yang tidak stabil, yang telah diperbarui untuk menghitung dengan cara yang kompatibel dengan " git patch-id --stable".

Lihat komit a8f6855 , komit 6f93d26 (26 Apr 2019) oleh Stephen Boyd ( akshayka) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit 8202d12 , 13 Jun 2019)

format-patch: membuat --base patch-idoutput stabil

Kami tidak menyiram konteks setiap kali kami memproses hunk dalam patch-idkode generasi diff.c, tetapi kami melakukan itu ketika kami membuat patch-id yang "stabil" dengan alat ' patch-id'.

Pelabuhan Mari bahwa logika yang sama lebih dari patch-id.cke diff.csehingga kita bisa mendapatkan hash yang sama ketika kita menghasilkan patch-id untuk ' format-patch --base=' jenis doa perintah.


Sebelum Git 2.24 (Q4 2019), " git format-patch -o <outdir>" melakukan yang setara dengan " mkdir <outdir>" tidak " mkdir -p <outdir>", yang sedang diperbaiki.

Lihat komit edefc31 (11 Okt 2019) oleh Bert Wesarg ( bertwesarg) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit f1afbb0 , 18 Okt 2019)

format-patch: membuat komponen utama direktori keluaran

Ditandatangani oleh: Bert Wesarg

'git format-patch -o' melakukan yang setara dengan 'mkdir' bukan 'mkdir -p', yang sedang diperbaiki.

Hindari penggunaan ' adjust_shared_perm' pada direktori terkemuka yang mungkin memiliki implikasi keamanan. Dicapai dengan menonaktifkan sementara ' config.sharedRepository' seperti ' git init' tidak.


Dengan Git 2.25 (Q1 2020), " git rebase" tidak berfungsi dengan baik ketika format.useAutoBasevariabel konfigurasi diatur, yang telah diperbaiki.

Lihat komit cae0bc0 , komit 945dc55 , komit 700e006 , komit a749d01 , komit 0c47e06 (04 Des 2019) oleh Denton Liu ( Denton-L) .
(Digabung oleh Junio ​​C Hamano - gitster- dalam komit 71a7de7 , 16 Des 2019)

rebase: memperbaiki format.useAutoBasekerusakan

Dilaporkan oleh: Christian Biesinger
Ditandatangani oleh: Denton Liu

Dengan format.useAutoBase = true, menjalankan rebase menghasilkan kesalahan:

fatal: failed to get upstream, if you want to record base commit automatically,
please use git branch --set-upstream-to to track a remote branch.
Or you could specify base commit by --base=<base-commit-id> manually
error:
git encountered an error while preparing the patches to replay
these revisions:

ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12

As a result, git cannot rebase them.

Perbaiki ini dengan selalu meneruskan --no-baseke format-patch dari rebase sehingga efek format.useAutoBasedinegasikan.

VONC
sumber
8

Untuk menghasilkan jalur dari komit tertentu (bukan komit terakhir):

git format-patch -M -C COMMIT_VALUE~1..COMMIT_VALUE
Makah
sumber
5

jika Anda hanya ingin diff file yang ditentukan, Anda dapat:

git diff master 766eceb - koneksi /> 000-mysql-connector.patch

jiahut
sumber
0

Dengan latar belakang lincah saya, saya akan menggunakan:

git log --patch -1 $ID > $file

Tetapi saya sedang mempertimbangkan untuk menggunakan git format-patch -1 $IDsekarang.

alls0rts
sumber
-5

Apa cara menghasilkan tambalan hanya untuk SHA1 spesifik?

Sederhana saja:

Pilihan 1. git show commitID > myFile.patch

Pilihan 2. git commitID~1..commitID > myFile.patch

Catatan: Ganti commitIDdengan id komit aktual (kode komit SHA1).

Ankush
sumber
3
Opsi 1 benar-benar salah dan tidak terkait dengan pertanyaan.
Anshuman Manral
3
Opsi 2 juga merupakan perintah yang tidak valid. Anda akan mendapatkan kesalahan seperti: git a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 ~ 1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 git: 'a5f4bcaeb7fa7de7b7fb7foufbfoufbbnfnfbbnfmnfmbnfmnfmnfmnfmnfmnfpnfmnpnfpnpnpnpnpnpnpnpnpnpnpnpfpfpfpfpfcf Lihat 'git --help'. Mohon periksa sebelum mengirim jawaban
Anshuman Manral