Mevcut bir Git alt modülünü Git deposunda nasıl taşırım?


356

Git süper projemdeki Git alt modülünün dizin adını değiştirmek istiyorum.

Dosyamda şu girdinin bulunduğunu varsayalım .gitmodules:

[submodule ".emacs.d/vimpulse"]  
path = .emacs.d/vimpulse  
url = git://gitorious.org/vimpulse/vimpulse.git

Önce .emacs.d/vimpulsedizini .emacs.d/vendor/vimpulse( burada ve burada açıklanmıştır) silmeden ve sonra yeniden eklemeden taşımak için ne yazmam gerekiyor?

Git gerçekten alt modül etiketindeki tüm yola ihtiyaç duyuyor mu

[submodule ".emacs.d/vimpulse"]

ya da sadece alt projenin adını saklamak mümkün mü?

[submodule "vimpulse"]

NOT: OP kendi sorusunu git mvdoğrudan sorudaki komutla cevaplar.
Dan Rosenstark

ANCAK, böyle kullanamazsınız git mv. deinitArdından stackoverflow.com/a/18892438/8047rm belirtildiği şekilde kullanın .
Dan Rosenstark

14
@Yar: en azından git 2.0.0'da, git mv sadece alt modüller için de çalışıyor , başka bir şeye gerek yok.
Pedro Romano

9
Git 1.8.5hareketli alt modüllerinden başlayarak , git mvkomut kullanılarak yerel olarak desteklenir ( ilk önce @thisch tarafından bağlanan sürüm notlarından ). Burada
dennisschagt

