Git alt modül başlığı 'başvuru bir ağaç değil' hatası


305

Ben geçersiz bir taahhüt işaret eden bir alt modül ile bir proje var: alt modül taahhüt yerel kaldı ve başka bir repo getirmeye çalıştığınızda olsun:

$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'

Ben yerel olarak değiştirebilirsiniz herhangi bir yolu yoktur submodule BAŞ repo iterek olmadan ne olması gerektiğini biliyor mu taahhüt ediyorum 2d7cfbd09fc96c04c4c41148d44ed7778add6b43?

Açık olup olmadığımdan emin değilim ... işte bulduğum benzer bir durum .


11
"ölümcül: referans bir ağaç değildir", alt modüllere referans olarak, genellikle ana repo'nun henüz beklemediği veya başka bir şekilde vidalandığı alt modül taahhüdü anlamına gelir. Bizim için bu kafa karıştırıcı hata mesajı, birisinin itmeyi unuttuğu bir alt modülü iterek çözüldü.
Chris Moschini

1
@ChrisMoschini - Ben sadece bu sorunu vardı, ve bu benim "çözüm" oldu, ben ana depo itti ve çekti., Ama son taahhüt submodule repo itmek unuttum. Teşekkürler!
Rotem

Belki de en son alt modül taahhütlerini zorlamayı unuttun
Hafenkranich

Yanıtlar:


378

Alt modülün deposunun kullanmak istediğiniz bir taahhüt içerdiğini varsayarsak (süper projenin mevcut durumundan referans alınan taahhütten farklı olarak), bunu yapmanın iki yolu vardır.

Birincisi, kullanmak istediğiniz alt modülün taahhüdünü zaten bilmenizi gerektirir. Doğrudan alt modülü ayarlayıp süper projeyi güncelleyerek “içten dışa” çalışır. İkincisi, alt modülü değiştiren süper projenin taahhüdünü bularak ve daha sonra farklı bir alt modül taahhüdüne atıfta bulunmak için süper projenin dizinini sıfırlayarak “dışarıdan, içeri” den çalışır.

Tersyüz

Zaten biliyorsanız alt modülü, kullanmak istediğiniz işlemek hangi cdardından, istediğiniz işlemek kontrol, alt modülün etmek git addvegit commit geri süper projede.

Misal:

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'

Hata! Birisi, alt modülde yayınlanmamış bir taahhüt anlamına gelen bir süper proje taahhüdü yaptı sub. Her nasılsa, alt modülün işlenmesini istediğimizi zaten biliyoruz 5d5a3ee314476701a20f2c6ec4a53f88d651df6c. Oraya git ve doğrudan kontrol et.

Alt Modüldeki Ödeme

$ cd sub
$ git checkout 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
Note: moving to '5d5a3ee314476701a20f2c6ec4a53f88d651df6c' which isn't a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
  git checkout -b <new_branch_name>
HEAD is now at 5d5a3ee... quux
$ cd ..

Bir taahhüdü kontrol ettiğimiz için, bu, alt modülde bağımsız bir HEAD üretir. Alt modülün bir dal kullandığından emin olmak istiyorsanız, komut satırında bir dal git checkout -b newbranch <commit>oluşturmak ve kullanıma almak veya istediğiniz dalda ödeme yapmak için kullanın (örneğin, ipucunda istenen tamamlayıcı ile).

Süper projeyi güncelleyin

Alt modüldeki bir ödeme, süper projeye çalışma ağacında bir değişiklik olarak yansıtılır. Bu nedenle, süper projenin dizinindeki değişikliği aşamalı hale getirmeli ve sonuçları doğrulamalıyız.

$ git add sub

Sonuçları Kontrol Edin

$ git submodule update
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

Alt modül zaten belirtilen tamamlamada olduğundan alt modül güncellemesi sessizdi. İlk fark, dizin ile çalışma ağacının aynı olduğunu gösterir. Üçüncü fark, tek aşamalı değişikliğin subalt modülü farklı bir işleme taşıdığını göstermektedir.

işlemek

git commit

Bu, sabitlenmiş alt modül girişini gerçekleştirir.


Dıştan içe

Alt modülden hangi taahhüdü kullanmanız gerektiğinden emin değilseniz, size yol göstermek için süper projedeki geçmişe bakabilirsiniz. Sıfırlamayı doğrudan süper projeden de yönetebilirsiniz.

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'

Bu yukarıdakiyle aynı durumdur. Ancak bu sefer, alt modüle daldırmak yerine süper projeden düzeltmeye odaklanacağız.

Süper Projenin Errant Taahhüdünü Bulun

