ana dal ve 'köken / usta' birbirinden ayrıldı, 'dallar' nasıl kesilir?


964

Bir şekilde efendim ve kökenim / efendi şubem birbirinden ayrıldı.
Aslında ayrılmalarını istemiyorum.

Bu farklılıkları nasıl görebilir ve 'birleştirebilirim'?


2
saparak ne demek istiyorsun? Efendinizi ittikten sonra yeniden ısrar ediyor musunuz?
hasen

13
"Şubeniz ve 'başlangıç ​​noktanız / üstatınız' ayrıldı, # ve her biri sırasıyla 1 ve 1 farklı taahhüt (ler) e sahip.
Frank

Cevabımı bu "yönlendirilmiş" uyarı mesajını yansıtacak şekilde güncelledim.
VonC

Başka bir soruya kabul edilen cevap, bunun devreye girebileceği bazı durumları çözmede de yardımcı olabilir (örneğin, ustanızı hareket ettirmeye çalışıyorsunuz, ancak zaten itilmişti): stackoverflow.com/questions/2862590/…
lindes

8

Yanıtlar:


1014

Farklılıkları aşağıdakilerle inceleyebilirsiniz :

git log HEAD..origin/master

önce çekerek (+ birleştirme getirme) (ayrıca bkz "her zaman belirli bir şubesinden çekmeye sen budala nasıl alabilirim?" )


Şöyle bir mesajınız olduğunda:

"Şubeniz ve 'başlangıç ​​noktanız / ustanız' birbirinden ayrıldı, # ve her biri sırasıyla 1 ve 1 farklı taahhüde sahip."

, güncellemenizorigin gerekip gerekmediğini kontrol edin . Eğer originup-to-date, sonra bazı kaydedilmesini itilmiş originyerel olarak kendi kaydedilmesini yapılmış ise başka repo.

... o ---- o ---- A ---- B  origin/master (upstream work)
                   \
                    C  master (your work)

C taahhüdünü A taahhüdüne dayandırdınız, çünkü o zamanlar yukarı akımdan aldığınız en son işti.

Bununla birlikte, kökene geri dönmeye çalışmadan önce, bir başkası B'yi zorladı.
Geliştirme tarihi ayrı yollara ayrıldı.

Daha sonra birleştirebilir veya yeniden pazarlayabilirsiniz. Ayrıntılar için Pro Git: Git Branching - Rebasing konusuna bakın .

Birleştirmek

Git merge komutunu kullanın:

$ git merge origin/master

Bu Git'e değişiklikleri origin/masterçalışmalarınıza entegre etmesini ve bir birleştirme taahhüdü oluşturmasını söyler .
Tarihin grafiği şimdi şöyle:

... o ---- o ---- A ---- B  origin/master (upstream work)
                   \      \
                    C ---- M  master (your work)

Yeni birleştirme olan M taahhüdü, her biri bu taahhütte depolanan içeriğe götüren bir geliştirme yolunu temsil eden iki ebeveyne sahiptir.

M'nin arkasındaki geçmişin artık doğrusal olmadığını unutmayın.

rebase

Git rebase komutunu kullanın:

$ git rebase origin/master

Bu, Git'e C komutunu (işinizi) A yerine B yerine
koyduğunuzu söyler. CVS ve Subversion kullanıcıları, taahhüt etmeden önce güncellendiklerinde, yukarı akıştaki işlerin üstünde yerel değişikliklerini rutin olarak yeniden oluştururlar.
Git, kesinleştirme ve yeniden pazarlama adımları arasında açık bir ayrım ekler.

Tarihin grafiği şimdi şöyle:

... o ---- o ---- A ---- B  origin/master (upstream work)
                          \
                           C'  master (your work)

C Komutu, git rebase komutu tarafından oluşturulan yeni bir komuttur.
C'den iki şekilde farklıdır:

  1. Farklı bir tarihi var: A yerine B.
  2. İçeriği hem B hem de C'deki değişiklikleri açıklar; birleştirme örneğindeki M ile aynıdır.

C 'nin arkasındaki tarihin hala doğrusal olduğunu unutmayın.
Şimdilik sadece doğrusal geçmişe izin vermeyi (şimdilik) seçtik cmake.org/cmake.git.
Bu yaklaşım, daha önce kullanılan CVS tabanlı iş akışını korur ve geçişi kolaylaştırabilir.
C 'yi depomuza itme girişimi işe yarayacaktır (izinleriniz olduğunu ve yeniden basarken hiç kimsenin itmediğini varsayarak).

