Git birleştirme taahhüdünde yeniden adlandırma


183

Aşağıdaki durumu ele alalım:

Bir konu dalında bazı işlerim var ve şimdi master'a geri dönmeye hazırım:

* eb3b733 3     [master] [origin/master]
| * b62cae6 2   [topic]
|/  
* 38abeae 1

Ben master birleştirme gerçekleştirmek, anlaşmazlıkları çözmek ve şimdi var:

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | eb3b733 3                     [origin/master]
|/  
* 38abeae 1

Şimdi, birleştirme bana biraz zaman aldı, bu yüzden başka bir getirme yapıyorum ve uzak ana dalın yeni değişiklikler olduğunu fark ediyorum:

*   8101fe3 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
| | * e7affba 4                   [origin/master]
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

'Git rebase origin / master' ı master'dan denersem, tüm çatışmaları tekrar çözmek zorunda kalırım ve birleştirme taahhüdünü de kaybederim:

* d4de423 2       [master]
* e7affba 4       [origin/master]
* eb3b733 3
| * b62cae6 2     [topic]
|/  
* 38abeae 1

Birleştirme taahhüdünü yeniden kazanmanın temiz bir yolu var mı, bu yüzden aşağıda gösterdiğim gibi bir tarihle karşılaşıyorum?

*   51984c7 Merge branch 'topic'  [master]
|\  
| * b62cae6 2                     [topic]
* | e7affba 4                     [origin/master]
* | eb3b733 3
|/  
* 38abeae 1

74
TL; DR:git rebase --preserve-merges origin/master
Ilia K.

6
Çatışmaları yeniden çözmek zorunda kalmayla ilgili olarak git rerere'ye bakmak isteyebilirsiniz .
Parker Coates,

git config --global pull.rebase preserve bir rebase sırasında birleştirme taahhütlerini her zaman korumak için
galath

4
Uyarı: Git 2.18'den (5 yıl sonra 2. Çeyrek) başlayarak git --rebase-mergeseski olanın yerini alacak git --preserve-merges. Bkz aynen Git adlı “ne rebase --preserve-merges” do (ve neden?)
VonC

1
--preserve-mergeskullanımdan kaldırıldı. Kullanımgit rebase --rebase-merges origin/master
Arjun Sreedharan

Yanıtlar:


127

Burada iki seçenek var.

Bunlardan biri etkileşimli bir yeniden taban oluşturmak ve birleştirme taahhüdünü düzenlemek, birleştirmeyi manuel olarak yeniden yapmak ve yeniden oluşturmaya devam etmektir.

Bir diğeri ise , kılavuzda aşağıdaki gibi açıklanan --rebase-mergesseçeneği kullanmaktır git rebase: "Varsayılan olarak, bir rebase yapılacaklar listesinden birleştirme taahhütlerini bırakacak ve yeniden temel alınan taahhütleri tek bir doğrusal dal haline getirecektir. birleşim yerine, yeniden oluşturma işlemlerinin yeniden oluşturulması, yeniden birleştirme işlemlerini yeniden oluşturarak, taahhütlerin içindeki dallanma yapısını korumaya çalışacaktır.


16
-P seçeneğini denedim ve gerçekten de taahhüt geçmişini istediğim gibi bırakıyor, ancak orijin / master olarak düzenlenmemiş dosyalarda bile çatışmaları tekrar çözmem için beni zorluyor. İlk önerinizden itibaren, kesin komut sırası hangisi olurdu?
jipumarino

2
@jipumarino: git rebase -i (birleştirme taahhüdünü düzenlemesini söyle), birleştirme taahhüdüne ulaştığında, git reset --hard HEAD ^, git merge, fix çakışmalar, git commit, git rebase --continue. Ayrıca, bu tür bir şeyle yardımcı olması gereken git rerere'ye bakmak isteyebilirsiniz (ama hiç kullanmadım, bu yüzden herhangi bir tavsiye veya yardım sunamıyorum).
siride

2
Teşekkürler. Tekrar etkinleştirdim ve rebase -p ile denedim ve olması gerektiği gibi çalışıyor.
jipumarino

3
İşte bu durumu açıklayan mükemmel bir blog yazısı:
Git'teki

1
rere çözüm değildir, çünkü birleştirmeleri ilk kez manuel olarak çözmeniz gerekir.
Ocak'ta Flimm

29

Tamam, bu eski bir soru ve zaten cevabını kabul etti @siride, ama bu cevap benim durumumda yeterli değildi, çünkü --preserve-mergessizi tüm çatışmaları ikinci kez çözmeye zorluyor. Benim fikrim dayalı @Tobi Bama tam adım adım komutları ile benim çözüm

Bu yüzden, sorudaki örneğe göre böyle bir duruma başlayacağız:

*   8101fe3 Merge branch 'topic'  [HEAD -> master]
|\  
| * b62cae6 2                     [topic]
| |
| | * f5a7ca8 5                   [origin/master]
| | * e7affba 4
| |/  
|/|   
* | eb3b733 3
|/  
* 38abeae 1