$ git log --oneline -p -- sub
ce5d37c local change in sub
diff --git a/sub b/sub
index 5d5a3ee..e47c0a1 160000
--- a/sub
+++ b/sub
@@ -1 +1 @@
-Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
+Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
bca4663 added sub
diff --git a/sub b/sub
new file mode 160000
index 0000000..5d5a3ee
--- /dev/null
+++ b/sub
@@ -0,0 +1 @@
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

Tamam, kötü gidiyor gibi görünüyor ce5d37c, bu yüzden alt modülü üst öğesinden ( ce5d37c~) geri yükleyeceğiz .

Alternatif olarak, alt modülün taahhüdünü yama metninden ( 5d5a3ee314476701a20f2c6ec4a53f88d651df6c) alabilir ve bunun yerine yukarıdaki “iç, dış” işlemini kullanabilirsiniz.

Süper projede ödeme

$ git checkout ce5d37c~ -- sub

Bu için alt modül girişi sıfırlamak suben işlemek ne kadar ce5d37c~süper projede.

Alt Modülü Güncelle

$ git submodule update
Submodule path 'sub': checked out '5d5a3ee314476701a20f2c6ec4a53f88d651df6c'

Alt modül güncellemesi tamamlandı (ayrılmış bir HEAD olduğunu gösterir).

Sonuçları Kontrol Edin

$ git diff ce5d37c~ -- sub
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

İlk fark sub, şimdi aynı olduğunu gösteriyor ce5d37c~. İkinci fark, indeks ve çalışma ağacının aynı olduğunu gösterir. Üçüncü fark, sadece aşamalı değişikliğin subalt modülün farklı bir işleme taşınması olduğunu gösterir .

işlemek

git commit

Bu, sabitlenmiş alt modül girişini gerçekleştirir.


"Dışarıda, İçeri" yaklaşımında, neden "ce5d37c'de kötüye gitmiş gibi görünüyor?" Kötü olanı hangi parmaklar yapar?
Garrett Albright

5
@Garrett: Varsayım, e47c0ayerel depoda mevcut olmayan bir taahhüttür sub, ancak süper projenin subbu taahhüdü işaret eder. Bu, başka birinin e47c0akopyasında oluşturduğu sub, süper projelerini bu taahhüde işaret edecek şekilde güncellediği e47c0ave merkezi / paylaşılan depoya itmeden süper projeyi ittiği için olmuş olabilir sub. Ve merkezi / paylaştı süper projesinden çekin ne zaman bir o noktaları işlemek almak subiçin e47c0ataahhüt olduğunu, ama biz “görmek” mümkün değil. ce5d37cşüphelidir, çünkü diferansiyele dayanarak ortaya çıkmıştır e47c0a.
Chris Johnsen

Hala subbir alt modül olarak sahip olan ana repoda tutulan hashın nerede olduğu ve meselenin subdaha eski bir durumuna dayanmadan doğrudan mevcut HEAD'e yönlendirilip değiştirilemeyeceği belirsiz . her zaman yardımcı olmayabilir repo.
matanster


187

bunu dene:

git submodule sync
git submodule update

2
Ne yazık ki benim için değil, bizim alt modüllerimizden biri ana git deposu tarafından bir add komutuyla hedeflendi, şimdi onu geri almakta sorun yaşıyor
Daniel

9
Benim için de çalıştı. Neden olsa bilmek isterdim.
BenBtg

12
git submodule syncBelirli bir alt modül için uzaktan kumandanın URL'sinin değiştiği senaryolarda a yapmanın gerekli olduğu ortaya çıkıyor. Bizim durumumuzda alt modülümüzü halka açık bir repodan ekledik ve sonra URL'yi özel bir çatalla değiştirdik ve kendimizi bu turşuya aldık.
Samscam

Örneğin: Github repo'yu (B) işaret eden bir alt modül ile kurulmuş bir repo (A) vardı. A deposunda bir şube oluşturdum çünkü B'yi başkasının github deposuna yönlendirmek istedim. Biraz uğraştıktan ve şubeye devam ettikten sonra, repo A'mı ustalaştım ve repo B ile ilgili bir sorun yaşadım. @Lonre Wang'ın çözümü bunu düzeltti.
fbicknel

2
Kimsenin GERÇEKTEN berbat olduğunu varsayarsak (bu durumda Chris Johnsen mükemmel cevaba ihtiyacınız olacak) Lonre Wang'ın cevabı sorunu çözmeli ... ... Alt modüllerinizin kendi alt modelleri var (ve sorun bir alt modülün içinde). Bu durumda, sorunu içeren alt modülün bulunduğu alt modüle cd yapmanız ve yukarıdaki komutları yürütmeniz gerekir. Güncellemenin --recursive seçeneği (git submodule update --recursive) olduğunu, ancak senkronizasyonun olmadığını unutmayın; gerçekten sorunlu alt (alt) modülü olan alt modül içinde 'git submodule sync' i manuel olarak çalıştırmanız gerekir. Bu benim sorunumdu;).
Carlo Wood

