Başka bir şubedeki tüm değişiklikleri tek bir taahhüt olarak birleştir (squash ile)


479

Git'te, tüm değişiklikleri bir daldan diğerine birleştirmenin bir yolu var mı, ancak aynı anda tek bir taahhütte eziliyor musunuz?

Sık sık ayrı bir dalda yeni bir özellik üzerinde çalışıyorum ve düzenli olarak taahhüt / itiyorum - esas olarak yedekleme veya üzerinde çalıştığım şeyi başka bir makineye aktarmak için. Çoğunlukla bu taahhütler "Feature xxx WIP" veya gereksiz bir şey der.

Bu iş bittiğinde ve WIP şubesini ustalıkla birleştirmek istediğimde, tüm bu ara taahhütleri atmak istiyorum ve sadece tek bir temiz taahhüdüm var.

Bunu yapmanın kolay bir yolu var mı?

Alternatif olarak, bir dalda dallandığı noktadan bu yana tüm bunları ezen bir komuta ne dersiniz?

Yanıtlar:


601

Başka bir seçenek git merge --squash <feature branch>nihayet bir git commit.

Gönderen Git birleştirme

--squash

--no-squash

Çalışma ağacını ve dizin durumunu gerçek bir birleştirme gerçekleşmiş gibi (birleştirme bilgileri hariç) üretin, ancak gerçekte bir taahhütte bulunmayın ya da taşımayın ya da bir sonraki birleştirme işleminin birleştirme taahhüdü oluşturmasına neden olacak şekilde HEADkayıt yapmayın . Bu, geçerli dalın üstünde, etkisi başka bir dalı (veya bir ahtapot durumunda daha fazlasını) birleştirmekle aynı olan tek bir işlem oluşturmanıza olanak tanır.$GIT_DIR/MERGE_HEADgit commit


1
Harika özellik! Git'i seviyorum. Gelecekte bunu kesinlikle kullanacak olsam da, rebase -i'de yolunuzu öğrenmenizi tavsiye ederim. Gerçekten de onları sadece bir taahhütten daha fazlasını yapmak istemiş olmanız durumunda iyi bir beceri.
Buck

4
Dikkatli bir kelime: Bu işe yarar, ancak varsayılan tamamlama iletisi, birleştirilen daldaki günlüğü içerir. Sorun, normalde gösterilen metnin tamamının gerçekte taahhüt mesajının bir parçası olmadığı, ancak bu durumda gördüğü formata benzemesidir. Yani tüm bunları istemiyorsanız, tamamlama mesajınızdan hepsini manuel olarak kaldırmanız gerekir. Bunu kullanmadan önce test
etmeliydim

23
Bu ve dalın birleştirilmiş olarak görülmeyeceği konusunda uyarılmalıdır. stackoverflow.com/questions/19308790/…
Ryan

3
IMHO buna çağrılmış olmalırebase --squash
Andy

yani (özellik dalını gerçekten birleştirmediğinden), işlemden sonra özellik dalını silecekseniz bu uygun olur. Bu doğru mu? (Ben bir git uzmanı değilim)
Andrew Spencer

214

Buldum! Birleştirme komutunun bir --squashseçeneği vardır

git checkout master
git merge --squash WIP

bu noktada her şey birleştirilir, muhtemelen çatışır, ancak taahhüt edilmez. Şimdi yapabilirim:

git add .
git commit -m "Merged WIP"

2
ne gelmez git add .mi?
Michael Potter

1
@MichaelPotter Tüm dosyaları ve değişiklikleri ekler
Daksh Shah

2
git add .geçerli dizinde yoksayılan dosyaları ekler, ben istenmeyen dosyaları bu şekilde almak dikkatli olurdum.
Jake Cobb

7
Alternatif olarak , yalnızca ağaca zaten eklenmiş olan dosyaları eklemek için git add .kullanabilirsiniz git add -u.
Brandon Ogle

19
Bir "git add." ayrıca yapılması kafa karıştırıcıdır. Ben "git merge --squash WIP" yaptığımda, zaten dizinde ezilmiş değişiklikler var. Tek gereken, onları taahhüt etmektir. Bir "git add." çalışma dizininde olan, ancak özellik dalının bir parçası olmayan değişiklikleri ekler. Soru, özellik dalındaki değişikliklerin bir taahhüt olarak nasıl taahhüt edileceği idi.
John Pankowicz

30

git rebase -i masterÖzellik dalınızı deneyin . Daha sonra, taahhütleri birleştirmek için bir 'seçim' hariç hepsini 'squash' olarak değiştirebilirsiniz. Rebase ile ezme işlemlerini görün

Son olarak, ana daldan birleştirme yapabilirsiniz.


