Bisakah saya mendapatkan output yang kompatibel dengan patch dari git-diff?

160

Saya melakukan kesalahan yang sangat sederhana. Saya mencoba menyiapkan file tambalan biasa, jadi saya bisa mengajukan kembali beberapa perubahan:

$ git diff > before
$ git diff something_here > save.patch
$ git checkout . 
$ patch < save.patch
$ git diff > after
$ diff before after
$

Dengan something_here blank hampir berfungsi, tetapi nama file tidak benar. Saya pikir saya hanya saya kehilangan beberapa opsi.

Dalam kehidupan nyata, saya akan melakukan penggabungan setelah checkout, sehingga patch mungkin gagal di sana, tetapi Anda lihat apa yang saya maksudkan.

Sunting Kesalahan saya di sini karena mengajukan pertanyaan yang salah. Pertanyaan sebenarnya adalah, saya ingin menyimpan perubahan saya, melakukan penggabungan, lalu menerapkan kembali perubahan, jika memungkinkan? Saya bertanya dengan cara yang salah karena saya terbiasa menggunakan tambalan untuk menyelesaikan masalah-masalah git diffseperti ini dan sepertinya itulah yang ingin saya lakukan.

Komentar Charles Bailey memiliki jawaban yang tepat. Bagi saya, git-apply adalah hal yang benar untuk dilakukan (git-simpanan terlihat lebih berat daripada yang saya butuhkan dan rebasing dan bundel jelas di luar tingkat keahlian saya saat ini.) Saya akan menerima jawaban yang diberikan Charles (karena Anda tidak dapat menerima komentar). Terima kasih atas semua sarannya.

Sunting, 6 tahun kemudian Seperti diketahui orang yang tahu subjeknya, saya terlalu memperkirakan kesulitannya git stash. Hampir setiap hari, saya akan menggunakan urutan berikut:

$ git stash
$ git merge
$ git stash pop
Malvolio
sumber
8
Apakah ada alasan khusus yang ingin Anda gunakan patchalih-alih git apply?
CB Bailey
3
Dan bahkan kemudian, apakah Anda benar-benar membutuhkan tambalan daripada sesuatu seperti git stashatau alat git lainnya?
CB Bailey
3
Setelah diedit, saya pikir itu git stashadalah solusi termudah untuk apa yang Anda coba lakukan, tetapi ada banyak pendekatan yang berhasil.
CB Bailey
1
@Malvolio: Memang benar, Anda bahkan tidak perlu memikirkan nama file sementara untuk menyimpan tambalan Anda.
CB Bailey
4
@Charlse, terkadang Anda perlu mengirim tambalan kepada seseorang tanpa seluruh repositori git. Misalnya jika menggunakan git-svn.
Elazar Leibovich

Jawaban:

139

Jika Anda ingin menggunakan tambalan Anda harus menghapus a/ b/awalan yang git gunakan secara default. Anda dapat melakukan ini dengan --no-prefixopsi (Anda juga dapat melakukan ini dengan -popsi tambalan ):

git diff --no-prefix [<other git-diff arguments>]

Namun biasanya, lebih mudah untuk menggunakan lurus git diffdan kemudian menggunakan output untuk memberi makan git apply.

Sebagian besar waktu saya mencoba untuk menghindari menggunakan tambalan teks. Biasanya satu atau lebih komit sementara digabungkan dengan rebase, git stashdan bundel lebih mudah dikelola.

Untuk kasus penggunaan Anda, saya pikir itu stashyang paling tepat.

# save uncommitted changes
git stash

# do a merge or some other operation
git merge some-branch

