Git push özellik dalı yeniden paylaşımından sonra reddedildi


918

Tamam, bunun basit bir git senaryosu olduğunu düşündüm, ne eksik?

Bir masterşubem ve bir featureşubem var. Biraz master, biraz featuresonra da biraz daha çalışıyorum master. Ben böyle bir şey ile sonuçlanır (sözlükbilimsel düzen taahhütlerin sırasını ima eder):

A--B--C------F--G  (master)
       \    
        D--E  (feature)

git push origin masterUzaktan kumandayı mastergüncel tutmak ya da git push origin feature(açıkken feature) işim için uzaktan yedekleme yapmak için hiçbir sorunum yok feature. Şimdiye kadar iyiyiz.

Ama şimdi ustalıktaki taahhütlerin featureüstüne geri dönmek istiyorum F--G, bu yüzden ben git checkout featureve git rebase master. Hala iyi. Şimdi elimizde:

A--B--C------F--G  (master)
                 \
                  D'--E'  (feature)

Sorun: yedekleme istediğim an yeni rebased featureile kollara git push origin feature, itme reddedilir ağaç rebasing nedeniyle değişti beri. Bu sadece ile çözülebilirgit push --force origin feature .

--forceİhtiyacım olduğundan emin olmadan kullanmaktan nefret ediyorum . Peki, buna ihtiyacım var mı? Yeniden bastırma , bir sonrakinin tam olması gerektiği anlamına mı geliyor ?push--force

Bu özellik dalı başka devs ile paylaşılmaz, bu yüzden zorla itme ile fiili bir sorunum yok , herhangi bir veri kaybetmeyeceğim, soru daha kavramsal.

Yanıtlar:


681

Sorun şu ki git push, uzak dalın yerel dalınıza hızlı bir şekilde iletilebileceği varsayılmaktadır, yani yerel ve uzak dallar arasındaki tüm fark yereldir ve sonunda şu şekilde bazı yeni taahhütler vardır:

Z--X--R         <- origin/some-branch (can be fast-forwarded to Y commit)
       \        
        T--Y    <- some-branch

git rebaseD ve E komutlarını gerçekleştirdiğinizde yeni tabana uygulanır ve yeni komisyonlar oluşturulur. Bu, rebase'den sonra böyle bir şeyiniz olduğu anlamına gelir:

A--B--C------F--G--D'--E'   <- feature-branch
       \  
        D--E                <- origin/feature-branch

Bu durumda uzak şube yerel olarak hızlı bir şekilde iletilemez. Yine de, teorik olarak yerel şube uzaktan birleştirilebilir (bu durumda açıkçası buna ihtiyacınız yoktur), ancakgit push yalnızca hızlı ileri birleştirme gerçekleştirirse hata ve hata yapar.

Ve --forceseçeneğin yaptığı şey, uzak dalın durumunu yok saymak ve onu içine attığınız taahhüde ayarlamaktır. Yani git push --force origin feature-branchsadece origin/feature-branchyerel ile geçersiz kılar feature-branch.

Bence, özellik dallarını yeniden temel almak masterve onları uzak depoya geri zorlamak, o dalda çalışan tek kişi olduğunuz sürece sorun olmaz.


67
Dürüst olmak gerekirse, özellik dalının orijinal versiyonunu yeniden temelli hale getirmek ve birleştirmek, tüm yeniden basma fikrini ortadan kaldırır.
KL-7

24
Belki sizi doğru anlamadım, ancak özellik dalını çekerseniz, yeni ana dalda yeniden adlandırın, zorlamadan geri itemezsiniz, çünkü özellik dalının uzak sürümü yeni ürününüze hızlı bir şekilde yönlendirilemez özellik dalının (yeniden temelli) sürümü. OP'nin sorusunda tam olarak tanımladığı şey buydu. Yeniden bastırma işleminden sonra, ancak itmeden önce git pull feature-branch, bu çekme işlemi yeni bir birleştirme taahhüdü oluşturur (özellik dalının uzak ve yerel sürümlerini birleştirerek). Böylece ya yeniden bastıktan sonra gereksiz bir birleşme yaşarsınız ya da itersiniz --force.
KL-7

6
Ah, sanırım anladım. Mark Longair'in cevabı ile aynı yaklaşımı tanımlıyorsunuz. Ancak birleştirme taahhüdü oluşturur. Bazı durumlarda yararlı olabilir, ancak push --forceherhangi bir birleştirme taahhüdü olmadan tarihi taahhütleri doğrusal tutmak için çoğunlukla kendi özellik dallarında rebase kullanıyorum (bu nedenle bir sorun değildir).
KL-7