git mvalt modülü çalışma alanında taşır ve alt modül .git dosyalarını doğru olarak güncelleştirir, ancak üst deponun .git / modules klasöründeki alt klasör aynı kalır - sorun değil mi? (Windows'ta git 2.19.0 kullanıyorum)
yoyo

Yanıtlar:


377

Not: Yorumlarda belirtildiği gibi, bu cevap git'in eski sürümlerinde gerekli olan adımları ifade eder. Git'in artık hareketli alt modüller için yerel desteği var:

Git 1.8.5'den bu yana, git mv old/submod new/submodbeklendiği gibi çalışır ve sizin için tüm sıhhi tesisat yapar. Git 1.9.3 veya daha yenisini kullanmak isteyebilirsiniz, çünkü alt modül taşıma düzeltmeleri içerir.


İşlem, bir alt modülü nasıl sileceğinize benzer (bkz. Bir alt modülü nasıl kaldırabilirim? ):

  1. Düzenleme .gitmodulesuygun altmodülün yolunu değiştirmek ve birlikte endekste koydu ve git add .gitmodules.
  2. Gerekirse, alt modülün ( mkdir -p new/parent) yeni konumunun üst dizinini oluşturun .
  3. Tüm içeriği eski klasörden yeni dizine taşı ( mv -vi old/parent/submodule new/parent/submodule).
  4. Git'in bu dizini ( git add new/parent) izlediğinden emin olun .
  5. İle eski dizini kaldırın git rm --cached old/parent/submodule.
  6. .git/modules/old/parent/submoduleİçeriğinin bulunduğu dizini adresine taşıyın .git/modules/new/parent/submodule.
  7. Düzen .git/modules/new/parent/configdosya, emin yeni konumlara worktree öğe noktaları, bu nedenle bu örnekte bunun olması gerektiğini yapmak worktree = ../../../../../new/parent/module. Genellikle ..o yerde doğrudan yolda iki dizin daha olmalıdır .
  8. Dosyayı düzenleyin new/parent/module/.git, içindeki yolun ana proje .gitklasörü içinde doğru yeni konumu gösterdiğinden emin olun , bu nedenle bu örnekte gitdir: ../../../.git/modules/new/parent/submodule.

    git status çıktı daha sonra benim için şöyle görünüyor:

    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       modified:   .gitmodules
    #       renamed:    old/parent/submodule -> new/parent/submodule
    #
    
  9. Son olarak, değişiklikleri yapın.


37
.Gitmodules'ü güncellediğinizde, hem bu pathyapılandırmayı hem de alt modülün adını güncellediğinizden emin olun . Örneğin, bar foo / modül hareketli / sen .gitmodules bölümünde değiştirmeniz gerekir modülü [submodule "foo/module"]için [submodule "bar/module"], ve aynı bölümünde path = foo/moduleetmek path = bar/module. Ayrıca, .git / config bölümünde değiştirmek gerekir [submodule "foo/module"]için [submodule "bar/module"].
wilhelmtell

3
Benim için de işe yaramadı ... Bulduğum en yakın çözüm bir alt modülü (bir acıyı) silmek ve daha sonra farklı bir konuma tekrar eklemek.
Pablo Olmos de Aguilera C.

33
Çok önemli bir not: fatal: 'git status --porcelain' failed in...Sadece alt modüldeki .git dosyalarını veya dizinlerini silerseniz.
antitoksik

19
Bu yazı böyle düzenleme gibi birkaç adım, özlüyor gibi görünüyor .git/modules/old/parent/submodulegüncelleyerek yeni konuma taşıyarak, gitdiriçinde old/parent/submodule/.git...
SZX

38
Git 1.8.5'den bu yana, git mv old/submod new/submodbeklendiği gibi çalışır ve sizin için tüm sıhhi tesisat yapar. Muhtemelen git 1.9.3+ kullanmak istiyorsunuz çünkü alt modül taşıma düzeltmeleri içeriyor.
Valloric

232

Valloric'in yukarıdaki yorumundan alınan en modern cevap:

  1. Git 1.9.3'e yükseltin (veya alt modül iç içe geçmiş alt modüller içeriyorsa 2.18 )
  2. git mv old/submod new/submod
  3. Daha sonra .gitmodules ve submodule dizini zaten bir taahhüt için hazırlanmıştır (bunu ile doğrulayabilirsiniz git status.)
  4. Değişiklikleri yapın git commitve hazırsınız!

Bitti!


3
Bu , taşınan alt modülün içindeki bir alt modül 1.9.3 dışında gerçekten işe yaradı . Biraz manuel temizlik gerekiyordu.
Pascal

3
Bu , sürüm notlarında1.8.5 açıklandığı gibi sürümde zaten çalışmalıdır .
dennisschagt

6
Bu cevap 1000 upvotes almalı, repo'mda yukarıda açıklanan adımları yaparken neredeyse bir karışıklık yaptım, gerçekten StackOverflow'un bu durum için bir kullanıcı tabanı olmalı.
MGP

5
Vay be, bu bir cazibe gibi çalıştı (git 1.9.5), keşke seçilen cevap olsaydı.
Alex Ilyaev

7
Bunun yapmadığı bir şey, alt modülün başlangıç ​​etiketini değiştirmemesidir. .gitmodulesDosyayı kontrol ederseniz old/submod, yol değiştirilirken hala alt modülün etiketi olarak kullanılır. Etiketi de değiştirmek için, modül dizini yolunu gerçekten taşımanız .gitve etiketi manuel olarak değiştirmeniz gerekir .gitmodules.
CMCDragonkai

55

Benim durumumda, bir alt modülü bir dizinden alt dizine taşımak istedim, örneğin "AFNetworking" -> "ext / AFNetworking". İzlediğim adımlar şunlardır:

  1. Alt modül adını ve yolunu "ext / AFNetworking" olarak değiştiren .gitmodules düzenleyin
  2. Alt modülün git dizinini ".git / modules / AFNetworking" öğesinden ".git / modules / ext / AFNetworking" klasörüne taşıyın
  3. Kitaplığı "AFNetworking" den "ext / AFNetworking" e taşıyın
  4. ".Git / modules / ext / AFNetworking / config" dosyasını düzenleyin ve [core] worktreesatırı düzeltin . Mine değiştirildi ../../../AFNetworkingetmek../../../../ext/AFNetworking
  5. "Ext / AFNetworking / .git" dosyasını düzenleyin ve düzeltin gitdir. Mine değiştirildi ../.git/modules/AFNetworkingetmek../../git/modules/ext/AFNetworking
  6. git add .gitmodules
  7. git rm --cached AFNetworking
  8. git submodule add -f <url> ext/AFNetworking

Sonunda git durumunda gördüm:

matt$ git status
# On branch ios-master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   .gitmodules
#   renamed:    AFNetworking -> ext/AFNetworking

Et voila. Yukarıdaki örnek, görevin karmaşıklığı üzerinde büyük bir fark yaratan dizin derinliğini değiştirmez ve alt modülün adını değiştirmez (bu gerçekten gerekli olmayabilir, ancak ne ile tutarlı olmak için yaptım bu yola yeni bir modül ekleseydim olurdu.)


4
Teşekkürler Matt. Kabul edilen cevapta kayboldum. Temel davadan daha fazlasını kapsadığınız için teşekkür ederiz. Bu bir cazibe gibi çalıştı.
Andrew

.Git / modules yollarını karıştırmanız veya alt modülün adını değiştirmeniz gerekmez (arand ve Bob Bell'den bahsedildiği gibi). Yine de, bunu yapmak işleri daha temiz tutabilir.
gatoatigrado

Herhangi bir alt alt modül için 2, 3, 4 ve 5. adımları yinelemeli olarak yapmayı unutmayın.
herzbube

22

[Güncelleme: 2014-11-26] Yar aşağıda güzel bir şekilde özetlediği gibi, herhangi bir şey yapmadan önce alt modülün URL'sini bildiğinizden emin olun. Bilinmiyorsa, .git/.gitmodulesanahtarı açın ve inceleyin submodule.<name>.url.

Benim için işe yarayan eski alt modülü kullanarak git submodule deinit <submodule>onu kaldırmaktıgit rm <submodule-folder> . Ardından alt modülü yeni klasör adıyla tekrar ekleyin ve tamamlayın. Devam etmeden önce git durumunun kontrol edilmesi, yeni alt adın yeni adla değiştirildiğini ve .gitmodule'un değiştirildiğini gösterir.

$ git submodule deinit foo
$ git rm foo
$ git submodule add https://bar.com/foo.git new-foo
$ git status
renamed:    foo -> new-foo
modified:   .gitmodules
$ git commit -am "rename foo submodule to new-foo"

1
Bunun için git 1.8.3 veya üstü gerekir. Git'inizi
Michael Cole

1
Veya daha iyi bir yol: sudo add-apt-repository ppa: git-core / ppa sudo apt-get güncellemesi sudo apt-get install git
Michael Cole

@MichaelCole Teşekkürler! Haklısın! Bkz. Git-1.8.3 Sürüm Notları . FYI: Ubuntu-13.10 (Saucy Salamander) Git-1.8.3.2'ye sahip , ancak ppa olduğunu bilmek güzel . Ayrıca, IMHO git alt ağaç birleştirme stratejisi daha iyi bir yaklaşımdır; Kendi projelerim için alt modülleri terk ettim. Mevcut projeler için hala anlaşılması iyi.
Mark Mikofski

Birkaç çözüm denedim ama seninki en iyisi. Yalnızca komut dosyasını kullanın, böylece herhangi bir git dosyasını değiştirmeniz gerekmez (ve olmamalıdır). Teşekkürler!
nahung89

12

Hile .git, alt modül dizininin artık ana depoda, altında tutulduğunu .git/modulesve her alt modülün kendisine işaret eden bir .gitdosyası olduğunu anlıyor gibi görünüyor . Şimdi ihtiyacınız olan prosedür:

  • Alt modülü yeni yuvasına taşıyın.
  • Düzenleme .gitsubmodule en çalışma dizinindeki dosya ve buna usta deponun sağ dizine işaret eden içeren yolunu değiştirmek .git/modulesdizinde.
  • Ana havuzun .git/modulesdizinini girin ve alt modülünüze karşılık gelen dizini bulun.
  • Düzen configdosyasını güncelleyerek worktreeo alt modül en çalışma dizininin yeni konuma işaret edecek biçimde yolu.
  • Düzenleme .gitmodulesaltmodülün çalışma dizinine yolunu güncelleme usta depo kök dosyası.
  • git add -u
  • git add <parent-of-new-submodule-directory>(Alt modül dizininin kendisini değil, üst öğesini eklemeniz önemlidir .)

Birkaç not:

  • [submodule "submodule-name"]Çizgiler .gitmodulesve .git/configbirbirleriyle aynı olmalıdır, ama başka bir şey karşılık gelmez.
  • Alt modül çalışma dizini ve .gitdizini doğru şekilde işaret etmelidir.
  • .gitmodulesVe .git/configdosyalar senkronize edilmelidir.

9

"[Submodule" den sonra tırnak işaretleri içindeki dize önemli değil. İsterseniz "foobar" olarak değiştirebilirsiniz. ".Git / config" içindeki eşleşen girişi bulmak için kullanılır.

Bu nedenle, "git submodule init" komutunu çalıştırmadan önce değişikliği yaparsanız, düzgün çalışır. Değişikliği yaparsanız (veya değişikliği birleştirme yoluyla alırsanız) .git / config dosyasını el ile düzenlemeniz veya "git submodule init" komutunu yeniden çalıştırmanız gerekir. İkincisini yaparsanız, eski adı .git / config olan zararsız bir "mahsur" girişe bırakılırsınız.


Bu gerçekten sinir bozucu, ama haklısın. En kötü yanı, sadece URL'yi değiştirirseniz, git init'i çalıştırmak onu güncellemiyor gibi görünüyorsa, .git / config'i manuel olarak düzenlemeniz gerekir.
crimson_penguin

1
bu durumda git submodule syncdeğişikliği .git/configotomatik olarak yayar
CharlesB

9

Standart komutları kullanarak yeni bir alt modül ekleyebilir ve eski alt modülü kaldırabilirsiniz. (.git içindeki yanlışlıkla hataları önlemelidir)

Örnek kurulum:

mkdir foo; cd foo; git init; 
echo "readme" > README.md; git add README.md; git commit -m "First"
## add submodule
git submodule add git://github.com/jquery/jquery.git
git commit -m "Added jquery"
## </setup example>

'Jquery' yi 'satıcı / jquery / jquery' ye taşıyın:

oldPath="jquery"
newPath="vendor/jquery/jquery"
orginUrl=`git config --local --get submodule.${oldPath}.url`

## add new submodule
mkdir -p `dirname "${newPath}"`
git submodule add -- "${orginUrl}" "${newPath}"

## remove old submodule
git config -f .git/config --remove-section "submodule.${oldPath}"
git config -f .gitmodules --remove-section "submodule.${oldPath}"
git rm --cached "${oldPath}"
rm -rf "${oldPath}"              ## remove old src
rm -rf ".git/modules/${oldPath}" ## cleanup gitdir (housekeeping)

## commit
git add .gitmodules
git commit -m "Renamed ${oldPath} to ${newPath}"

Büyük alt modüller için bonus yöntemi:

Alt modül büyükse ve klonu beklememeyi tercih ediyorsanız, eski alt kaynağı özgün olarak kullanarak yeni alt modülü oluşturabilir ve ardından başlangıç ​​noktasını değiştirebilirsiniz.

Örnek (aynı örnek kurulumu kullanın)

oldPath="jquery"
newPath="vendor/jquery/jquery"
baseDir=`pwd`
orginUrl=`git config --local --get submodule.${oldPath}.url`

# add new submodule using old submodule as origin
mkdir -p `dirname "${newPath}"`
git submodule add -- "file://${baseDir}/${oldPath}" "${newPath}"

## change origin back to original
git config -f .gitmodules submodule."${newPath}".url "${orginUrl}"
git submodule sync -- "${newPath}"

## remove old submodule
...

Head kullanmıyorsanız, adresindeki modülün doğru sürümünü de kontrol etmeniz gerekebilir newPath.
paulmelnikow

2

Verilen çözüm benim için çalışmadı, ancak benzer bir sürüm ...

Bu klonlanmış bir havuzdadır, bu nedenle alt modül git depoları üst depolarda bulunur. Tüm katyonlar en üst depodan:

  1. .Gitmodules düzenleyin ve söz konusu alt modül için "path =" ayarını değiştirin. (Etiketi değiştirmenize veya bu dosyayı dizine eklemenize gerek yoktur.)

  2. .Git / modules / name / config dosyasını düzenleyin ve söz konusu alt modül için "worktree =" ayarını değiştirin

  3. Çalıştırmak:

    mv submodule newpath/submodule
    git add -u
    git add newpath/submodule
    

Havuzların atomik mi yoksa göreceli alt modüller mi olduğunu fark ettim, benim durumumda göreceli (alt modül / .git, topproject / .git / modüller / alt modül)


2

Sadece git-submodule-move kabuk komut dosyasını kullanın .


Heh, bu soruyu tekrar aradım ve daha yüksek oy alan cevaplardan birini kullandım ve şimdi aşağı kaydırıp unutmuş olduğum önceki cevabımı görseydim.
Flimm

2

Dün bu sıkıntıdan geçtim ve bu cevap mükemmel çalıştı. İşte netlik için adımlarım:

  1. Alt modülün teslim edildiğinden ve sunucusuna itildiğinden emin olun. Ayrıca hangi dalda olduğunu bilmeniz gerekir.
  2. Alt modülünüzün URL'sine ihtiyacınız var! Kullanın more .gitmodulesçünkü alt modülü sildiğinizde etrafında olmayacak
  3. Şimdi kullanabilir deinit, rmdaha sonra vesubmodule add

MİSAL

KOMUTLARI

    git submodule deinit Classes/lib/mustIReally
    git rm foo
    git submodule add http://developer.audiob.us/download/SDK.git lib/AudioBus

    # do your normal commit and push
    git commit -a 

NOT: git mv bunu yapmaz. Hiç.


3
İyi özet. +1 git mv, Git'in son sürümlerinde daha iyi olmalıdır.
VonC

@VonC Git 1.8.5 üzerinde test ettim, bunun ne kadar iyi olduğuna eminim mv. Teşekkürler!
Dan Rosenstark
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.