Bagaimana Anda menekan squash menjadi satu tambalan dengan git format-tambalan?

163

Saya punya delapan komitmen di cabang yang ingin saya kirimi email ke beberapa orang yang belum git tercerahkan. Sejauh ini, semua yang saya lakukan memberi saya 8 file tambalan, atau mulai memberi saya tambalan file untuk setiap komit dalam sejarah cabang, sejak awal waktu. Saya menggunakan git rebase --interaktif untuk menekan komit, tapi sekarang semua yang saya coba memberi saya zillions patch dari awal waktu. Apa yang saya lakukan salah?

git format-patch master HEAD # yields zillions of patches, even though there's 
                             # only one commit since master
skiphoppy
sumber
Saya ingin tahu tentang metode apa yang akan Anda gunakan di antara proposisi di bawah ini. Beri tahu kami;)
VonC
4
Saya akan menggunakan git diff seperti yang disarankan oleh Rob Di Marco. Tapi aku libur kerja selama dua minggu, baru saja menyaksikan kelahiran bayi perempuanku yang kedua tadi malam, jadi sebentar sebelum aku menggunakannya! :)
skiphoppy
2
Saya akan senang melihat git format-patch - master squash KEPALA
schoetbi
1
Coba master .. KEPALA untuk menentukan rentang rev.
Konrad Kleine

Jawaban:

186

Saya akan merekomendasikan melakukan ini pada cabang sekali pakai sebagai berikut. Jika komit Anda berada di cabang "baris baru" dan Anda telah beralih kembali ke cabang "master" Anda, ini seharusnya bisa dilakukan:

[adam@mbp2600 example (master)]$ git checkout -b tmpsquash
Switched to a new branch "tmpsquash"

[adam@mbp2600 example (tmpsquash)]$ git merge --squash newlines
Updating 4d2de39..b6768b2
Fast forward
Squash commit -- not updating HEAD
 test.txt |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git commit -a -m "My squashed commits"
[tmpsquash]: created 75b0a89: "My squashed commits"
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git format-patch master
0001-My-squashed-commits.patch

Semoga ini membantu!

Adam Alexander
sumber
2
Ini yang saya gunakan ketika saya ingin menyimpan sejarah secara lokal (kalau-kalau saya perlu mengedit tambalan). Kalau tidak, saya hanya menggunakan rebase -i dan menekan komit.
sebnow
5
bagi saya, itu bekerja lebih dapat diandalkan dengan git comit -m "My squashed commits"jika tidak akan menambah file yang tidak terlacak lainnya
Sebastian
Selain itu, Anda dapat beralih ke komit tertentu alih-alih master dan melakukan ini untuk membuat tambalan dari komit ke komit:git checkout 775ec2a && git checkout -b patch && git merge --squash branchname
Berry M.
131

Hanya dengan menambahkan satu solusi lagi ke pot: Jika Anda menggunakan ini sebagai gantinya:

git format-patch master --stdout > my_new_patch.diff

Maka masih akan ada 8 tambalan ... tetapi semuanya akan berada dalam tambalan tunggal dan akan berlaku sebagai satu dengan:

git am < my_new_patch.diff
Taryn East
sumber
13
Saya suka solusi ini. Perlu diperhatikan bahwa itu terkadang membuat patch yang jauh lebih besar daripada metode yang dijelaskan oleh @Adam Alexander. Ini karena beberapa file dapat diedit lebih dari satu kali melalui komit. Metode ini memperlakukan setiap komit secara terpisah, bahkan jika beberapa file dikembalikan. Tapi sebagian besar waktu ini bukan masalah.
gumik
1
Opsi ini bagus jika Anda mencoba menghindari penggabungan! (mis. Anda ingin melewatkan beberapa komitmen). Anda masih bisa git rebase -i ...dan remas semuanya menjadi satu.
Jorge Orpinel
21

Saya selalu menggunakan git diff jadi dalam contoh Anda, sesuatu seperti