11
“Force-push” ile ilgili sorun, gerçekten “gevşek şeyler” (önceki taahhütler) yapabilmenizdir, herhangi bir Versiyon Kontrol Sisteminde normalde ASLA mümkün olmaması gereken bir şey ➪ Bu nedenle en az bir „master-ish“ şubesi olmalıdır potansiyel hasarı sınırlamak için zorla itmeyi kabul etmeme ayarları . (Aşağıdakilerden herhangi birini belirtin: huysuz / işten kovulmuş çalışanlar, kendi aptallığı, yorgun ve aşırı çalışan 'kararlar' ...).
Frank Nocke

13
--force-with-lease@hardev'in önerdiği gibi harika bir seçenektir
augustorsouza

465

-F veya --force kullanmak yerine geliştiriciler

--force-with-lease

Neden? Çünkü uzak dalı kesinlikle iyi bir fikir olan değişiklikler açısından kontrol eder. James ve Lisa'nın aynı özellik dalında çalıştıklarını ve Lisa'nın bir taahhütte bulunduğunu düşünelim. James şimdi yerel şubesine yeniden basmaya çalışıyor ve itmeye çalışırken reddediliyor. Elbette James bunun yeniden tabandan kaynaklandığını ve --force kullandığını ve Lisa'nın tüm değişikliklerini yeniden yazacağını düşünüyor. James - kiralama işlemiyle birlikte kullansaydı, başkası tarafından yapılan taahhütler olduğuna dair bir uyarı alırdı. Bir kimsenin, bir rebase'den sonra iterken neden --force yerine - force kullanacağını anlamıyorum.


33
Harika bir açıklama. git push --force-with-leasebeni bir grup kurtardı.
ckib16

5
Bu yararlı bir yorum, ancak gerçekten sorunun cevabı değil.
Dallin

4
Bu cevaptır, ustalaşmaya / geliştirmeye yeniden başlamak bir sorun yaratır, tam da bu yüzden - kiralama ile kuvvet var.
Tamir Daniely

3
Bu kabul edilen cevap olmalı. Tam olarak açıklanan sorunu çözer - bu arada başka biri taahhüt ederse zorlamadan zorlama.
Luzian

3
Bence hem kabul edilen cevap hem de bu soruya değiniyor. Kabul edilen cevap neden zorlamanız gerektiğini açıklar. Bu da neden --force-with-leasekullanma endişesini --force
giderdiğini

47

Bunun yerine "ödeme -b" kullanmak ve anlamak daha kolaydır.

git checkout myFeature
git rebase master
git push origin --delete myFeature
git push origin myFeature

sildiğinizde, farklı SHA Kimliği içeren bir çıkış dalını içeri itmeyi önlersiniz. Bu durumda yalnızca uzak dalı siliyorum.


6
Bu, özellikle ekibinizde tüm git push - force komutlarını reddeden bir git kancası varsa harika çalışır.
Ryan Thames

1
iyi çalıştığı için teşekkür ederim. İşte daha iyi anlamak için okuduğum daha fazla ayrıntı. Bu, zorla itme yapmak istemediğinizde veya yapamadığınızda çok yararlıdır. Uzak Dalları Silme ve Yeniden
İsimlendirme

5
Bu aynı sonuca sahiptir push --force, bu yüzden sadece git repo önleme etrafında almak için bir yoldur --force. Bu nedenle, bunun hiç iyi bir fikir olduğunu düşünmüyorum - ya repo izin veriyor push --forceya da iyi bir nedenden dolayı onu devre dışı bırakıyor. Nabi'nin cevabı, --forceuzak depoda devre dışı bırakıldıysa daha uygundur , çünkü diğer geliştiricilerin taahhütlerini kaybetme veya başka sorunlara neden olma riski yoktur.
Logan Pickup

19

Bunun bir çözümü msysGit en olanı yapmak rebasing birleştirme eski kafasında rebase, birleştirme sonrası - Senaryo yapar featureile -s ours. Sonuç grafiği ile sonuçlanırsınız:

A--B--C------F--G (master)
       \         \
        \         D'--E' (feature)
         \           /
          \       --
           \    /
            D--E (old-feature)

... ve featureçabucak ilerlemeniz hızlı ilerleyecektir.

Başka bir deyişle, şunları yapabilirsiniz:

git checkout feature
git branch old-feature
git rebase master
git merge -s ours old-feature
git push origin feature

(Test edilmedi, ama bence bu doğru ...)


