Tarihe gömülü bir Git taahhüdünü nasıl bölebilirim?


292

Geçmişimi kustum ve bazı değişiklikler yapmak istiyorum. Sorun şu ki, iki alakasız değişiklikle ilgili bir taahhüdüm var ve bu taahhüt yerel (itilmemiş) geçmişimdeki diğer bazı değişikliklerle çevrili.

Bu taahhüdü dışarı çıkmadan önce ayırmak istiyorum, ancak gördüğüm kılavuzların çoğunun en son taahhüdünüzü veya taahhüt edilmemiş yerel değişiklikleri bölmekle ilgisi var. Bunu, o zamandan beri taahhütlerimi "yeniden yapmak" zorunda kalmadan, tarihe gömülü bir taahhüde yapmak mümkün müdür?


Yanıtlar:


450

Rebase kılavuzunda taahhütleri bölme kılavuzu vardır . Kısa özet:

  • Hedef taahhüdü (örn. git rebase -i <commit-to-split>^ branch) İçeren etkileşimli bir yeniden oluşturma işlemi gerçekleştirin ve düzenlenecek şekilde işaretleyin.

  • Rebase bu taahhüde ulaştığında, taahhütten git reset HEAD^önce sıfırlamak için kullanın , ancak çalışma ağacınızı olduğu gibi bırakın.

  • İstediğiniz kadar taahhütte bulunarak, kademeli olarak değişiklikler ekleyin ve taahhüt edin. add -pbelirli bir dosyaya değişikliklerin yalnızca bir kısmını eklemek yararlı olabilir. commit -c ORIG_HEADBelirli bir taahhüt için orijinal kayıt mesajını tekrar kullanmak istiyorsanız kullanın .

  • Ne taahhütte bulunduğunuzu (iyi fikir!) Test etmek istiyorsanız, taahhüt git stashetmediğiniz kısmı (veya stash --keep-indextaahhüt etmeden önce ) gizlemek için kullanın , test edin, ardından git stash popgerisini çalışma ağacına geri döndürün. Tüm değişiklikleri tamamlayana kadar taahhütte bulunmaya devam edin, yani temiz bir çalışma ağacınız olsun.

  • git rebase --continueŞimdi bölünmüş taahhütten sonra taahhütleri uygulamaya devam etmek için çalıştırın .


17
... ama bölünme taahhüdünden bu yana tarihi zaten ittiyseniz, hiçbirini yapmayın.
wilhelmtell

29
@wilhelmtell: Her zamanki "potansiyel olarak tehlikeli; bkz. 'yukarı akış rebazından kurtulma'" kazan plakasını atladım çünkü OP açıkça bu tarihi itmediğini söyledi.
Cascabel

2
ve mükemmel bir okuma yaptınız. Henüz paylaşılan tarih olmadığını belirlediğimde 'kazan plakası' önlemek için çalışıyordu :) Herhangi bir bakımdan, öneri ile başarı elde ettim. Gerçi bu şeyleri yapmak büyük bir acıdır. Burada bir ders öğrendim ve bu, taahhütlerin doğru bir şekilde yapıldığından emin olmak için!
Ben

2
İlk adım olarak daha iyi ifade edilebilir git rebase -i <sha1_of_the_commit_to_split>^ branch. Ve git guibir dosyanın farklı bölümlerini farklı taahhütlere eklemek için kullanılabilecek bölme görevi için güzel bir araçtır.
Qiang Xu

3
@QiangXu: Birincisi makul bir öneri. İkincisi, tam da bu yüzden önerdiğim git add -p, git guibu departmanda yapabileceğinden daha fazlasını yapabilir (özellikle iri parçaların düzenlenmesi, mevcut iri parçadan başlayarak her şeyin sahnelenmesi ve regex ile iri parçaların aranması).
Cascabel

3

Magit ile nasıl yapılacağı aşağıda açıklanmıştır .

Diyelim ki ed417ae değiştirmek istediğiniz kişi; alakasız iki değişiklik içerir ve bir veya daha fazla taahhüt altına gömülür. Hit lled417ae Günlüğü ve gezinmek göstermek için:

ilk günlük

Sonra rrebase pop-up penceresini açmak için tıklayın

açılır pencere

ve mtaahhüt noktasını değiştirmek.

Bölmek @istediğiniz taahhütte nasıl var olduğuna dikkat edin - bu, HEAD'in şu taahhütte olduğu anlamına gelir:

Bir taahhüdü değiştirmek