Git pull komutu, başlangıç ​​noktasından getirme ve üzerinde yerel çalışmayı yeniden oluşturma için kısa bir yol sağlar:

$ git pull --rebase

Bu, yukarıdaki getirme ve yeniden oluşturma adımlarını tek bir komutta birleştirir.


5
Aynı sorunu ararken bunu buldum, neden 'git reset --hard HEAD' sorunu çözmediğini açıklayabilir misiniz?
Neth

12
@Neth: çünkü aşamalı değişikliklerle ilgili değildir (yani dizinde mevcut olan ancak henüz taahhüt edilmeyen değişiklikler), ancak yerel taahhütlerle ilgili (uzaktan kumandadaki mevcut taahhütlerden farklıdır). git reset --hard HEADyalnızca dizin oluşturulmuş taahhütlü olmayan değişiklikleri kaldıracak ve yerel ve uzak taahhütler arasındaki farkları uzlaştırmak için hiçbir şey yapmayacaktır . Yalnızca bir birleştirme veya bir geri ödeme iki komisyon kümesini (yerel olan ve uzak olan) bir araya getirecektir.
VonC

4
Vay be, bu harika yanıt için teşekkürler. Biz yanlışlıkla "--rebase" olmadan bir "git pull" yapmıştı ve "git rebase origin / master" sadece düzeltme oldu!
mrooney

3
Nasıl olur - Sadece yerel değişikliklerimi yoksaymak / dökümü ve uzaktan kumandanın bulunduğu yerel şubemle olmak istiyorum? Başka bir deyişle, örneğinize masterişaret etmek istiyorum B.
CygnusX1

23
@ CygnusX1, git reset --hard origin/masteraşağıdaki cevapta belirtildiği gibi olacaktır : stackoverflow.com/a/8476004/6309
VonC

725

Bunu aldım ve yukarıdaki yanıtları okuduktan sonra bile buna neyin sebep olduğu konusunda gizem duydum. Benim çözümüm

git reset --hard origin/master

Daha sonra bu sadece (yerel) master kopyamı (berbat olduğunu varsayıyorum) (uzak) orijin / master ile gösterildiği gibi doğru noktaya sıfırlar.

UYARI : Henüz zorlanmayan tüm değişiklikleri kaybedeceksiniz origin/master.


21
evet, aptallar seçeneği gibi geliyor, ama gerçek bir tehlike yoksa ve hızlı bir düzeltme için buradaysanız - bu işe
yarar

7
Bunun için önce ana dalda olması gerekir ("git checkout master").
blueyed

Bu, başlangıçtan en son geldiğimde bir kez başıma geldi, daha sonra bir başkası, önceki menşe taahhüdünün geri dönmesine neden olan bir başlangıç ​​noktasına zorlama yaptı. Bu yüzden yerel şubem geri döndü ve kökten en son çekmeye çalıştığımda birleşmem gerektiğini söylüyordu. Bu durumda, sorunun kökeni önceden düzeltilmiş olduğundan --hard origin / (branch) 'u sıfırlamak mantıklıydı.
Landon Poch

96
Muhtemelen kullanıcıları, bunun henüz başlamamış olan tüm değişiklikleri kaybetmelerine neden olacağı konusunda uyarmalısınız
Pedro Loureiro

6
@PedroLoureiro Taahhütler gerçekten kaybolur, yine de taahhütleri bulabilir git reflogveya içinde görebilirsiniz gitk --all. Ancak, elbette, sert sıfırlama bir rebase'den başka bir şeydir.
sebkraemer

52
git pull --rebase origin/master 

size çoğu zaman yardımcı olabilecek tek bir komuttur.

Düzenleme: Taahhütleri başlangıç ​​/ ana konumdan alır ve değişikliklerinizi yeni çekilen dal geçmişine uygular.


89
Lütfen komutun ne yaptığını
belirtin

1
Herhangi bir sorun yoksa, master / master tüm değişiklikleri içeren master'ınızla sona erecektir, ayrıca tüm yerel taahhütleriniz bunun üzerinde tekrarlanacaktır. Bana iyi geliyor.
Philipp Claßen

7
Dışında gerçek farklılıklar ve sizi durdurulmuş bir rebase bırakır.
ffledgling

Bu bir hata verir: hata: Değişiklikler birleştirilemedi. Düzeltme eki
0024'de

32

