Git rebase'i zorunlu bir zorlama gerektirmeden nasıl kullanabilirim?


94

Git nirvana'yı başarma çabasıyla, şu anda birleştiğim durumlar için geri ödemeyi nasıl kaldıracağımı öğrenmek için günü geçiriyorum.

Git 101 akışı (aşağıda açıkladığım) olduğunu düşündüğüm şeyden geçerken, push --forcedeğişikliklerimi başlangıç ​​noktasına geri gönderirken bunu yapmak zorundayım .

Ben tek değilim - bunun kapalı bir zemin olduğunu biliyorum (bkz. 1 , 2 , 3 , 4 , 5 ) ve bir kuvvetin neden gerekli olduğuna dair teknik nedenleri anlıyorum . Benim sorunum şu - geri ödeme övgülerini ve hayatlarını nasıl değiştirdiğini söyleyen birçok (birçok) blog girişi var ( birkaçını listelemek için 1 , 2 , 3 , 4'e bakın ), ancak hiçbiri bunun push --forcebir parçası olduğundan bahsetmiyor onların akışı. Ancak, mevcut yığın aşımı sorularına verilen hemen hemen her yanıt, "evet, yeniden baz alacaksanız, kullanmalısınız push --force" gibi şeyler söyler .

Rebase savunucularının sayısı ve dinselliği göz önüne alındığında, 'push -force' kullanmanın bir rebase akışının doğal bir parçası olmadığına ve eğer biri sık sık zorlamak zorunda kalırsa, yanlış bir şeyler yaptıklarına inanmak zorundayım .

push --forceBir olan kötü bir şey .

İşte benim akışım. Aynı sonuçları zorlamadan nasıl elde edebilirim?

Basit Örnek

İki dal:

  • v1.0 - bir sürüm dalı, yalnızca yamaları içerir
  • master - sonraki büyük sürüm için her şey.

Birkaç yama kaydetmem ve bir sonraki sürüm için birkaç işlemim var.

önceden birleştirmek

Bir sonraki sürümde kaybolmamaları için yamaları ustamla birleştirmek istiyorum. Aydınlanma öncesi basitçe:

git checkout master
git merge v1.0

Ama şimdi deniyorum

git checkout master
git rebase v1.0

Yani şimdi buradayım:

görüntü açıklamasını buraya girin

Zaman için:

git push

Nafile.

Yanıtlar:


43

Yeniden bağlama harika bir araçtır, ancak en iyi sonucu, ana başlıkta konu dalları için ileri sarma birleştirmeleri oluşturmak için kullandığınızda işe yarar. Örneğin, yeni pencere öğesi dalınızı ana öğeye göre yeniden temel alabilirsiniz:

git checkout add-new-widget
git rebase -i master

Ana dalın ileri sarma birleşimini gerçekleştirmeden önce. Örneğin:

git checkout master
git merge --ff-only add-new-widget

Bunun yararı, geçmişinizde çok fazla karmaşık birleştirme taahhüdü veya birleştirme çatışması olmayacak, çünkü tüm değişiklikleriniz birleştirmeden önce ustanın ucuna yeniden yüklenecek. İkincil bir fayda, yeniden git push --forcekredi vermiş olmanızdır, ancak ana dalda geçmişi bozmadığınız için kullanmak zorunda değilsiniz .

Bu kesinlikle geri ödeme için tek kullanım durumu veya tek iş akışı değil, ama gördüğüm en mantıklı kullanımlarından biri. YMMV.


4
Teşekkürler CG, bence "bunu hızlı ileri birleştirme oluşturmak için kullan" anahtar kelime. Yukarıdaki iki canlı şubem - bir geliştirme dalı ve bir sürüm şubesi - bulunduğum durum için geçerli değil, ancak yalnızca sınırlı bir süre için gerekli olan geçici konu dalları için çok iyi uygulanıyor gibi görünüyor ve daha sonra birleştirildikten sonra silinir. Tekrar teşekkürler.
Roy Truelove

1
Bunu anlıyorum ama asıl soru kalıyor. Sanırım asıl cevap @Fabien Quatravaux
IsmailS

5
Yine de 1.0 şubesini zorla itmeniz gerekecek, değil mi? En azından, işler benim için her zaman böyle olma eğilimindedir. Fabiens yöntemi bunun olmasını engelleyecektir.
joerx

23

@CodeGnome doğru. Master'ı v1.0 dalında yeniden temellendirmemelisiniz, ancak ana üzerinde v1.0 şubesi, bu tüm farkı yaratacaktır.

git checkout -b integrate_patches v1.0
git rebase master
git checkout master
git merge integrate_patches

V1.0'ı işaret eden yeni bir dal oluşturun, bu yeni dalı ana dalın üstüne taşıyın ve ardından V1.0 yamalarının yeni sürümünü ana dala entegre edin. Şunun gibi bir şeyle sonuçlanacaksın:

o [master] [integrate_patches] Another patch on v1.0
o A patch on v1.0
o Another change for the next major release
o Working on the next major release
|  o [v1.0] Another path on v1.0
|  o A patch on v1.0
| /
o Time for the release

Rebase'in bu şekilde kullanılması resmi git dokümantasyonu tarafından tavsiye edilmektedir .

Bence haklısın git push --force: Sadece bir hata yaptıysan ve istemediğin bir şeyi ittiğinde kullanmalısın.


Bence bu, OP'deki spesifik problem için en iyi cevap. Geçici bir birleştirme dalı oluşturursunuz ve bunun üzerinde yeniden temel alırsınız, ardından ana olarak birleştirir ve başlangıç ​​noktasına itersiniz. Geçici şubenin başlangıç ​​noktasına itilmesi gerekmez. Vereceğim tek ek tavsiye, birleştirilmiş / yeniden yazılmış kodun nitelendirilebileceği bir geliştirme veya qa şubesine sahip olmaktır. Nitelendirmeden sonra, bu kod daha sonra yalnızca ff ana ile birleştirilir. Bu, yeterlilik süreciniz çok uzun sürerse, kolay düzeltme yapılmasına olanak tanır. Bu temelde "git akışı" sürecidir.
Javid Jamae

Teşekkürler Fabien, harika cevap. Sadece değişiklikleri entegre etmek isteyen masterve özellik dalının kendisini birleştirmeyi git checkout my-branch; git rebase master; git checkout master; git merge my-branch
önemsemeyen bizler

17

Yeniden basarsanız zorlamanız gerekir ve zaten değişiklikler hakkı yayınladık?

Bir grup geri ödeme kullanıyorum, ancak ya özel bir şeyde yayınlıyorum (örneğin, bir zorlama isteğinin parçası olarak GitHub'daki kendi klonum) ya da ilk kez basmadan önce yeniden tabanlarım.

Bu, yeniden temel aldığınız iş akışının kalbidir, ancak çok fazla zorlamayın: hazır olana kadar yayınlamayın, bastıktan sonra yeniden satış yapmayın.


Teşekkürler Dan. O halde yukarıdakilerin nasıl başarılması gerektiğini bana bildirir misiniz? Bu, yeniden ödemenin geçerli olduğu bir senaryo değil mi?
Roy Truelove

2
Tüm çalışmanızı konu dallarına ayırırsanız, yeniden satış için iyi bir senaryo oluşturur. Sen rebaseyeni Konunuz dalı haline değişiklikleri çekti, ama o şubenin değişiklikleri, size tamamladığımızda mergeana gelişme dalı haline şube geri.
redhotvengeance

1
Sorun, şubeyi yayınlamış olmanızdır - bu nedenle, depoya zorla göndermeniz gerekir. İkisinden birinden vazgeçmelisiniz: yaptığınız gibi yayınlamak veya yeniden satış yapmak. Afedersiniz.
Daniel Pittman

Yeniden bağlama bu senaryoda işe yaramıyor gibi görünüyor. v1.0 bir konu dalı değil, bir sürüm dalı, bu yüzden asla ölmeyecek ve yayınlanması gerekiyor.
Roy Truelove

5

Yanlış bir itmenin sonucu olmayan bu rebase-then-force-push modelinin iyi bir kullanım durumu olduğunu düşünüyorum: birden fazla yerden (bilgisayardan) bir özellik dalı üzerinde kendi başınıza çalışmak. Bunu sık sık yapıyorum, çünkü bazen masaüstümde ofiste ve bazen dizüstü bilgisayarımda evden / müşteri sitesinden çalışıyorum. Ana şubeye ayak uydurmak ve / veya birleştirmeleri daha temiz hale getirmek için ara sıra yeniden ödeme yapmam gerekiyor, ancak aynı zamanda bir makineden başka bir makinede çalışmaya devam etmek için (sadece çektiğim yer) zorla itmem gerekiyor. Dalda çalışan tek ben olduğum sürece, bir cazibe gibi çalışıyor.


2
Aynı iş akışına sahibim (birden çok bilgisayardan / konumdan çalışıyorum). Öyleyse, 'mytopic' adlı bir konu dalı üzerinde çalıştığınızı varsayalım. Her zaman yerel bir atılabilir dalı (bu sadece miytopiğin bir dalı olan) "ana" üzerine yeniden sıraladığınız ve sonra onu tekrar miytopiğe birleştirdiğiniz sürece, asla zorlamanız gerekmez. OP'nin biraz farklı bir senaryosu vardır, bu nedenle böyle bir durumda bir kuvvet itişi gerekli olabilir. Bununla birlikte, OP'nin yanlış yoldan geri döndüğünü düşünüyorum - eğer açıkladığım gibi yaparsa, o zaman hiçbir zorlama gerekmeyecektir.
bwv549

3

İşte kullandığım şey (şube adınızın foobar olduğunu varsayarak ):

git checkout master              # switch to master
git rebase   foobar              # rebase with branch
git merge -s ours origin/master  # do a basic merge -- but this should be empty
git push origin master           # aaand this should work

2
Yeniden kaplama ustası tuhaf görünüyor.
Emil Vikström

2
git
kişiliksiz

1
git merge -s ours origin/<branch>bizim için
Max

0

tl; dr paylaşılan şubelerle birleştirme, tek tek şubelerle yeniden bağlama. --force-with-leasezorlamaya karşı daha güvenli bir alternatiftir ve söz konusu git nirvana'yı gücün yıkıcı doğası olmadan elde etmenize yardımcı olmalıdır.

Çeşitli ekiplerin iş akışları için çalıştığını gördüğüm genel bir kural, mergepaylaşılan dallar (yani, ana veya geliştirme) için kullanmak rebaseve kendi özellik dalınızda çalışırken kullanmaktır . İşte bir özellik dalının tipik bir yaşam döngüsü

git checkout master
git checkout -b new-feature
git commit -am "commit new work"
git push -u origin new-feature
# have code reviewed, run CI, etc.,
# meanwhile master has new commits
git checkout master
git pull
git rebase -i master # -i for interactive rebase allows you to squash intermediate commits
git push --force-with-lease
git merge master

Burada yaptığımız şeyin basit bir İngilizce versiyonu:

  1. Master dışında yeni bir şube oluşturdu
  2. Dalda çalışma tamamlandı ve uzaktan kumandaya gönderildi
  3. ustanın geri dönüşü
  4. İle çalışmayı uzaktan kumandaya itin force-with-lease
  5. çok temiz bir git günlüğü ile ana dalda birleştirme, şubemizin en son ana (paylaşılan dal) ile "yakalanması" için paylaşılan şubemizdeki birden fazla birleşmeden kaynaklanan karmaşayı azaltın

Dördüncü adım GERÇEKTEN önemli ve rebase kullanımını savunmaya başlamamın ana nedenlerinden biri. force-with-leaseherhangi bir yeni kaydetme eklenip eklenmediğini görmek için uzaktan kumandayı kontrol eder. Eğer seningit push yıkıcı olduğu kanıtlanmış oldu o itmek olmaz!

Umarım bu, yeniden taban kullanmak için daha fazla güven verir.

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.