26
En yaygın nedeninin git rebase( masterözellik dalınıza geri dönmek yerine ) temiz lineer taahhüt geçmişi yapmak olduğuna inanıyorum . Yaklaşımınızla tarih daha da kötüleşir. Ve yeniden basma, önceki sürümlerine referans vermeden yeni taahhütler oluşturduğundan, bu birleştirme sonucunun yeterli olacağından bile emin değilim.
KL-7

6
@ KL-7: Bütün mesele merge -s oursyapay olarak önceki sürüme bir üst referans eklemesidir. Elbette, tarih temiz görünmüyor, ancak sorgulayıcı, featuredalın zorlanmasını zorlamaktan özellikle rahatsız görünüyor ve bu da etrafta dolaşıyor. Rebase yapmak istiyorsanız, aşağı yukarı biri veya diğeri. :) Daha genel olarak, msysgit projesinin bunu yapmasının ilginç olduğunu düşünüyorum ....
Mark Longair

@ KL-7: Bu arada, cevabınızı + 1'ledim, ki bu doğru olanı - sadece bunun da ilginç olabileceğini düşündüm.
Mark Longair

En azından benim için kesinlikle ilginç. Teşekkür ederim. Daha önce oursstrateji gördüm ama bunun sadece çatışma durumumuz için, şubemizdeki değişiklikleri kullanarak bunları otomatik olarak çözerek geçerli olduğunu düşündüm. Farklı çalıştığı ortaya çıktı. Ve bu şekilde çalışmak, yeniden temelli sürüme ihtiyacınız varsa (örneğin, repo bakımcının temiz bir şekilde uygulayabilmesi için master) çok yararlıdır, ancak kuvvet itmekten kaçınmak istiyorsanız (bazı nedenlerden ötürü özellik dalınızı kullanıyorsanız).
KL-7

15

Bu dalda yalnızca bir geliştirici olduğu (veya yeniden oluşturulduktan sonra) kökeni / özelliğiyle satır içi olmayan durum olabilir veya olmayabilir.

Bu nedenle, aşağıdaki diziyi kullanmanızı öneririm:

git rebase master
git checkout -b feature_branch_2
git push origin feature_branch_2

Evet, yeni şube, bunu bir --force olmadan çözmeli, ki bu genellikle büyük bir dezavantaj.