Ben çalıştığında bu durumun içinde buldum rebase uzak dalı takip ettiğini bir şube ve ben efendi üzerine rebase çalışıyordu. Eğer rebase çalışırsanız bu senaryoda, büyük olasılıkla şube bulacaksınız ayrıldığı ve git nubees için değil bir karmaşa yaratabilir!

Diyelim ki ustadan dallanmış olan my_remote_tracking_branch şubesindesiniz

$ git status

# Dalda my_remote_tracking_branch

taahhüt edilecek hiçbir şey yok (çalışma dizini temiz)

Ve şimdi efendiden şu şekilde geri çekmeye çalışıyorsunuz:

git rebase ustası

ŞİMDİ DUR ve kendinize biraz sorundan kurtulun! Bunun yerine, birleştirmeyi şu şekilde kullanın:

git merge master

Evet, şubenizde ekstra taahhütlerle sonuçlanacaksınız. Ancak "ayrışmasız" dallara katılmıyorsanız, bu yeniden temellendirmekten çok daha akıcı bir iş akışı olacaktır. Çok daha ayrıntılı bir açıklama için bu bloga bakın .

Öte yandan, şubeniz sadece yerel bir şubeyse (yani henüz herhangi bir uzaktan kumandaya itilmemişse) kesinlikle bir rebase yapmalısınız (ve bu durumda şubeniz ayrılmayacaktır ).

Bu okuma Şimdi eğer zaten çünkü olan bir senaryo böyle rebase nedeniyle, geri son alabilirsiniz kullanarak (un-ayrıldığı halde yani) kökenden taahhüt "ayrıldığı" in:

git reset --hard origin / my_remote_tracking_branch


5
Temel kural, yeniden rebasebastığınız şube yayınlanmadıysa (ve başkaları tarafından kullanılmadıysa) kullanmaktır. Aksi takdirde kullanın merge. Zaten yayınlanmış (ve kullanılmış) şubeleri yeniden oluşturursanız, şubenizi kullanan her geliştiricideki geçmişi yeniden yazmak için bir komployu koordine etmeniz gerekir.
Mikko Rantalainen

1
Ne yazık ki yapmadan önce bu mesajı okumadım git rebase master...
Vitaly Isaev

Eğer 'foobar' dalında git rebase master yaparsam o zaman git push -f yapana kadar teknik olarak foobar orijin / foobardan ayrılır, değil mi?
relipse


1
git reset --hard origin/my_remote_tracking_branchgerçekten işe
yarayan

24

Benim durumumda, yönlendirilmiş mesaja neden olmak için yaptığım şey: Yaptımgit push ama sonra yaptımgit commit --amend taahhüt mesajına bir şey eklemek için . Sonra başka bir taahhütte bulundum.

Yani benim durumumda bu sadece orijin / üstatın güncel olmadığı anlamına geliyordu. Başka hiç kimsenin başlangıç ​​noktasına / efendisine dokunmadığını bildiğim için, düzeltme önemsizdi: git push -f ( -fkuvvet demek)


8
git push -fÖnceden taahhüt edilen ve kaynak haline getirilen değişikliklerin üzerine yazmak için + 1'leyin. Eminim ki hiç kimse depoya dokunmadı.
zacharydl

4
Çok riskli bir komut. Lütfen komutun risk faktörü ile ilgili kısa bir bilgi yazın.
J4cK

1
@Trickster: Riski daha önce tarif etmiştim: "Başka hiç kimsenin orijin / ustaya dokunmadığını bildiğim için". İnanıyorum ki, bu durumda, bu riskli bir komut değildir.
Darren Cook

1
Birisi ustayı taahhüt ederse ve sonra bir kişi git push -f komutunu çalıştırırsa, yüksek riskli komuttur
J4cK

11