git diff master > patch.txt
Rob Di Marco
sumber
15
Kecuali Anda kehilangan semua pesan komit dan metadata. Keindahan git format-patch adalah dimungkinkan untuk merekonstruksi seluruh cabang dari satu set tambalan.
mcepl
metode buat-cabang-dan-squash memiliki manfaat menggabungkan semua pesan komit menjadi satu, tetapi metode ini jauh lebih cepat jika Anda ingin menulis pesan komit Anda sendiri
woojoo666
sebenarnya, pesan gabungan dapat dilakukan menggunakan git log, lihat jawaban saya untuk contoh
woojoo666
2
Opsi yang bagus, tetapi pertimbangkan bahwa 'git diff' tidak dapat menyertakan perbedaan biner (mungkin ada opsi untuk melakukannya).
Santiago Villafuerte
18

Ini adalah adaptasi dari jawaban Adam Alexander, kalau-kalau perubahan Anda di cabang utama. Ini lakukan hal berikut:

  • Membuat cabang sekali pakai baru "tmpsquash" dari titik yang kita inginkan (cari kunci SHA yang menjalankan "git --log" atau dengan gitg. Pilih komit yang Anda inginkan menjadi kepala tmpsquash, komit yang setelah itu dalam master akan menjadi terjepit berkomitmen).
  • Menggabungkan perubahan dari master ke tmpsquash.
  • Melakukan perubahan tergencet ke tmpsquash.
  • Buat tambalan dengan komit terjepit.
  • Kembali ke cabang utama

laura@rune:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38
laura@rune:~/example (master)$ git checkout tmpsquash
Switched to branch 'tmpsquash'
laura@rune:~/example (tmpsquash)$ git merge --squash master
Updating ba3c498..40386b8
Fast-forward
Squash commit -- not updating HEAD

[snip, changed files]

11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git commit -a -m "My squashed commits"
[test2 6127e5c] My squashed commits
11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git format-patch master
0001-My-squashed-commits.patch
laura@rune:~/example  (tmpsquash)$ git checkout master
Switched to branch 'master'
laura@rune:~/example  (master)$
rek
sumber
Membuat perubahan pada master adalah anti-pola jika Anda tidak akan mendorong mereka untuk menjauhkan diri. Dan jika Anda mau, Anda mungkin tidak perlu membuat file tambalan untuk mereka.
ivan_pozdeev
18

Seperti yang sudah Anda ketahui, a git format-patch -8 HEADakan memberi Anda delapan tambalan.

Jika Anda ingin 8 komit Anda muncul sebagai satu, dan tidak keberatan menulis ulang sejarah cabang Anda ( o-o-X-A-B-C-D-E-F-G-H), Anda dapat:

git rebase -i
// squash A, B, C, D, E ,F, G into H

atau, dan itu akan menjadi solusi yang lebih baik, putar ulang semua 8 komitmen Anda dari X(komit sebelum 8 komitmen Anda) pada cabang baru

git branch delivery X
git checkout delivery
git merge --squash master
git format-patch HEAD

Dengan begitu, Anda hanya memiliki satu komitmen pada cabang "pengiriman", dan itu mewakili semua 8 komitmen terakhir Anda

VONC
sumber
git merge masterhanya melakukan fast forward dan tidak memecah menjadi satu. Ubah untuk git merge --squash mastermembuat semua komit tergencet dan terlihat di area panggung. Alur Anda akan bekerja dengan perubahan ini. (Saya menggunakan git versi 2.1.0.)
Stunner
5

Format-patch antara dua tag:

git checkout <source-tag>
git checkout -b <tmpsquash>
git merge --squash <target-tag>
git commit -a -m "<message>"
git format-patch <source-tag>
kashesandr
sumber
5

Cara termudah adalah menggunakan git diff, dan menambahkan git logjika Anda ingin pesan komit gabungan yang dihasilkan oleh metode squash. Misalnya, untuk membuat tambalan antara komit abcddan 1234:

git diff abcd..1234 > patch.diff
git log abcd..1234 > patchmsg.txt

Kemudian saat menerapkan tambalan:

git apply patch.diff
git add -A
git reset patch.diff patchmsg.txt
git commit -F patchmsg.txt

Jangan lupakan --binary argumen git diffketika berurusan dengan file non-teks, misalnya gambar atau video.

woojoo666
sumber
0

Berdasarkan jawaban Adam Alexander:

git checkout newlines
## must be rebased to master
git checkout -b temporary
# squash the commits
git rebase -i master
git format-patch master
Julien W
sumber