3
Söylediğim için üzgünüm ama: Mevcut olanları zorla geçersiz kılmaktan kaçınmak için “şube oluşturmaya devam et”, “yalnız özellik geliştiricilere” (kim geçersiz kılabilir) ne de bir özellik dalında çalışan birden fazla kişiye (o branşın “artışını” bildirip (hareket etmek için millet). - Daha çok bir versiyonlama sistemi içinde manuel versiyonlama (“thesis_00.doc, thesis_01.doc, ...”) gibi ...
Frank Nocke

2
Ayrıca, bir şube adında açılmış bir github PR'ınız varsa, ittiğiniz yeni şube adı için yeni bir PR oluşturmanız gerekir.
gprasant

1
@frankee Deneyimlerime göre yarı doğru. Yalnız bir geliştirici için, evet, sadece zorla itmek yeterince kolaydır, ancak daha sonra sizi ısırabilecek bir alışkanlıktır. + yeni bir geliştirici katıldı mı? veya belki --hard reset kullanmayan bazı CI sistemleri? işbirliği yapan bir ekip için, yeni şube adının iletilmesi yeterince kolay olduğunu düşünüyorum, bu da kolayca bir ekip için + yazılabilir, yerel olarak veya şube günlük çalışmaya hazır değilken birleşmeye hazır olduğunda öneririm , fazladan taahhüt sonuç olarak rebase / merge çakışmalarıyla uğraşmaktan daha az zordur.
JAR.JAR.beans

PR için @gprasant, yine, bunun rebase için yanlış olacağını düşünüyorum, aslında PR düzeltmeleri ile tek taahhütleri görmek istiyorum. Rebase (squash) ancak daha sonra ustalaşmanın birleştirilmesinin bir parçası olarak ve halkla ilişkiler tamamlandığında ve hazır olduğunda gerçekleşmelidir (bu nedenle yeni halkla ilişkiler açılması gerekmez).
JAR.JAR.beans

13

Güç zorlamasından kaçınmanın yolu, yeni bir dal oluşturmak ve bu yeni dal üzerinde devam etmek ve bazı istikrarlardan sonra, yeniden temel alınan eski dalı kaldırmak:

  • Teslim alınan şubeyi yerel olarak yeniden adlandırma
  • Yeniden oluşturulmuş şubeden yeni bir şubeye dallanma
  • Bu dalı yeni bir şube olarak uzaktan kumandaya itmek. ve uzaktan kumandadaki eski şubeyi silme

1
Neden bu seçenek için aşk yok? Kesinlikle en temiz, en basit, en güvenli.
cdmo

Şube adını izleyen yaklaşık 200 sistemim olduğu ve görev için belirli bir isim olması gerektiği için ve şube adlarını yapmaya başlarsam her itme fikrimi kaybedeceğim.
Tamir Daniely

@TamirDaniely Denemedim, ancak yeni şubeyi aynı eski adla itmeden ve itmeden önce eski şubeyi (uzaktan) silmek sorunu çözüyor mu?
Nabi

2
@Nabi Bu tam olarak - kiralama ile zorlamanın yaptığı şeydir, ancak aynı zamanda sizin olmayan yeni taahhütlerin olmadığını doğrular.
Tamir Daniely

12

Diğerleri sorunuzu yanıtladı. Bir dalı yeniden temellendirirseniz, o dalı zorlamaya zorlamanız gerekir.

Rebase ve paylaşılan bir depo genellikle anlaşılmaz. Bu yeniden yazma tarihi. Diğerleri bu dalı kullanıyorsa veya o daldan dallanmışsa, rebase oldukça tatsız olacaktır.

Genel olarak, rebase yerel şube yönetimi için iyi çalışır. Uzaktan şube yönetimi en iyi şekilde açık birleştirme (--no-ff) ile çalışır.

Ayrıca master'ı bir özellik dalında birleştirmekten de kaçınırız. Bunun yerine, master yapmak için yeni bir şube adı ile yeniden temellendiriyoruz (örneğin, bir sürüm soneki eklemek). Bu, paylaşılan depoya yeniden bastırma sorununu önler.


5
Lütfen bir örnek ekleyebilir misiniz?
Thermech

8

Daldaki a ile git merge masterilgili sorun nedir feature? Bu, ana işi şubeden ayrı tutarken, yaptığınız işi koruyacaktır.

A--B--C------F--G
       \         \
        D--E------H

Düzenleme: Ah üzgünüm sorun bildirimi okumadım. Yaptığınız gibi güç kullanmanız gerekir rebase. Geçmişi değiştiren tüm komutların --forcebağımsız değişkene ihtiyacı olacaktır . Bu, işinizi kaybetmenizi (eski Dve Ekaybolacak) önleyecek bir arızadır .

Böylece git rebaseağacın nasıl göründüğünü gerçekleştirdiniz (kısmen adlandırılmış bir dalda Dve kısmen gizli olmasa da E):

A--B--C------F--G
       \         \
        D--E      D'--E'

Böylece, yeni featuredalınızı (içinde D've E'içinde) itmeye çalışırken , kaybedersiniz Dve E.


3
Bunda yanlış bir şey yok ve işe yarayacağını biliyorum. Sadece ihtiyacım olan şey değil. Dediğim gibi, soru pratik olmaktan daha kavramsal.
Yuval Adam

4

Benim için aşağıdaki kolay adımlar işe yarıyor:

1. git checkout myFeature
2. git rebase master
3. git push --force-with-lease
4. git branch -f master HEAD
5. git checkout master
6. git pull

Yukarıdakilerin tümünü yaptıktan sonra, aşağıdaki komutu da uygulayarak myFeature dalını silebiliriz:

git push origin --delete myFeature

3

Aşağıdakiler benim için çalışıyor:

git push -f origin branch_name

ve hiçbir kodumu kaldırmaz.

Ancak, bundan kaçınmak istiyorsanız, aşağıdakileri yapabilirsiniz:

git checkout master
git pull --rebase
git checkout -b new_branch_name

o zaman tüm taahhütlerinizi yeni şubeye kiralayabilirsiniz. git cherry-pick COMMIT ID ve sonra yeni dalınızı itin.


5
-fiçin bir takma addır --force.
epochengine

1

OP sorunu anladığı gibi, daha güzel bir çözüm arar ...

Uygulama olarak buna ne dersiniz?

  • Gerçek özellik geliştirme dalına sahip olun (asla yeniden bastırma ve zorlamadığınız, böylece özellik geliştiricileriniz sizden nefret etmiyor). Burada, düzenli olarak bu değişiklikleri anadan birleştirme ile yakalayın. Messier tarihi , evet, ama hayat kolaydır ve hiç kimse işine karışmaz.

  • İkinci bir özellik geliştirme dalına sahip olun, burada bir özellik takım üyesi düzenli olarak tüm özellik taahhütlerini, gerçekten de yeniden temelli, gerçekten zorlamaya iter. Yani neredeyse temiz, oldukça yeni bir ustalık taahhüdüne dayanıyor. Özellik tamamlandığında, o dalı master'ın üzerine itin.

Bu yöntem için zaten bir kalıp adı olabilir.

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.