Biz ebeveyn (47e18b3) ve isabet etmek gezinme yüzden, ebeveyne HEAD taşımak istediğiniz x( magit-reset-quicklybağlı, okullandığınız takdirde evil-magit) ve söylemek enter "evet ben noktada işlemek anlamına". Günlüğünüz şimdi şöyle görünmelidir:

sıfırladıktan sonra günlüğe kaydet

Şimdi, qnormal Magit durumuna gitmek için vurun, ardından uilk taahhütte gitmeyenleri bozmak için normal çarpıklık komutunu kullanın c, gerisini her zamanki gibi yapın, sonra ikinci taahhütte olanları sbitirin ve ctamamlayın: vurmak rrebase açılır pencere açmak

açılır pencere

ve rdevam etmek için bir tane daha ve işiniz bitti! llşimdi gösteriyor:

her şey tamamlandı


1

Bir taahhüdü bölmek <commit>ve bundan önce yeni taahhüdü eklemek ve yazarın tarihini kaydetmek için <commit>, - adımlar aşağıdaki gibidir:

  1. Önce taahhüdü düzenle <commit>

    git rebase -i <commit>^^
    

    Not: belki de düzenlemek de gerekecektir <commit>.

  2. Kiraz <commit>endeks içine almak

    git cherry-pick -n <commit>
    
  3. Dizinden gereksiz değişiklikleri etkileşimli olarak sıfırlayın ve çalışma ağacını sıfırlayın

    git reset -p && git checkout-index -f -a
    

    Alternatif olarak, gereksiz değişiklikleri etkileşimli olarak saklayın: git stash push -p -m "tmp other changes"

  4. Varsa diğer değişiklikleri yapın ve yeni taahhüdü oluşturun

    git commit -m "upd something" .
    

    İsteğe bağlı olarak, daha fazla ara taahhüt eklemek için 2-4 maddelerini tekrarlayın.

  5. Yeniden baslamaya devam et

    git rebase --continue
    

0

Yalnızca tek bir dosyadan içerik ayıklamak istiyorsanız daha hızlı bir sürüm vardır. Daha hızlıdır çünkü etkileşimli rebase aslında etkileşimli değildir (ve son işlemden çıkarmak istiyorsanız elbette daha da hızlıdır, o zaman hiç yeniden pazarlamaya gerek yoktur)

  1. Düzenleyicinizi kullanın ve ayıklamak istediğiniz satırları silin the_file. Kapatın the_file. İhtiyacınız olan tek sürüm bu, gerisi sadece git komutları.
  2. Dizindeki silme işlemini aşamalandır:

    git  add  the_file
    
  3. Az önce sildiğiniz satırları dizini etkilemeden geri yükleyin !

    git show HEAD:./the_file > the_file
    
  4. "SHA1" satırları çıkarmak istediğiniz işlemdir:

    git commit -m 'fixup! SHA1' 
    
  5. 3. adımda geri yüklenen içerikle ikinci, yepyeni taahhüdü oluşturun:

    git commit -m 'second and new commit' the_file 
    
  6. Düzenleme, durdurma / devam etme - her şeyi kabul et:

    git rebase --autosquash -i SHA1~1
    

Tabii ki, çıkarma taahhüdü son taahhüt olduğunda daha da hızlıdır:

4. git commit -C HEAD --amend
5. git commit -m 'second and new commit' thefile
6. no rebase, nothing

Eğer kullanırsanız magito zaman adım 4, 5 ve 6 tek bir eylem şunlardır: anlık Fixup Teslim


-2

Henüz itmediyseniz, sadece kullanın git rebase. Daha da iyisi, git rebase -itaahhütleri etkileşimli olarak hareket ettirmek için kullanın . Sorunlu taahhüdü öne taşıyabilir, sonra istediğiniz gibi bölebilir ve yamaları geri taşıyabilirsiniz (gerekirse).


14
Hiçbir yere taşımanıza gerek yok. Olduğu yere bölün.
Cascabel

1
Ne yazık ki, bu benim için işe yaramıyor çünkü taahhütten sonraki tarihin bir kısmı ona bağlı, bu yüzden biraz kısıtlıyım. Ancak, bu benim ilk tercihim olurdu.
Ben

@Ben: sorun değil - daha sonra yapılan taahhütlerin hiç değişmesi gerekmeyecek (bazı değişiklikleri atmak yerine tüm değişiklikleri sakladığınızı varsayarsak). Daha fazla bilgi için - stackoverflow.com/questions/1440050/…
Eter
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.