Bu, okuyucunun yararı için, onu özetlemeye ve işler beklendiği gibi çalışmazsa nasıl yapılacağına dair adım adım bir kılavuz vermeye çalışır. Aşağıda test edilmiş ve güvenli bir yol için git
sürümüne 2.17
ve üzeri bir altmodülün kurtulmak için :
submodule="path/to/sub" # no trailing slash!
git submodule deinit -- "$submodule"
git rm -- "$submodule"
- Bu sizin için işe yaramazsa aşağıya bakın.
- Seçenek yok. Tehlikeli bir şey yok. Ve daha fazlasını yapmayı bile düşünmeyin!
- Debian Buster
2.20.1
ve Ubuntu 18.04 ile test edildi 2.17.1
.
"$submodule"
sadece adı nereye koyacağınızı ve boşluklara ve benzerlerine dikkat etmeniz gerektiğini vurgulamaktır
- Windows üzerinde ise, ilk satırı yok sayın
"$submodule"
ve alt modüle doğru şekilde belirlenmiş bir yolun Windows yoluyla değiştirin . (Ben Windows değilim)
Uyarı!
Asla .git
dizinin iç kısımlarına dokunmayın ! İçeride düzenleme .git
karanlık tarafa girer. Ne pahasına olursa olsun uzak dur!
Ve evet, bunun git
için suçlayabilirsiniz , çünkü git
geçmişte birçok kullanışlı şey eksikti . Alt modülleri tekrar çıkarmanın uygun bir yolu gibi.
Dokümantasyonunda çok tehlikeli bir kısım olduğunu düşünüyorum git submodule
. $GIT_DIR/modules/<name>/
Kendinizi çıkarmanızı önerir .
Anladığım kadarıyla bu sadece basit bir yanlış değil, son derece tehlikelidir ve gelecekte büyük baş ağrılarına neden olur! Aşağıya bakınız.
Bunu not et
git module deinit
doğrudan ters
git module init
fakat
git submodule deinit -- module
git rm -- module
ayrıca oldukça ters
git submodule add -- URL module
git submodule update --init --recursive -- module
çünkü bazı komutların temelde tek bir şeyden daha fazlasını yapması gerekir:
git submodule deinit -- module
- (1) güncelleme
.git/config
git rm
- (2) modülün dosyalarını kaldırır
- (3) böylece alt modülün alt modüllerini tekrar tekrar kaldırır
- (4) güncelleme
.gitmodules
git submodule add
- verileri içine çeker
.git/modules/NAME/
- (1) yapar
git submodule init
, bu yüzden güncellemeler.git/config
- (2)
git submodule update
, modülü tekrar tekrar kontrol etmez
- (4) güncelleme
.gitmodules
git submodule update --init --recursive -- module
- gerekirse daha fazla veri çeker
- (3) alt modülün alt modüllerini tekrar tekrar kontrol eder
Bu tamamen simetrik olamaz, çünkü kesinlikle simetrik tutmak pek mantıklı değildir. İkiden fazla komuta gerek yoktur. Ayrıca, "veriyi çekmek" örtüktür, çünkü buna ihtiyacınız vardır, ancak önbelleğe alınmış bilgilerin kaldırılması yapılmaz, çünkü bu hiç gerekli değildir ve değerli verileri silebilir.
Bu gerçekten yeni gelenler için şaşırtıcı, ama temelde iyi bir şey: git
sadece açık bir şey yapar ve bunu doğru yapar ve daha fazlasını yapmaya bile çalışmaz. git
başka bir "Eierlegende Wollmilchsau" olmak yerine güvenilir bir iş yapması gereken bir araçtır ("Eierlegende Wollmilchsau" benim için "İsviçreli bir ordu bıçağının kötü versiyonuna" çevirir).
Bu yüzden insanların şikayetlerini anlıyorum, "Neden git
benim için açık olanı yapmıyor ". Çünkü buradaki "açık" bakış açısından bağlıdır. Her durumda güvenilirlik çok daha önemlidir. Bu nedenle, sizin için açık olan şey, olası tüm teknik durumlarda doğru olan şey değildir. Lütfen unutmayın: AFAICS git
sosyal yolu değil, teknik yolu izler. (Dolayısıyla akıllı isim: git)
Bu başarısız olursa
Yukarıdaki komutlar aşağıdakiler nedeniyle başarısız olabilir:
- Sizin
git
çok eski. Sonra daha yenisini kullanın git
. (Nasıl yapılacağı konusunda aşağıya bakın.)
- Onaylanmamış verileriniz var ve verilerinizi kaybedebilirsiniz. O zaman ilk önce onları halletsen iyi olur.
- Alt modülünüz bir
git clean
anlamda temiz değil . Ardından önce bu komutu kullanarak alt modülünüzü temizleyin. (Aşağıya bakınız.)
- Geçmişte desteklenmeyen bir şey yaptınız
git
. O zaman karanlık taraftasın ve işler çirkinleşiyor ve karmaşıklaşıyor. (Belki başka bir makine kullanmak sorunu düzeltir.)
- Belki de bilmediğim başarısız olmanın daha fazla yolu var (Ben sadece biraz
git
güç kullanıcısıyım.)
Olası düzeltmeler takip edilir.
Daha yeni bir tane kullanın git
Makineniz çok eskiyse hayır vardır submodule deinit
Gözlerinde farklı git
. Güncellemenizi istemiyorsanız (veya yapamıyorsanız) git
, daha yeni bir makine kullanın git
! git
tamamen dağıtılmak içindir, bu nedenle git
işi yapmak için başka bir tane kullanabilirsiniz :
workhorse:~/path/to/worktree$ git status --porcelain
hiçbir şey çıktı olmamalıdır ! Varsa, önce şeyleri temizleyin!
workhorse:~/path/to/worktree$ ssh account@othermachine
othermachine:~$ git clone --recursive me@workhorse path/to/worktree/.git TMPWORK && cd TMPWORK
- Şimdi alt modül işlerini yapın
othermachine:~/TMPWORK$ git commit . -m . && exit
workhorse:~/path/to/worktree$ git fetch account@othermachine:TMPWORK/.git
workhorse:~/path/to/worktree$ git merge --ff-only FETCH_HEAD
. Bu işe yaramazsa,git reset --soft FETCH_HEAD
- Şimdi bir şeyleri
git status
temizle, tekrar temiz olana kadar . Bunu yapabilirsiniz, çünkü ilk adım sayesinde daha önce temizlediniz.
Bu othermachine
, bir VM veya Windows altındaki bazı Ubuntu WSL olabilir. Hatta bir chroot
(ama kök olmayan olduğunu varsayıyorum, çünkü eğer öyleyse root
yenisine güncellemek daha kolay olmalı git
).
Not açamıyorsa ssh
üzere ulaşım yolları trainloads vardır git
depoları. Çalışma ağacınızı bazı USB çubuklara ( .git
dizin dahil ) kopyalayabilir ve çubuktan klonlayabilirsiniz. Sadece temiz bir şekilde bir şeyler almak için kopyayı kopyalayın. Alt modüllerinize doğrudan diğer makineden erişilememesi durumunda, bu bir PITA olabilir. Ancak bunun için de bir çözüm var:
git config --add url.NEWURLPREFIX.insteadOf ORIGINALURLPREFIX
Bu çarpımı kullanabilirsiniz ve bu içine kaydedilir $HOME/.gitconfig
. Gibi bir şey
git config --add 'url./mnt/usb/repo/.insteadof' https://github.com/
gibi URL'leri yeniden yazar
https://github.com/XXX/YYY.git
içine
/mnt/usb/repo/XXX/YYY.git
Böyle güçlü git
özelliklere alışmaya başlarsanız çok kolaydır .
Önce şeyleri temizle
Elle temizlemek iyidir, çünkü bu şekilde unuttuğunuz bazı şeyleri tespit edebilirsiniz.
- Git kaydedilmemiş şeylerden şikayet ederse, taahhüt edin ve güvenli bir yere itin.
- Git bazı yemeklerden şikayetçiyse
git status
ve git clean -ixfd
arkadaşınsa
- Seçenekler kaçınmak için deneyin
rm
ve deinit
olabildiğince sürece. Eğer bir Pro iseniz seçenekleri (gibi -f
) git
iyidir. Ama buraya geldiğiniz gibi, muhtemelen submodule
bölgede çok deneyimli değilsiniz . Bu yüzden üzülmektense güvende olsan iyi olur.
Misal:
$ git status --porcelain
M two
$ git submodule deinit two
error: the following file has local modifications:
two
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'two' contains local modifications; use '-f' to discard them
$ cd two
$ git submodule deinit --all
error: the following file has local modifications:
md5chk
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'md5chk' contains local modifications; use '-f' to discard them
$ cd md5chk
$ git submodule deinit --all
error: the following file has local modifications:
tino
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'tino' contains local modifications; use '-f' to discard them
$ cd tino
$ git status --porcelain
?? NEW
$ git clean -i -f -d
Would remove the following item:
NEW
*** Commands ***
1: clean 2: filter by pattern 3: select by numbers 4: ask each
5: quit 6: help
What now> 1
Removing NEW
$ cd ../../..
$ git status --porcelain
$ git submodule deinit two
Cleared directory 'two'
Submodule 'someunusedname' (https://github.com/hilbix/src.git) unregistered for path 'two'
Bakın, buna -f
gerek yok submodule deinit
. İşler temizse, bir git clean
bakıma. Ayrıca git clean -x
gerekli olmadığını da unutmayın . Bu git submodule deinit
, yoksayılan izlenmemiş dosyaları koşulsuz olarak kaldırdığı anlamına gelir . Bu genellikle istediğiniz şeydir, ancak unutmayın. Bazen yok sayılan dosyalar, yeniden hesaplanması saatler veya günler süren önbelleğe alınmış veriler gibi değerli olabilir.
Neden asla çıkarmıyorsunuz $GIT_DIR/modules/<name>/
?
Muhtemelen insanlar önbelleğe alınmış depoyu kaldırmak istiyorlar, çünkü daha sonra bir sorunla karşılaşmaktan korkuyorlar. Bu doğrudur, ancak bu "problem" ile karşılaşmak onu çözmenin doğru yoludur! Düzeltme kolay ve doğru yapıldığından sonsuza dek mutlu yaşayabileceksiniz. Bu, verileri kendiniz kaldırdığınızdan daha zahmetli bir sorunu önler.
Misal:
mkdir tmptest &&
cd tmptest &&
git init &&
git submodule add https://github.com/hilbix/empty.git two &&
git commit -m . &&
git submodule deinit two &&
git rm two &&
git commit -m . &&
git submodule add https://github.com/hilbix/src.git two
Son satır şu hatayı verir:
A git directory for 'two' is found locally with remote(s):
origin https://github.com/hilbix/empty.git
If you want to reuse this local git directory instead of cloning again from
https://github.com/hilbix/src.git
use the '--force' option. If the local git directory is not the correct repo
or you are unsure what this means choose another name with the '--name' option.
Neden bu hata? Çünkü .git/modules/two/
daha önce https://github.com/hilbix/empty.git adresinden dolduruldu ve şimdi başka bir şeyden, yani https://github.com/hilbix/src.git olarak yeniden doldurulacak . Https://github.com/hilbix/empty.git adresinden yeniden doldurursanız bunu görmezsiniz
Şimdi ne yapmalı? Peki, aynen söylendiği gibi yapın! kullanım--name someunusedname
git submodule add --name someunusedname https://github.com/hilbix/src.git two
.gitmodules
sonra benziyor
[submodule "someunusedname"]
path = two
url = https://github.com/hilbix/src.git
ls -1p .git/modules/
verir
someunusedname/
two/
Bu şekilde size dalları geçiş yapabilirsiniz gelecekte / ileri ve geri işlemek ve yeniden herhangi belaya asla nedeniyle, two/
iki farklı (ve muhtemelen uyumsuz) memba depoları sahip. Ve en iyisi: Her ikisini de yerel olarak önbelleğe al.
- Bu sadece sizin için geçerli değil. Deponuzu kullanan diğer herkes için de geçerlidir.
- Ve tarihi kaybetmezsiniz. Eski alt modülün en son sürümünü aktarmayı unuttuysanız, yerel kopyayı girebilir ve daha sonra yapabilirsiniz. Birisinin bazı alt modülleri itmeyi unutmasının oldukça yaygın olduğuna dikkat edin (çünkü bu alışmaya başlayana kadar yeni gelenler için bir PITA'dır
git
).
Ancak önbelleğe alınan dizini kaldırdıysanız, --name
seçenekleri kullanamayacağınız için her iki farklı ödeme birbiri üzerine rastlar , değil mi? Yani her ödeme yaptığınızda, .git/modules/<module>/
dizini tekrar tekrar kaldırmanız gerekebilir . Bu son derece hantaldır ve benzeri bir şeyi kullanmayı zorlaştırır git bisect
.
Bu nedenle bu modül dizinini yer tutucu olarak tutmak için çok teknik bir neden var. Aşağıdaki bir şeyi kaldırmayı öneren kişiler .git/modules/
daha iyi bilmezler veya git bisect
bu tür bir alt modül uyumsuzluğunu geçerse bunun neredeyse imkansız gibi güçlü özellikleri kullanmasını söylemeyi unuturlar .
Başka bir neden yukarıda gösterilmiştir. Şuna bak ls
. Orada ne görüyorsun?
Modülün 2. varyantı two/
altında .git/modules/two/
değil, altında .git/modules/someunusedname/
! Yani gibi şeyler git rm $module; rm -f .git/module/$module
tamamen yanlış! Çıkarmanız module/.git
veya .gitmodules
kaldırmanız gereken doğru şeyi bulmanız gerekir !
Yani sadece diğer çoğu cevap bu tehlikeli tuzağa düşmekle kalmıyor, çok popüler git
uzantılar bile bu hatayı aldı ( şimdi orada düzeltildi )! .git/
Eğer tam olarak yapmazsanız çok daha iyi dizin, ne yaptığınızı!
Felsefi açıdan bakıldığında, tarihi silmek her zaman yanlıştır!
Kuantum mekaniği hariç , her zamanki gibi, ama bu tamamen farklı bir şey.
Muhtemelen tahmin ettiniz : hilbix benim GitHub hesabım.
git rm modulename
verm -rf .git/modules/modulename