# re-apply changes, removing stash if successful
# (you may be asked to resolve conflicts).
git stash pop
CB Bailey
sumber
7
git diff --no-prefix master > diff.patchdan kemudiangit checkout master patch -p0 < diff.patch
Natim
1
@ Natim Untuk keamanan tertinggi saya akan merekomendasikan menggunakan patch --dry-run < diff.patchsebelum mengeluarkan perintah terakhir.
ᴠɪɴᴄᴇɴᴛ
1
@ ᴠɪɴᴄᴇɴᴛ apa manfaat melakukan itu? Karena kita menggunakan git, kita tidak mungkin kehilangan apa pun, bukan?
Natim
1
@ Natim Seperti yang saya katakan, hanya untuk keamanan tertinggi, tidak perlu membatalkan apa pun jika terjadi kesalahan. Saya juga memikirkan orang-orang yang membaca ini dan ingin menggunakan di patchluar git (mungkin menggunakan file tambalan yang dihasilkan oleh diff) dalam kasus penggunaan yang lebih umum.
ᴠɪɴᴄᴇɴᴛ
Untuk memasukkan file baru ke dalam tambalan Anda, Anda juga harus memasukkan "git diff --no-prefix --cached" di tambalan. Mungkin ada cara yang lebih baik?
jamshid
219

Penggunaan hanya -p1: Anda akan perlu menggunakan -p0dalam --no-prefixkasus pula, sehingga Anda hanya dapat meninggalkan keluar --no-prefixdan menggunakan -p1:

$ git diff > save.patch
$ patch -p1 < save.patch

$ git diff --no-prefix > save.patch
$ patch -p0 < save.patch
ndim
sumber
1
Jika Anda bertanya-tanya mengapa, pria itu merangkumnya dengan baik - sumber .
tutuDajuju
3
Ini tidak akan berfungsi dengan penggantian nama; git diffmenampilkan garis yang patchmengabaikan. git applyadalah cara untuk pergi.
hraban
17

Diff git memiliki segmen path ekstra yang ditambahkan ke path file. Anda dapat menghapus entri ini di jalur dengan menentukan -p1 dengan tambalan, seperti:

patch -p1 < save.patch
Henrik Gustafsson
sumber
10
  1. Saya menyimpan diff direktori saat ini (termasuk file yang tidak berkomitmen) terhadap HEAD saat ini.
  2. Kemudian Anda dapat memindahkan save.patchfile ke mana saja (termasuk file biner).
  3. Pada mesin target Anda, terapkan tambalan menggunakan git apply <file>

Catatan: berbeda dengan file yang saat ini dipentaskan juga.

$ git diff --binary --staged HEAD > save.patch
$ git reset --hard
$ <transport it>
$ git apply save.patch
Matej
sumber
Ha ha ha. Itu lucu. Saya mengajukan pertanyaan ini hampir empat tahun yang lalu dan cara saya melakukan ini telah berkembang tetapi jika Anda bertanya kepada saya kemarin bagaimana melakukannya, saya akan memberikan jawaban Anda dan mengatakan saya mendapatkannya dari jawaban untuk pertanyaan ini. (Sebenarnya saya mungkin akan menggunakan yang telanjang git diff > save.patchdan git checkout .bukan reset, tapi ya ...
Malvolio
Oh tidak memperhatikan umurnya 4 tahun: P. Btw, setel ulang hanya untuk mendemonstrasikannya berfungsi .. Saya juga tidak melihat siapa pun menggunakan git applyatau menjadikan diff relevan dengan keadaan Anda dan penunjuk ke komit terakhir tersedia. Melakukannya sama sekali git difftidak melakukan apa pun
Matej
Ya, sekarang saya bertanya-tanya bagaimana saya bisa tahu git apply. Masalahnya git diffadalah (saya pikir) dari menggunakan git reset- hubungan antara repo, indeks, dan area kerja adalah masalah.
Malvolio
8

Trik yang berguna untuk menghindari membuat file tambalan sementara:

git diff | patch -p1 -d [dst-dir]
mulai lambat
sumber
Apa yang saya inginkan. Juga berfungsi sempurna dengan simpanan! git stash show -p stash@{3} | patch -p1 -d [dst-dir]
dtmland