Git'in dallanma karmaşıklığı konusunda yeniyim. Her zaman tek bir dal üzerinde çalışıyorum ve değişiklikleri işliyorum ve ardından periyodik olarak uzak kaynağıma itiyorum.
Geçenlerde bir yerde, bazı dosyaları commit hazırlama aşamasından çıkarmak için sıfırladım ve daha sonra birkaç yeni yerel commit'ten kurtulmak için bir `rebase -i' yaptım. Şimdi tam olarak anlayamadığım bir durumdayım.
Çalışma alanımda, `git günlüğü' tam olarak beklediğim şeyi gösteriyor - gitmesini istemediğim taahhütlerle doğru trendeyim ve orada yenileri var, vb.
Ama az önce uzaktaki depoya gönderdim ve oradakiler farklı-- yeniden düzenlemede öldürdüğüm birkaç değişiklik gönderildi ve yerel olarak işlenen yenileri orada değil.
Sanırım "master/origin" HEAD'den ayrılmış, ancak bunun ne anlama geldiği, komut satırı araçlarıyla nasıl görselleştirileceği ve nasıl düzeltileceği konusunda %100 net değilim.
Öncelikle, HEAD'in ne olduğunu ve ayrıldığında ne anlama geldiğini açıklığa kavuşturalım.
HEAD, o anda kontrol edilen commit'in sembolik adıdır. HEAD ayrılmadığında ("normal"1 durum: kontrol edilmiş bir dalınız var), HEAD aslında bir dalın "ref "sine işaret eder ve dal da commit'e işaret eder. HEAD böylece bir dala "eklenir". Yeni bir commit yaptığınızda, HEAD'in işaret ettiği dal yeni commit'i işaret edecek şekilde güncellenir. HEAD sadece dalı işaret ettiği için otomatik olarak onu takip eder.
git symbolic-ref HEAD
, refs/heads/master
sonucunu verir
"master" adlı dal kontrol edilir.git rev-parse refs/heads/master
yield 17a02998078923f2d62811326d130de991d1a95a
Bu işlem, ana dalın geçerli ucu veya "başı "dır.git rev-parse HEAD
ayrıca 17a02998078923f2d62811326d130de991d1a95a
sonucunu verir
"Sembolik hakem" olmanın anlamı budur. Başka bir referans aracılığıyla bir nesneye işaret eder.HEAD→
refs/heads/master→
17a02998078923f2d62811326d130de991d1a95a` var
HEAD ayrıldığında, bir dal aracılığıyla dolaylı olarak bir işleme işaret etmek yerine doğrudan bir işleme işaret eder. Ayrılmış bir HEAD'i isimsiz bir dal üzerindeymiş gibi düşünebilirsiniz.
git symbolic-ref HEAD
, fatal: ref HEAD is not a symbolic ref
ile başarısız oluyorgit rev-parse HEAD
çıktısı 17a02998078923f2d62811326d130de991d1a95a
Sembolik bir ref olmadığından, doğrudan commit'in kendisine işaret etmelidir.HEAD→
17a02998078923f2d62811326d130de991d1a95a` var
Ayrılmış bir HEAD ile hatırlanması gereken önemli şey, işaret ettiği commit başka bir şekilde referanslanmamışsa (başka hiçbir ref ona ulaşamaz), başka bir commit'i kontrol ettiğinizde "sarkık" hale gelecektir. Sonunda, bu tür sarkan commitler çöp toplama işlemi ile budanacaktır (varsayılan olarak, en az 2 hafta tutulurlar ve HEAD'in reflog'u tarafından referans alınarak daha uzun süre tutulabilirler).
1 Ayrılmış bir HEAD ile "normal" işler yapmakta bir sakınca yoktur, sadece reflog'dan düşen geçmişi bulmak zorunda kalmamak için ne yaptığınızı takip etmeniz gerekir.
Etkileşimli bir yeniden düzenlemenin ara adımları ayrılmış bir HEAD ile yapılır (kısmen aktif dalın reflogunu kirletmekten kaçınmak için). Tam yeniden düzenleme işlemini bitirirseniz, orijinal dalınızı yeniden düzenleme işleminin kümülatif sonucu ile günceller ve HEAD'i orijinal dala yeniden ekler. Tahminimce, rebase işlemini hiçbir zaman tam olarak tamamlamadınız; bu da sizi rebase işlemi tarafından en son işlenen commit'e işaret eden ayrılmış bir HEAD ile baş başa bırakacaktır.
Durumunuzu kurtarmak için, ayrılmış HEAD'inizin şu anda işaret ettiği commit'i işaret eden bir dal oluşturmalısınız:
git branch temp
git checkout temp
(bu iki komut git checkout -b temp
olarak kısaltılabilir)
Bu, HEAD'inizi yeni temp
dalına yeniden ekleyecektir.
Ardından, mevcut işlemeyi (ve geçmişini) üzerinde çalışmayı beklediğiniz normal dal ile karşılaştırmalısınız:
git log --graph --decorate --pretty=oneline --abbrev-commit master origin/master temp
git diff master temp
git diff origin/master temp
(Muhtemelen günlük seçeneklerini denemek isteyeceksiniz: -p
ekleyin, tüm günlük mesajını görmek için --pretty=...
seçeneğini devre dışı bırakın, vb.)
Yeni temp
dalınız iyi görünüyorsa, master
dalını ona işaret edecek şekilde güncellemek (örneğin) isteyebilirsiniz:
git branch -f master temp
git checkout master
(bu iki komut git checkout -B master temp
olarak kısaltılabilir)
Daha sonra geçici dalı silebilirsiniz:
git branch -d temp
Son olarak, muhtemelen yeniden oluşturulmuş geçmişi zorlamak isteyeceksiniz:
git push origin master
Uzak dal yeni commit'e "hızlı ileri" alınamıyorsa (yani mevcut bir commit'i düşürdüyseniz veya yeniden yazdıysanız ya da başka bir şekilde geçmişin bir kısmını yeniden yazdıysanız) push etmek için bu komutun sonuna `--force' eklemeniz gerekebilir.
Bir yeniden yerleştirme işleminin ortasında olsaydınız muhtemelen temizlemeniz gerekirdi. Rebase işleminin yapılıp yapılmadığını .git/rebase-merge/
dizinine bakarak kontrol edebilirsiniz. Sadece bu dizini silerek devam eden yeniden düzenlemeyi manuel olarak temizleyebilirsiniz (örneğin, aktif yeniden düzenleme işleminin amacını ve bağlamını artık hatırlamıyorsanız). Genellikle git rebase --abort
kullanırsınız, ancak bu muhtemelen kaçınmak isteyeceğiniz bazı ekstra sıfırlamalar yapar (HEAD'i orijinal dala geri taşır ve orijinal commit'e geri sıfırlar, bu da yukarıda yaptığımız işin bir kısmını geri alır).
Ayrılmış başın temel açıklaması için buraya bakın:
http://git-scm.com/docs/git-checkout
Görselleştirmek için komut satırı:
git branch
veya
git branch -a
aşağıdaki gibi bir çıktı alacaksınız:
* (no branch)
master
branch1
Bu duruma bir git checkout somecommit
vb. yaparak da gelebilirdiniz ve sizi aşağıdaki şekilde uyarırdı:
'KAFA'nız 'ayrılmış' durumdasınız. Sen etrafa bakabilir, deneysel çalışmalar yapabilir değişiklikleri yapın ve bunları işleyin ve bu işlemde yaptığınız tüm taahhütleri atın herhangi bir şubeyi etkilemeden durum başka bir ödeme gerçekleştirerek.
Eğer yeni bir şube oluşturmak istiyorsanız oluşturduğunuz taahhütleri koruyun, şunları yapabilirsiniz bu nedenle (şimdi veya daha sonra) -b ile checkout komutunu tekrar verin. Örnek:
git checkout -b new_branch_name
Şimdi, onları ustaya götürmek için:
Bir git reflog
veya hatta sadece git log
yapın ve taahhütlerinizi not edin. Şimdi git checkout master
ve taahhütleri git merge
yapın.
git merge HEAD@{1}
Düzenle:
Eklemek gerekirse, git rebase -i
yi yalnızca ihtiyacınız olmayan taahhütleri silmek / öldürmek için değil, aynı zamanda bunları düzenlemek için de kullanın. Komite listesinde "edit" yazmanız yeterlidir ve komitenizi değiştirebilir ve ardından devam etmek için bir git rebase --continue
yayınlayabilirsiniz. Bu, hiçbir zaman ayrılmış bir HEAD'e gelmemenizi sağlayacaktır.