8
Evet, işe yarıyor, ama etkileşimli rebase uğraşmasını istemiyorum. Şube düzleştiği için her şeyi istiyorum.
Brad Robinson

2
+1 Bu temiz bir geçmiş sağlar. Taahhütleri bireysel yamalar, kartlar, hikayeler, vb. Olarak tanımlamak ve yönetmek çok daha kolay
Ryan

2

Kabul edilen cevabın önerdiği git merge --squash <feature branch>gibi kullanmak hile yapar, ancak birleştirilmiş dalı gerçekte birleştirildiği gibi göstermez.

Bu nedenle daha da iyi bir çözüm:

  • En son master'dan yeni bir şube oluşturun
  • Birleştirmek <feature branch>Kullanarak yukarıdakileregit merge --squash
  • Yeni oluşturulan dalı master ile birleştir

Bu wiki prosedürü ayrıntılı olarak açıklar.


0

Bunu yapmak için kendi git takma adımı oluşturdum. Onu arıyorumgit freebase ! Mevcut dağınık, dayanılmaz özellikli dalınızı alır ve taahhütleri tek bir taahhütte ezilmiş ve belirttiğiniz dalda yeniden oluşturulmuş (varsayılan olarak ana) ile aynı ada sahip yeni bir dal haline gelir. En sonunda, yeni "serbest tabanlı" dalınız için istediğiniz herhangi bir taahhüt mesajını kullanmanıza izin verecektir.

Aşağıdaki diğer adı .gitconfig dosyasına yerleştirerek yükleyin:

[alias]
  freebase = "!f() { \
    TOPIC="$(git branch | grep '\\*' | cut -d ' ' -f2)"; \
    NEWBASE="${1:-master}"; \
    PREVSHA1="$(git rev-parse HEAD)"; \
    echo "Freebaseing $TOPIC onto $NEWBASE, previous sha1 was $PREVSHA1"; \
    echo "---"; \
    git reset --hard "$NEWBASE"; \
    git merge --squash "$PREVSHA1"; \
    git commit; \
  }; f"

Aşağıdakileri çalıştırarak özellik dalınızdan kullanın: git freebase <new-base>

Bunu sadece birkaç kez test ettim, bu yüzden önce okuyun ve çalıştırmak istediğinizden emin olun. Küçük bir güvenlik önlemi olarak, başlangıç ​​sha1'ini yazdırır, böylece bir şey ters giderse eski dalınızı geri yükleyebilirsiniz.

Bunu github'daki dotfiles repo'mda koruyacağım: https://github.com/stevecrozz/dotfiles/blob/master/.gitconfig


mutluluk gibi çalıştı! siz de bir göz sürebilir evernote.com/shard/s52/sh/7f8f4ff1-9a68-413f-9225-c49e3ee2fafd/...
İlya Sheershoff

-1

git merge --squash <feature branch> iyi git bir seçenektir.

Daha az taahhüt için.

git merge do x times - git reset HEAD ^ --soft sonra git commit.

Riskle silinen dosyalar geri gelebilir.


-5

Bunu "rebase" komutuyla yapabilirsiniz. Dallara "ana" ve "özellik" diyelim:

git checkout feature
git rebase main

Rebase komutu, "main" e eşit bir üst öğe ile bir taahhüt olarak "özellik" üzerindeki tüm taahhütleri yeniden oynatır.

"Özellik" oluşturulduğundan (veya en son birleştirmeden sonra) "ana" değiştiyse daha git merge mainönce çalıştırmak isteyebilirsiniz git rebase main. Bu şekilde, birleşme çatışmanız olması durumunda geçmişinizin tamamına sahip olursunuz.

Rebase'den sonra, şubenizi ana ile birleştirebilirsiniz, bu da hızlı ileri bir birleştirmeye neden olur:

git checkout main
git merge feature

İyi bir genel bakış için Git Kavramını Anlama'nın rebase sayfasına bakın


Bu benim için işe yaramadı. Sadece bir WIP şubesi ile basit bir test repo oluşturdum ve yukarıdakileri denedim ve birleştirme çatışmaları aldım (ustada herhangi bir değişiklik yapmamış olmama rağmen).
Brad Robinson

Özellik
main'dan

Tamam, tekrar denedim. Bu sefer anlaşmazlık olmadı, ama tarih ezilmedi.
Brad Robinson

Git-merge belgelerine bir kez daha baktığınızda, haklısınız, bazı taahhütler kalacak. "Ana" ile "özellik" arasında daha önce birleştirme yaptıysanız, rebase bunların bazılarını kaldırır, ancak hepsini kaldırmaz.
NamshubWriter

Özellik dalı daha önce yayınlanmışsa yeniden temellendirmenin oldukça tehlikeli olabileceğini unutmayın. Bu SO sorusu hakkında daha fazla bilgi .
Robert Rossmann
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.