Bazen etkili bir şekilde imkansızdır (ek veriye sahip olmak için şanslı olabileceğiniz bazı istisnalar hariç) ve buradaki çözümler işe yaramaz.
Git ref geçmişini (şubeleri içeren) korumaz. Sadece her dal için geçerli pozisyonu (kafa) saklar. Bu, git'te zaman içinde bazı şube geçmişini kaybedebileceğiniz anlamına gelir. Örneğin, ne zaman dallıyorsanız, hangi dalın orijinal olduğu hemen kaybolur. Bir dalın yaptığı tek şey:
git checkout branch1 # refs/branch1 -> commit1
git checkout -b branch2 # branch2 -> commit1
İlk taahhüdün şube olduğunu varsayabilirsiniz. Durum böyle olma eğilimindedir, ancak her zaman böyle değildir. Yukarıdaki operasyondan sonra ilk olarak her iki şubeye geçmenizi engelleyen hiçbir şey yoktur. Ayrıca, git zaman damgalarının güvenilir olduğu garanti edilmez. Her ikisine de, yapısal olarak gerçekten dal haline gelene kadar değil.
Diyagramlarda sayıları kavramsal olarak taahhüt etme eğilimindeyken, git işlenen ağaç dalları olduğunda git'in gerçek kararlı bir sekans kavramı yoktur. Bu durumda sayıların (sıralama sırasını) zaman damgası ile belirlendiğini varsayabilirsiniz (tüm zaman damgalarını aynı olarak ayarladığınızda bir git kullanıcı arabiriminin işleri nasıl ele aldığını görmek eğlenceli olabilir).
İnsan kavramsal olarak şunu bekler:
After branch:
C1 (B1)
/
-
\
C1 (B2)
After first commit:
C1 (B1)
/
-
\
C1 - C2 (B2)
Aslında elde ettiğiniz budur:
After branch:
- C1 (B1) (B2)
After first commit (human):
- C1 (B1)
\
C2 (B2)
After first commit (real):
- C1 (B1) - C2 (B2)
B1'in orijinal dal olduğunu varsayarsınız, ancak bu sadece ölü bir dal olabilir (birisi ödeme yaptı -b ama asla taahhütte bulunmadı). Git içinde meşru bir şube yapısı elde etmeyi taahhüt edene kadar:
Either:
/ - C2 (B1)
-- C1
\ - C3 (B2)
Or:
/ - C3 (B1)
-- C1
\ - C2 (B2)
C1'in C2 ve C3'ten önce geldiğini her zaman bilirsiniz, ancak C2'nin C3 veya C3'ün C2'den önce gelip gelmediğini asla güvenilir bir şekilde bilemezsiniz (çünkü iş istasyonunuzdaki zamanı örneğin herhangi bir şeye ayarlayabilirsiniz). B1 ve B2 de yanıltıcıdır, çünkü hangi şubenin ilk geldiğini bilemezsiniz. Birçok durumda çok iyi ve genellikle doğru bir tahmin yapabilirsiniz. Biraz yarış pisti gibi. Genelde arabalarla eşit olan her şey, o zaman arkadan bir kucağa gelen bir arabanın arkadan bir tur başlattığını varsayabilirsiniz. Ayrıca çok güvenilir sözleşmelerimiz var, örneğin usta, neredeyse her zaman en uzun yaşam dallarını temsil edecek, ancak ne yazık ki bunun bile olmadığı durumlar gördüm.
Burada verilen örnek, tarihi koruyan bir örnektir:
Human:
- X - A - B - C - D - F (B1)
\ / \ /
G - H ----- I - J (B2)
Real:
B ----- C - D - F (B1)
/ / \ /
- X - A / \ /
\ / \ /
G - H ----- I - J (B2)
Burada gerçek de yanıltıcıdır çünkü insanlar olarak onu soldan sağa, kökten yaprağa okuruz (ref). Git bunu yapmaz. Yaptığımız (A-> B) başımızdaki git git (A <-B veya B-> A). Ref'den köke doğru okur. Referanslar herhangi bir yerde olabilir, ancak en azından aktif dallar için yaprak olma eğilimindedir. Ref, bir taahhüdü işaret eder ve taahhütler, çocuklarına değil, ebeveynlerine / çocuklarına benzer bir şey içerir. Bir taahhüt bir birleştirme taahhüdü olduğunda birden fazla ebeveyni olacaktır. İlk ebeveyn her zaman birleştirilen orijinal taahhüttür. Diğer ebeveynler her zaman orijinal taahhütte birleştirilen taahhütlerdir.
Paths:
F->(D->(C->(B->(A->X)),(H->(G->(A->X))))),(I->(H->(G->(A->X))),(C->(B->(A->X)),(H->(G->(A->X)))))
J->(I->(H->(G->(A->X))),(C->(B->(A->X)),(H->(G->(A->X)))))
Bu çok etkili bir gösterim değil, git'in her ref'den (B1 ve B2) alabileceği tüm yolların bir ifadesidir.
Git'in dahili depolama birimi daha çok benzer (bir ebeveyn olarak A iki kez görünmez):
F->D,I | D->C | C->B,H | B->A | A->X | J->I | I->H,C | H->G | G->A
Bir ham git komutunu dökerseniz, sıfır veya daha fazla üst alan görürsünüz. Sıfır varsa, bu hiçbir üst öğe ve kesinleştirme bir kök demektir (aslında birden fazla kökünüz olabilir). Bir tane varsa, bu bir birleşme olmadığı anlamına gelir ve bu bir kök taahhüdü değildir. Birden fazla olması, taahhüdün bir birleştirmenin sonucu olduğu ve ilkinden sonraki tüm ebeveynlerin birleştirme taahhütleri olduğu anlamına gelir.
Paths simplified:
F->(D->C),I | J->I | I->H,C | C->(B->A),H | H->(G->A) | A->X
Paths first parents only:
F->(D->(C->(B->(A->X)))) | F->D->C->B->A->X
J->(I->(H->(G->(A->X))) | J->I->H->G->A->X
Or:
F->D->C | J->I | I->H | C->B->A | H->G->A | A->X
Paths first parents only simplified:
F->D->C->B->A | J->I->->G->A | A->X
Topological:
- X - A - B - C - D - F (B1)
\
G - H - I - J (B2)
Her ikisi de A'ya çarptığında, zincirleri aynı olacaktır, bundan önce zincirleri tamamen farklı olacaktır. Diğer iki taahhüdün ortak ilk taahhüdü ortak atadır ve oradan ayrılırlar. Burada taahhüt, şube ve ref terimleri arasında bazı karışıklıklar olabilir. Aslında bir taahhüdü birleştirebilirsiniz. Birleşmenin gerçekten yaptığı budur. Bir ref sadece bir noktaya işaret eder ve bir şube .git / refs / heads klasöründeki bir ref'den başka bir şey değildir, klasör konumu, ref'nin etiket gibi başka bir şeyden ziyade bir dal olduğunu belirleyen şeydir.
Tarihi kaybettiğiniz yer, birleşmenin koşullara bağlı olarak iki şeyden birini yapmasıdır.
Düşünmek:
/ - B (B1)
- A
\ - C (B2)
Bu durumda, her iki yönde birleştirme, mevcut teslim alınan dal tarafından işaret edilen taahhüt ve ikinci ebeveyn ile mevcut dalınıza birleştirdiğiniz dalın ucundaki taahhüt olarak yeni ana taahhüt oluşturacaktır. Ortak atalarından bu yana birleştirilmesi gereken her iki dalda da değişiklikler olduğu için yeni bir taahhüt yaratmalıdır.
/ - B - D (B1)
- A /
\ --- C (B2)
Bu noktada D (B1) artık her iki daldan da (kendisi ve B2) her iki değişiklik kümesine sahiptir. Ancak ikinci dalın B1'den değişikliği yok. B1'den B2'ye değişiklikleri senkronize olacak şekilde birleştirirseniz, şuna benzer bir şey bekleyebilirsiniz (git birleştirme işlemini ancak --no-ff ile böyle yapmaya zorlayabilirsiniz):
Expected:
/ - B - D (B1)
- A / \
\ --- C - E (B2)
Reality:
/ - B - D (B1) (B2)
- A /
\ --- C
B1'in ek taahhütleri olsa bile bunu elde edersiniz. B2'de B1'in sahip olmadığı değişiklikler olmadığı sürece, iki şube birleştirilecek. Sadece bir dalın bir değişiklik setine sahip olduğu bir rebazın aksine, bir daldan diğerinin üzerine bir daldan bir değişiklik kümesi uygulamak zorunda olmadığı bir rebase (rebases yemek veya doğrusallaştırma geçmişi) gibi bir hızlı ileri yapar.
From:
/ - B - D - E (B1)
- A /
\ --- C (B2)
To:
/ - B - D - E (B1) (B2)
- A /
\ --- C
B1 üzerinde çalışmayı durdurursanız, uzun vadede tarihi korumak için işler büyük ölçüde iyidir. Sadece B1 (master olabilir) tipik olarak ilerler, böylece B2'nin B2'nin tarihindeki B2 konumu, B1 ile birleştirildiği noktayı başarıyla temsil eder. Git'in B'den dalına gitmenizi beklediği şey budur, o zaman A'yı B birikiminde istediğiniz kadar biriktirebilirsiniz, ancak B'yi tekrar A ile birleştirdiğinizde, B ve daha fazla çalışmanız beklenmez. . Çalıştığınız şubeye hızlıca bir araya getirdikten sonra şubeniz üzerinde çalışmaya devam ediyorsanız, her seferinde B'nin önceki geçmişini silersiniz. Kaynağa hızlı bir şekilde ilerledikten sonra şubeye taahhüt edildikten sonra her seferinde gerçekten yeni bir şube oluşturuyorsunuz.
0 1 2 3 4 (B1)
/-\ /-\ /-\ /-\ /
---- - - - -
\-/ \-/ \-/ \-/ \
5 6 7 8 9 (B2)
1 ila 3 ve 5 ila 8, ya 4 ya da 9 tarihini takip ederseniz ortaya çıkan yapısal dallardır. Git'te bu adlandırılmamış ve referanslandırılmamış yapısal dallardan hangisinin adı verilen ve referans dallara ait olduğunu bilmenin bir yolu yoktur. yapının sonu. Bu çizimden 0 ila 4'ün B1'e ve 4 ila 9'un B2'ye ait olduğunu, ancak 4 ve 9'un dışında hangi dalın hangi dala ait olduğunu bilemediğini varsayabilirsiniz, bunu sadece yanılsaması. 0, B2'ye ve 5, B1'e ait olabilir. Bu durumda, yapısal dalların her birine ait dal adı verilen 16 farklı olasılık vardır.
Bu soruna geçici bir çözüm bulmak için birkaç git stratejileri vardır. Git birleştirmeyi hiçbir zaman hızlı ileri sarmaya zorlamayabilir ve her zaman bir birleştirme dalı oluşturabilirsiniz. Şube geçmişini korumanın korkunç bir yolu, seçtiğiniz bazı kurallara göre etiketler ve / veya şubelerdir (etiketler gerçekten önerilir). Gerçekten bir araya geldiğiniz şubede boş bir işlem önermem. Çok yaygın bir kural, şubenizi gerçekten kapatmak istediğinize kadar bir entegrasyon dalıyla birleşmektir. Bu, insanların şube sahibi olma noktasında çalıştığınız gibi uymaya çalışmaları gereken bir uygulamadır. Ancak gerçek dünyada ideal her zaman pratik değildir, yani doğru olanı yapmak her durum için uygun değildir. Eğer sen