16

Bu hata, alt modülde bir taahhüdün eksik olduğu anlamına gelebilir. Yani, havuzun (A) bir alt modülü (B) vardır. A, B'yi belirli bir taahhüdü işaret edecek şekilde yüklemek istiyor (B'de). Bu işlem bir şekilde eksikse, bu hatayı alırsınız. Bir kez olası neden: Taahhüt için referans A'ya itildi, ancak asıl taahhüt B'den itilmedi.

Daha az olasılıkla, bir izin sorunu vardır ve taahhüt yüklenemez (git + ssh kullanıyorsanız mümkündür).

Alt modül yollarının .git / config ve .gitmodules'de iyi göründüğünden emin olun.

Denenecek son bir şey var - alt modül dizininin içinde: git reset HEAD --hard


3
Soruda ... sorunun kendisinin nasıl çözüleceğini açıklamıştım. Ve neredeyse iki yıl önce başarıyla cevaplandı ... İzinlerin bununla hiçbir ilgisi yok.
Mauricio Scheffer

1
Siz söylediniz, kesinlikle açıklamadınız.
Daniel Tsadok

Demek istediğim, bu cevap değerli bir bilgi eklemiyor, onu silebilirdim.
Mauricio Scheffer

4
"git reset HEAD --hard" da bana yardımcı oldu ... başka hiçbir şey işe yaramadı. Önceki çözümleri de denedim, zar yok. Teşekkürler!
Virgil

1
Her iş parçacığı kendi çevrimiçi küçük dünya. Söyledikleriniz sizi temsil eder - insanların kişisel geçmişinizi, yorumlarınızı arzu ettiğiniz saygıyı sağlayacak bir çerçevede çerçevelemeye çalışacaklarını bekleyemezsiniz. Nazik olun, saygılı olun ve insanlardan kişisel tuhaflıklarınızı anlamalarını istemeniz gerekmeyecek. Yorumunuzu tarafsız bir bağlamdan okuyabilirseniz, yabancıların yaptığı gibi, eleştirilerimi anlayacaksınız.
Stabledog

10

Muhtemel neden

Bu şu durumlarda olabilir:

  1. Alt modül (ler) yerinde düzenlendi
  2. Taranan alt modülün karmasını güncelleyen alt modül (ler)
  3. Alt modül (ler) itilmedi .

örneğin böyle bir şey oldu:

$ cd submodule
$ emacs my_source_file  # edit some file(s)
$ git commit -am "Making some changes but will forget to push!"

Bu noktada alt modül itilmiş olmalıdır.

$ cd .. # back to parent repository
$ git commit -am "updates to parent repository"
$ git push origin master

Sonuç olarak, eksik komutlar uzak kullanıcı tarafından hala yerel diskte oldukları için bulunamamıştır.

Çözüm

Alt modülü itmek için değiştiren kişiyi bilgilendirin, yani

$ cd submodule
$ git push

6

Yaptığımda bu hatayı aldım:

$ git submodule update --init --depth 1

ancak ana projedeki taahhüt daha erken bir taahhüde işaret ediyordu.

Alt modül klasörünü silme ve çalıştırma:

$ git submodule update --init

sorunu çözmedim. Repoyu sildim ve derinlik bayrağı olmadan tekrar denedim ve işe yaradı.

Bu hata Ubuntu 16.04 git 2.7.4'te olur, ancak Ubuntu 18.04 git 2.17'de olmaz, TODO tam sabitleme taahhüdünü veya sürümünü bulur.


ekibim o zamandan beri bizim kod yol çok fazla güçlük lol alt modülleri terk etti
Plato

1
alternatifin neydi?
nuzzolilo

@nuzzolilo eklediğimiz username/repo#shapackage.json, çok daha esnek bir seçenek sisteminizi bir dizi docker konteyneri ile organize etmektir
Plato

3
Bu çok can sıkıcı. --depth=1Repo geçmişine ihtiyacım olmadığında çok fazla bant genişliği tasarrufu sağlıyor. Eğer kimse bunun neden olduğunu bulur veya bilirse bilmek isterim.
i336_

@ i336_ Nedenini açıklayamasam da, sorunu burada hafifletmeye yardımcı olan bir cmake yardımcısı yazdım: github.com/LMMS/lmms/blob/… . deinitSorunu çoğu zaman düzelten bir yaklaşım kullanır . Bir derleme sistemi ile birlikte paketlendiğinde, son kullanıcı derleme sisteminin alt modülleri getirmesine ve kırık recursivekomutu tamamen terk etmesine izin verebilir . Alt modül gibi bu kırılmaların bir kuvvet zorlaması yaptığı ve taahhüdü tamamen ortadan kaldırdığı senaryolar hala var.
tresf

5