Önümüzde 2 taahhüt var, bu yüzden kiraz toplama işe yaramaz.

  1. Her şeyden önce, istediğimiz doğru tarihi yaratalım:

    git checkout -b correct-history # create new branch to save master for future
    git rebase --strategy=ours --preserve-merges origin/master
    

    --preserve-mergesTarihte birleştirme taahhüdümüzü kurtarmak için kullanıyoruz . Bu --strategy=oursbirleştirme işleminde hangi içeriklerin olacağı umurumda olmadığından tüm birleştirme çatışmalarını görmezden geliriz, şimdi sadece güzel bir tarihe ihtiyacımız var.

    Tarih şöyle görünecektir (master yok sayılıyor):

    *   51984c7 Merge branch 'topic'  [HEAD -> correct-history]
    |\  
    | * b62cae6 2                     [topic]
    * | f5a7ca8 5                     [origin/master]
    * | e7affba 4
    * | eb3b733 3
    |/  
    * 38abeae 1
    
  2. Şimdi doğru indeksi alalım.

    git checkout master # return to our master branch
    git merge origin/master # merge origin/master on top of our master
    

    Burada ek birleştirme çakışmaları olabilir, ancak bu yalnızca 8101fe3ve arasında değiştirilmiş dosyalardan gelen çakışmalar olacaktır f5a7ca8, ancaktopic

    Tarih şöyle görünecektir (doğru geçmişi göz ardı ederek):

    *   94f1484 Merge branch 'origin/master'  [HEAD -> master]
    |\  
    * | f5a7ca8 5                   [origin/master]
    * | e7affba 4
    | *   8101fe3 Merge branch 'topic'
    | |\  
    | | * b62cae6 2                     [topic]
    |/ /
    * / eb3b733 3
    |/  
    * 38abeae 1
    
  3. Son aşama şubemizi doğru tarih ve şubemizi doğru endeks ile birleştirmektir.

    git reset --soft correct-history
    git commit --amend
    

    reset --softŞubemizi (ve geçmişimizi) doğru geçmişe sıfırlamak için kullanıyoruz , ancak dizin ve çalışma ağacını olduğu gibi bırakıyoruz. Ardından commit --amend, yanlış dizine sahip olan birleştirme taahhüdümüzü ustanın iyi dizinimizle yeniden yazmak için kullanırız .

    Sonunda böyle bir duruma sahip olacağız (üst düzey bir üst kimliğe dikkat edin):

    *   13e6d03 Merge branch 'topic'  [HEAD -> master]
    |\  
    | * b62cae6 2                     [topic]
    * | f5a7ca8 5                     [origin/master]
    * | e7affba 4
    * | eb3b733 3
    |/  
    * 38abeae 1
    

Bu harika ve çok yardımcı oldu! Ancak, hile ile tamamlamadım - amend: Bununla ilgili daha fazla bilgi ekleyebilir misiniz? Çalıştırdıktan sonra tam olarak ne olur - taahhüt edilen SHA'nın değiştiğini fark ettim - ama neden? Ya da bunu yapmazsan ne olur?
ZenJ

1
@ZenJ git commit --amend, değişiklikleri son işleme (HEAD, bu durumda birleştirme taahhüdü) ekler. Taahhüt içeriği değiştiği için, karma güncellenir.
Dries Staelens

1
Çatışmaları gidermeden önce 'tekrar' etkinleştirilmemiş insanlar için bu çözüm harika çünkü çatışmaları tekrar düzeltmenizden kurtarıyor. Teşekkürler!
Shackleford

6

Bunu anlamaya çalışırken bir günümü kaybettiğim ve aslında bir iş arkadaşının yardımıyla bir çözüm bulduğum göz önüne alındığında, içeri girmem gerektiğini düşündüm.

Büyük bir kod tabanımız var ve aynı anda 2 şube yoğun bir şekilde değiştiriliyor. Eğer bir ana dal ve bir ikincil dal vardır.

İkincil şubeyi ana şubeye birleştirirken, ana şubede çalışmalar devam ediyor ve işim bittiğinde, değişikliklerimi geçemiyorum çünkü uyumsuzlar.

Bu nedenle benim "birleştirme" benim "yeniden" gerekir.

Sonunda böyle yaptık:

1) SHA'yı not edin. ör .: c4a924d458ea0629c0d694f1b9e9576a3ecf506b

git log -1

2) Uygun geçmişi oluşturun, ancak bu birleşmeyi bozacaktır.

git rebase -s ours --preserve-merges origin/master

3) SHA'yı not edin. ör .: 29dd8101d78

git log -1

4) Şimdi daha önce bulunduğunuz yere sıfırlayın

git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard

5) Şimdi mevcut master'ı çalışma şubenize birleştirin

git merge origin/master
git mergetool
git commit -m"correct files

6) Artık doğru dosyalara sahip olduğunuza, ancak yanlış geçmişe sahip olduğunuza göre, aşağıdaki değişikliklerle doğru geçmişi alın:

git reset 29dd8101d78 --soft

7) Ve sonra - orijinal birleştirme taahhüdünüzdeki sonuçları değiştirin

git commit --amend

İşte bu kadar!


1

Görünüşe göre yapmak istediğiniz ilk birleşmenizi kaldırmak. Aşağıdaki prosedürü takip edebilirsiniz:

git checkout master      # Let's make sure we are on master branch
git reset --hard master~ # Let's get back to master before the merge
git pull                 # or git merge remote/master
git merge topic

Bu size istediğinizi verir.


4
Tekrar etkinleştirildiğinde, bu, siride tarafından yukarıda verilen rebase -p çözümü ile aynı sonucu veriyor gibi görünüyor.
jipumarino

0
  • Birleştirme işleminizden
  • Kolay olması gereken yeni değişikliği Cherry-pick
  • eşyalarını kopyala
  • dosyaları yerel kopyanızdan kopyalayarak birleştirmeyi yeniden yapın ve çakışmaları çözün;)

1
Bu cevap iyi görünüyor, ancak gerçek git komutlarını verirseniz, kullanıcının gitmesi için yeni olması durumunda daha yararlı olur
Louise Davies
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.