Git format-patch ile nasıl bir yama yaparsınız?


163

Bir dalda henüz aydınlanmayan bazı kişilere e-posta ile göndermek istediğim sekiz taahhüt var. Şimdiye kadar yaptığım her şey bana 8 yama dosyası veriyor ya da zamanın başından beri şubenin tarihindeki her taahhüt için yama dosyaları vermeye başlıyor. Taahhütleri ezmek için git rebase - etkileşimli kullandım, ama şimdi denediğim her şey bana zamanın başlangıcından beri milyonlarca yama veriyor. Neyi yanlış yapıyorum?

git format-patch master HEAD # yields zillions of patches, even though there's 
                             # only one commit since master

Aşağıdaki öneriler arasında hangi yöntemi kullanacağınızı merak ediyorum. Bize bildirin;)
VonC

4
Git farkını Rob Di Marco'nun önerdiği gibi kullanacağım. Ama iki hafta işsizim, dün gece ikinci kız çocuğumun doğuşuna tanıklık ettim, bu yüzden kullanmadan önce biraz zaman geçecek! :)
skiphoppy

2
Git Format-Patch'i görmek isterim
squash

1
Bir devir aralığı belirtmek için master..HEAD öğesini deneyin.
Konrad Kleine

Yanıtlar:


186

Bunu aşağıdaki gibi bir ıssız dalda yapmanızı tavsiye ederim. Taahhütleriniz "yeni satırlar" dalındaysa ve zaten "ana" dalınıza geri döndüyseniz, bu hile yapmalıdır:

[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

Bu yardımcı olur umarım!


2
Geçmişi yerel olarak tutmak istediğimde kullandığım şey budur (düzeltme ekini düzenlemeniz gerektiğinde). Aksi takdirde sadece rebase -i kullanıyorum ve taahhütleri eziyorum.
sebnow

5
benim için daha güvenilir çalıştı, git comit -m "My squashed commits"aksi takdirde diğer izlenmemiş dosyaları eklerdi
Sebastian

Taahhüt dan Additonally sen taahhüt yerine ustanın taahhüt Belli bir bölüme geçmek ve bir yama oluşturmak için bunu yapabilirsiniz:git checkout 775ec2a && git checkout -b patch && git merge --squash branchname
Berry M.

131

Tencereye bir çözüm daha eklemek için: Bunun yerine şunu kullanırsanız:

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

Sonra hala 8 yama olacak ... ama hepsi tek bir yama dosyasında olacak ve aşağıdakilerle uygulanacak:

git am < my_new_patch.diff

13
Bu çözümü seviyorum. @Adam Alexander tarafından açıklanan yöntemden bazen çok daha büyük bir yama oluşturabileceğine dikkat etmek önemlidir. Bunun nedeni, bazı dosyaların taahhütler aracılığıyla birden fazla kez düzenlenebilmesidir. Bu yöntem, bir dosya geri döndürülse bile her bir taahhüdü ayrı ayrı ele alır. Ancak çoğu zaman bu bir sorun değildir.
gumik

1
Birleştirme işleminden kaçınmaya çalışıyorsanız bu seçenek harikadır! (örneğin, bazı taahhütleri atlamak istiyorsunuz). Yine de git rebase -i ...hepsini bire bir ezebilirsin.
Jorge Orpinel

21

Ben her zaman git diff kullanıyorum, örneğin

git diff master > patch.txt

15
Tüm taahhüt mesajlarını ve meta verileri kaybetmeniz dışında. Git format-patch'in güzelliği, tüm dalı bir dizi yamadan yeniden yapılandırmanın mümkün olmasıdır.
mcepl

şube oluştur ve squash yöntemi, tüm taahhüt mesajlarını bir araya getirme avantajına sahiptir, ancak kendi taahhüt mesajınızı yazmak istiyorsanız bu yöntem çok daha hızlıdır
woojoo666 3:15

aslında, kombine bir mesaj kullanılarak yapılabilir git log, bir örnek için cevabım bakın
woojoo666

2
Güzel bir seçenek, ancak 'git diff' ikili farklılıklar içeremez düşünün (belki bunu yapmak için bir seçenek var).
Santiago Villafuerte

18

Bu, değişikliklerinizin ana dalda olması durumunda Adam Alexander yanıtının bir uyarlamasıdır. Bunu yapmak:

  • İstediğimiz noktadan "tmpsquash" yeni bir atma dalı oluşturur ("git --log" çalıştıran veya gitg ile çalışan SHA anahtarını arayın. ezilmiş taahhütler).
  • Master'dan tmpsquash'e yapılan değişiklikleri birleştirir.
  • Tmpsquash'te ezilmiş değişiklikleri yapar.
  • Ezilmiş taahhütlerle düzeltme eki oluşturur.
  • Ana şubeye geri döner

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)$

Kendinizi uzaktan kumanda etmeye zorlamayacaksanız, master'da değişiklik yapmak bir anti-desendir. Ve eğer yapacaksanız, muhtemelen onlar için yama dosyaları oluşturmanız gerekmez.
ivan_pozdeev

18

Bildiğiniz gibi, a git format-patch -8 HEADsize sekiz yama verecektir.

8 taahhüdünüzün bir olarak görünmesini ve şubenizin ( o-o-X-A-B-C-D-E-F-G-H) geçmişini yeniden yazmayı önemsemiyorsanız , şunları yapabilirsiniz:

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

veya daha iyi bir çözüm olurdu , 8 taahhüdünüzü X(8 taahhütten önceki taahhüt) yeni bir dalda tekrar oynatın

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

Bu şekilde, "teslimat" dalında yalnızca bir taahhüdünüz olur ve bu son 8 taahhüdünüzü temsil eder


git merge mastersadece bir hızlı ileri alır ve bir tanesini ezmez. git merge --squash masterHazırlanan alanda tüm taahhütlerin ezilmesini ve görünür olmasını sağlamak için değiştirin . Akışınız bu değişiklikle çalışacaktır. (Git sürüm 2.1.0 kullanıyorum.)
Stunner

5

İki etiket arasındaki biçim düzeltme eki:

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

5

En kolay yol kullanmak git diffve git logsquash yönteminin çıkardığı birleşik taahhüt mesajını kullanmaktır. Örneğin, commit abcdve 1234: arasında yama oluşturmak için :

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

Sonra yamayı uygularken:

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

Resim veya video gibi metin olmayan dosyalarla uğraşırken --binarytartışmayı unutmayın git diff.


0

Adam Alexander'ın cevabına dayanarak:

git checkout newlines
## must be rebased to master
git checkout -b temporary
# squash the commits
git rebase -i master
git format-patch master
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.