Benim durumumda değişiklikler yaptım origin/master ve sonra bunu yapmam gerektiğini fark etti :-( Bu, yerel değişikliklerin bir alt ağaçta olması nedeniyle karmaşıktı. değişiklikleri (SourceTree kullanarak) ve sonra "ıraksama mesajı" aldım.

Yerel olarak dağınıklığı düzelttikten sonra (ayrıntılar burada önemli değil) uzak origin/masterşubeye tekrar "geri gitmek" istedim, böylece yerel ile mastertekrar senkronize olacaktı . Benim durumumdaki çözüm:

git push origin master -f

Not -f(kuvvet) anahtarı. Bu origin/master, yanlışlıkla itilmiş olan "kötü değişiklikleri" sildi ve şimdi yerel ve uzak dallar senkronize durumda.

Bunun potansiyel olarak yıkıcı bir işlem olduğunu lütfen unutmayın, bu nedenle yalnızca uzak ana makinenin zamanında "geri taşındığından"% 100 emin olduğunuzda gerçekleştirin.


Her zaman yararlıdır ama kesinlikle soruya cevap vermez.
Thibault D.

1
@ThibaultD. olmasa bile, tam da aradığım şey buydu.
Neil Chowdhury

Ben alıyorum You are not allowed to force push code to a protected branch on this project.. Çatalıma zorlamaya çalışıyorum.
BanAnanas


5

Burada çok sayıda cevap olduğunu biliyorum, ama bence git reset --soft HEAD~1bazı dikkatleri hak ediyor, çünkü ayrışmış durumu çözerken son yerel (itilmemiş) taahhütte değişiklikler yapmanıza izin veriyor . Bence bu, çekmekten daha çok yönlü bir çözüm rebase, çünkü yerel taahhüt gözden geçirilebilir ve hatta başka bir şubeye taşınabilir.

Anahtar --softsert yerine kullanmaktır --hard. 1'den fazla taahhüt varsa, bir varyasyon HEAD~xçalışmalıdır. İşte durumumu çözen tüm adımlar (uzaktan 1 tane yerel taahhüt ve 8 tane taahhütte bulundum):

1) git reset --soft HEAD~1 Yerel taahhüdü geri almak. Sonraki adımlar için SourceTree arabirimini kullandım, ancak aşağıdaki komutların da çalışması gerektiğini düşünüyorum:

2) git stash 1'den stash değişikliklerine). Artık tüm değişiklikler güvende ve artık bir farklılık yok.

3) git pull uzaktan değişiklikleri almak için.

4) git stash pop veya git stash applyistendiği takdirde yeni bir taahhüt takip eden son saklama değişikliklerini uygulamak. Bu adım, 2) ile birlikte yerel taahhütteki değişiklikleri çöpe atmak istediğinizde isteğe bağlıdır . Ayrıca, başka bir şubeye katılmak istediğinizde, bu adım istenen şubeye geçildikten sonra yapılmalıdır.


Aslında, bu günlerde, pull --rebaseyine de otomatik olarak saklanırdı. stackoverflow.com/a/30209750/6309
VonC

4

Farklılıkları görüntülemek için:

git difftool --dir-diff master origin/master

Bu, iki dal arasındaki değişiklikleri veya farklılıkları gösterecektir. Araxis'te (En sevdiğim) bir klasör farklı stilinde görüntüler. Değiştirilen dosyaların her biri gösteriliyor. Daha sonra dosyadaki değişikliklerin ayrıntılarını görmek için bir dosyaya tıklayabilirim.


1
Git-dir'in ilginç kullanımı: +1
VonC

3

Benim durumumda bu, çatışma çözümlememi yapmamamdan kaynaklandı.

Sorun, git pullkomutun çalıştırılması nedeniyle oluştu . Kökenimdeki değişiklikler, çözdüğüm yerel repo ile çatışmaya yol açtı. Ancak, onları taahhüt etmedim. Bu noktada çözüm, değişiklikleri uygulamaktır ( git commitçözülen dosya)

Çakışmayı git statusçözdüğünüzden beri bazı dosyaları değiştirdiyseniz, komut yerel değişiklikleri işaretsiz yerel değişiklikler olarak gösterir ve çözünürlüğü aşamalı yerel değişiklikler olarak gösterir. Bu, ilk önce birleştirme git commitişlemindeki değişiklikleri gerçekleştirerek, ardından normal olmayan değişiklikleri (örneğin git commit -a) ekleyerek ve gerçekleştirerek düzgün bir şekilde çözülebilir .


0

Zaten taahhüt itti, son taahhüt mesajı düzenlemeye çalışırken aynı mesajı vardı: git commit --amend -m "New message" kullanarak değişiklikleri itti zaman git push --force-with-lease repo_name branch_name hiçbir sorun yoktu.


0

A dalına dayalı bir dal oluşturduğumda bu sorunla karşılaştım.

git checkout -b a

ve sonra a dalının yukarı akışını B

git branch -u origin/B

Sonra yukarıdaki hata mesajını aldım.

Bu sorunu benim için çözmenin bir yolu,

  • Şubeyi silme a
  • Tarafından yeni bir şube oluşturun b
git checkout -b b origin/B
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.