Bu aynı zamanda, yeniden temellendirilen bir depoya işaret eden bir alt modülünüz olduğunda ve verilen taahhüt "gittiğinde" de olabilir. Taahhüt hala uzak depoda olsa da, bir dalda değildir. Yeni bir şube oluşturamazsanız (örneğin deponuz değil), süper projeyi yeni bir taahhüde işaret edecek şekilde güncellemek zorunda kalırsınız. Alternatif olarak, alt modüllerin kopyalarınızdan birini başka bir yere itebilir ve süper projeyi bunun yerine bu depoya işaret edecek şekilde güncelleyebilirsiniz.



2

Bu yanıt, sınırlı terminal git deneyimi olan SourceTree kullanıcıları içindir.

Sorunlu alt modülü Git projesinden (süper proje) açın.

Getir ve 'Tüm etiketleri getir' seçeneğinin işaretli olduğundan emin ol.

Git projenizi yeniden çekin.

Bu, 'referans bir ağaç değildir' problemini on kez 9 çözecektir. Bu 1 kez olmayacak, üst cevapta açıklandığı gibi bir terminal düzeltmedir.


1

Alt modül geçmişiniz yine de alt modülde güvenli bir şekilde korunur.

Peki, neden sadece alt modülü silmek ve tekrar eklemek istemiyorsunuz?

Aksi takdirde, alt modülün içindeki HEADveya refs/master/headiçindeki el ile düzenlemeyi denediniz mi.git


1
Bu işe yaramaz, çünkü bir yerde sadece başka bir yerde yerel yayın olan ancak yayınlanmayan 2d7cfbd09fc96c04c4c41148d44ed7778add6b43 referansı var
Mauricio Scheffer

1

Emin olmak için gitikili dosyalarınızı güncellemeyi deneyin .

Windows için GitHub git version 1.8.4.msysgit.0, benim durumumda sorun olan sürüme sahip. Güncelleme çözüldü.


1

Benim durumumda, yukarıdaki cevapların hiçbiri, iyi cevaplar olsalar bile sorunu çözmez. Bu yüzden çözümümü gönderiyorum (benim durumumda iki git istemcisi var, istemci A ve B):

  1. alt modülün dizinine gidin:

    cd sub
    
  2. master için ödeme:

    git checkout master
    
  3. her iki istemcinin görebileceği bir taahhüt kodunu yeniden oluşturmak

  4. ebeveynin dizinine geri dön:

  5. ustalaşmak

  6. diğer istemciye geçin rebaseagain tekrar yapın.

  7. nihayet şimdi iyi çalışıyor! Belki birkaç taahhüdü kaybedersiniz ama işe yarar.

  8. FYI, alt modülünüzü çıkarmaya çalışmayın, .git/modulesorada kalacaktır ve reaktif yerel olana kadar bu alt modülü tekrar okuyamaz.


1

Git deposunu alt modülün kafasıyla senkronize etmek için, gerçekten istediğiniz şey olması durumunda, alt modülün çıkarılmasının ve ardından okumanın tarihle uğraşmasını önlediğini buldum. Ne yazık ki bir alt modülün kaldırılması tek bir git komutu olmaktan ziyade saldırıya ihtiyaç duyar, ancak yapılabilir.

Https://gist.github.com/kyleturner/1563153'ten esinlenerek alt modülü kaldırmak için izlediğim adımlar :

  1. Git git rm - önbellekli
  2. İlgili satırları .gitmodules dosyasından silin.
  3. İlgili bölümü .git / config dizininden silin.
  4. Şimdi izlenmeyen alt modül dosyalarını silin.
  5. .Git / modules / dizinini kaldırın

Yine, istediğiniz tek şey alt modülün kafasına tekrar işaret etmekse ve alt modülün yerel kopyasını sağlam tutmaya gerek kalmadan karmaşık bir şey yapmadıysanız faydalı olabilir. Kök nerede olursa olsun, kendi repo'su olarak "doğru" alt modülünüz olduğunu varsayar ve alt modül olarak uygun şekilde geri almak istediğinizi varsayarsınız.

Not: Bu tür manipülasyonlara veya basit taahhüt veya itmenin ötesinde herhangi bir git komutuna girmeden önce her zaman projenizin tam bir kopyasını alın. Bunu diğer tüm cevaplarla ve genel bir git kılavuzu olarak tavsiye ederim.


1

Sadece bu sorun üzerinde tökezledi ve bu çözümlerin hiçbiri benim için işe yaramadı. Sorunumun çözümü olduğu ortaya çıkan aslında çok daha basit: Git'i yükseltin. Benimki 1.7.1 idi ve 2.16.1'e (en son) yükselttikten sonra, sorun iz bırakmadan gitti! Sanırım burada bırakıyorum, umarım birisine yardım eder.

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.