Gitリポジトリ内の既存のGitサブモジュールを移動するにはどうすればよいですか?


356

私のGitスーパープロジェクトでGitサブモジュールのディレクトリ名を変更したいと思います。

私の.gitmodulesファイルに次のエントリがあるとしましょう:

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

最初にそれを削除せずに.emacs.d/vimpulseディレクトリを移動するために何を入力する必要がありますか.emacs.d/vendor/vimpulseここここで説明さ ています)、次にそれを再度追加します。

Gitは本当にサブモジュールタグの完全なパスを必要としますか

[submodule ".emacs.d/vimpulse"]

または、サブプロジェクトの名前だけを保存することもできますか?

[submodule "vimpulse"]

注:OPは、自分の質問に対してgit mv、質問内のコマンドで答えます。
Dan Rosenstark、2014

ただし、git mvこのように使用することはできません。deinit次にrm 、指定されたstackoverflow.com/a/18892438/8047を使用します。
Dan Rosenstark、2014

14
@Yar:少なくともgit 2.0.0では、サブモジュールでもgit mv 機能するだけで、他には何も必要ありません。
ペドロロマーノ2014年

9
Gitから始めて、1.8.5サブモジュールの移動は、git mvコマンドを使用してネイティブにサポートされます(最初に@thischによってリンクされたリリースノートから)。こちら
denisschagt 2014年

git mvワークスペースでサブモジュールを移動し、サブモジュールの.gitファイルを正しく更新しますが、親リポジトリの.git / modulesフォルダー内のサブフォルダーは同じままです-それでいいですか?(私はWindowsでgit 2.19.0を使用しています)
yoyo

回答:


377

注:コメントで述べたように、この回答は古いバージョンのgitで必要な手順を示しています。Gitは、サブモジュールの移動をネイティブでサポートしています。

git 1.8.5以降git mv old/submod new/submod、期待どおりに動作し、すべての配管を行います。サブモジュールの移動に関する修正が含まれているため、git 1.9.3以降を使用することをお勧めします。


プロセスは、サブモジュールを削除する方法と似ています(サブモジュールを削除するにどうすればよいですか?を参照):

  1. .gitmodulesサブモジュールのパスを適切に編集および変更し、でインデックスに入れgit add .gitmodulesます。
  2. 必要に応じて、サブモジュールの新しい場所の親ディレクトリを作成します(mkdir -p new/parent)。
  3. すべてのコンテンツを古いディレクトリから新しいディレクトリに移動します(mv -vi old/parent/submodule new/parent/submodule)。
  4. Gitがこのディレクトリを追跡していることを確認してください(git add new/parent)。
  5. で古いディレクトリを削除しgit rm --cached old/parent/submoduleます。
  6. .git/modules/old/parent/submoduleすべてのコンテンツを含むディレクトリをに移動し.git/modules/new/parent/submoduleます。
  7. .git/modules/new/parent/configファイルを編集し、worktreeアイテムが新しい場所を指していることを確認しますworktree = ../../../../../new/parent/module。この例では、このようにする必要があります。通常..、その場所の直接パスには、2つ以上のディレクトリが必要です。
  8. この例では、ファイルを編集し、ファイル内new/parent/module/.gitのパスがメインプロジェクト.gitフォルダー内の正しい新しい場所を指していることを確認しますgitdir: ../../../.git/modules/new/parent/submodule

    git status その後、出力は次のようになります。

    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       modified:   .gitmodules
    #       renamed:    old/parent/submodule -> new/parent/submodule
    #
    
  9. 最後に、変更をコミットします。


37
.gitmodulesを更新するときは、そのpath構成とサブモジュールの名前の両方を更新してください。例えば、バーするFOO /モジュールを動かすには/あなたが.gitmodulesセクションに変更しなければならないモジュール[submodule "foo/module"]には[submodule "bar/module"]、その同じセクションの下path = foo/modulepath = bar/module。また、.git / configでセクション[submodule "foo/module"]をに変更する必要があります[submodule "bar/module"]
ヴィルヘルムテル

3
それも私にはうまくいきませんでした...私が見つけた最も近い解決策は、サブモジュールを削除し(苦痛)、それを別の場所に再度追加することです。
パブロオルモスデアギレラC.

33
非常に重要な注意:fatal: 'git status --porcelain' failed in...サブモジュール内の.gitファイルまたはディレクトリをすべて削除した場合。
2012年

19
この投稿では、編集.git/modules/old/parent/submodule、新しい場所への移動、更新などのいくつかの手順がgitdirold/parent/submodule/.git
欠落

38
git 1.8.5以降git mv old/submod new/submod、期待どおりに動作し、すべての配管を行います。サブモジュールの移動に関する修正が含まれているため、おそらくgit 1.9.3+を使用する必要があります。
Valloric 2014年

232

上記のValloricのコメントからの最新の回答:

  1. (またはGitの1.9.3にアップグレードサブモジュールは、ネストされたサブモジュールが含まれている場合は2.18
  2. git mv old/submod new/submod
  3. その後、.gitmodulesとサブモジュールディレクトリは既にコミット用にステージングされています(これはgit status。で確認できます)。
  4. 変更をコミットして、準備完了git commitです!

できた!


3
これは確かに、移動したサブモジュール内のサブモジュールを1.9.3 除いて機能しました。手動でクリーンアップする必要がありました。
Pascal、

3
これは、リリースノートに1.8.5記載されているバージョンですでに動作しているはずです。
dennisschagt 2014年

6
この回答は1000票を獲得するはずです。私は上記の手順を実行する私のリポジトリでほとんど混乱しました。実際、StackOverflowはこの状況のユースケースを持っているはずです。
MGP

5
うわー、これは魅力のように機能しました(git 1.9.5)、それが選択された答えであったと思います。
Alex Ilyaev 2015年

7
これが行わないことの1つは、サブモジュールの初期ラベルを変更しないことです。.gitmodulesファイルを確認するとold/submod、パスが変更されている間も、サブモジュールのラベルとして使用されます。ラベルも変更するには、実際にモジュールのディレクトリパスを内に移動して.gitから、で手動でラベルを変更する必要があるようです.gitmodules
CMCDragonkai 2017年

55

私の場合、サブモジュールを1つのディレクトリからサブディレクトリに移動したいと思っていました(例: "AFNetworking"-> "ext / AFNetworking")。これらは私が従ったステップです:

  1. .gitmodulesを編集して、サブモジュールの名前とパスを「ext / AFNetworking」に変更します。
  2. サブモジュールのgitディレクトリを「.git / modules / AFNetworking」から「.git / modules / ext / AFNetworking」に移動します
  3. ライブラリを「AFNetworking」から「ext / AFNetworking」に移動します
  4. 「.git / modules / ext / AFNetworking / config」を編集して、[core] worktree行を修正します。鉱山がから../../../AFNetworkingに変更されました../../../../ext/AFNetworking
  5. 「ext / AFNetworking / .git」を編集して修正しますgitdir。鉱山がから../.git/modules/AFNetworkingに変更されました../../git/modules/ext/AFNetworking
  6. git add .gitmodules
  7. git rm --cached AFNetworking
  8. git submodule add -f <url> ext/AFNetworking

最後に、私はgitステータスで見ました:

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

出来上がり。上記の例は、ディレクトリの深さを変更しないため、タスクの複雑さに大きな違いがあり、サブモジュールの名前は変更されません(実際には必要ないかもしれませんが、そのパスに新しいモジュールを追加した場合に発生します。)


4
マットに感謝します。私は受け入れられた答えで迷いました。ベースケース以上をカバーしていただきありがとうございます。これは魅力のように働きました。
Andrew Hubbs 2013年

.git / modulesパスをシャッフルしたり、サブモジュールの名前を変更したりする必要はありません(arandとBob Bellが言及しているように)。しかし、そうすることで物事をよりクリーンに保つことができます。
gatoatigrado 2013年

サブサブモジュールに対してステップ2、3、4、および5を再帰的に実行することを忘れないでください。
herzbube 2013年

22

[更新:2014-11-26] Yarが以下にまとめているように、何かを行う前に、サブモジュールのURLを確認してください。不明な場合.git/.gitmodulesは、鍵を開いて調べますsubmodule.<name>.url

私のために働いたのは git submodule deinit <submodule>続けてを使用して古いサブモジュール削除するgit rm <submodule-folder>。次に、サブフォルダーを新しいフォルダー名で再度追加してコミットします。コミットする前にgitステータスを確認すると、古いサブモジュールの名前が新しい名前に変更され、.gitmoduleが変更されています。

$ 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
これにはgit 1.8.3以降が必要です。gitのアップグレードについては、この投稿を参照してください。evgeny
Michael Cole 14

1
または、より良い方法:sudo add-apt-repository ppa:git-core / ppa sudo apt-get update sudo apt-get install git
Michael Cole

@MichaelColeありがとう!その通りその通り!Git-1.8.3リリースノートを参照してください。参考:Ubuntu-13.10(Saucy Salamander)にはGit-1.8.3.2がありますが、ppaがあることを知っておくと役に立ちます。また、IMHO gitサブツリーのマージ戦略の方が優れています。私は自分のプロジェクトのサブモジュールを放棄しました。既存のプロジェクトについては、まだ理解しておくとよいでしょう。
Mark Mikofski、2014

私はいくつかの解決策を試しましたが、あなたの解決策が最高です。コマンドラインのみを使用するので、gitファイルを変更する必要はありません(変更してはいけません)。ありがとう!
nahung89

12

トリックは.git、サブモジュールのディレクトリがマスターリポジトリのに保存され、.git/modules各サブモジュールが.gitそれを指すファイルを持っていることを理解しているようです。これは今必要な手順です:

  • サブモジュールを新しいホームに移動します。
  • .gitサブモジュールの作業ディレクトリにあるファイルを編集し、そこに含まれるパスを変更して、マスターリポジトリの.git/modulesディレクトリ内の正しいディレクトリを指すようにします。
  • マスターリポジトリの.git/modulesディレクトリを入力し、サブモジュールに対応するディレクトリを見つけます。
  • configファイルを編集しworktree、サブモジュールの作業ディレクトリの新しい場所を指すようにパスを更新します。
  • .gitmodulesマスターリポジトリのルートにあるファイルを編集し、サブモジュールの作業ディレクトリへのパスを更新します。
  • git add -u
  • git add <parent-of-new-submodule-directory>(サブモジュールディレクトリ自体ではなく、を追加することが重要です。)

いくつかのメモ:

  • との[submodule "submodule-name"]行は互いに一致し.gitmodulesている.git/config必要がありますが、他の何にも対応していません。
  • サブモジュールの作業ディレクトリと.gitディレクトリは、互いに正しくポイントしている必要があります。
  • ファイル同期する必要があります。.gitmodules.git/config

9

「[サブモジュール」の後に引用符で囲まれた文字列は関係ありません。必要に応じて、「foobar」に変更できます。「.git / config」で一致するエントリを見つけるために使用されます。

したがって、「git submodule init」を実行する前に変更を加えると、問題なく動作します。変更を加える場合(またはマージによって変更を取得する場合)は、.git / configを手動で編集するか、「git submodule init」を再度実行する必要があります。後者を実行すると、.git / configに古い名前の無害な「取り残された」エントリが残ります。


これは本当に迷惑ですが、あなたは正しいです。最悪の部分は、URLを変更しただけの場合、git initを実行しても更新されないようで、.git / configを手動で編集する必要があることです。
crimson_penguin 2012年

1
この場合git submodule sync、変更は.git/config自動的に伝播されます
CharlesB

9

標準のコマンドを使用して、新しいサブモジュールを追加し、古いサブモジュールを削除できます。(.git内の偶発的なエラーを防止する必要があります)

設定例:

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」を「vendor / jquery / jquery」に移動します。

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}"

大きなサブモジュールのボーナスメソッド:

サブモジュールが大きく、クローンを待たない場合は、古いものを起点として新しいサブモジュールを作成し、起点を切り替えることができます。

例(同じ設定例を使用)

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を使用していない場合は、モジュールの正しいバージョンをでチェックアウトする必要がある場合もありますnewPath
paulmelnikow 2013年

2

与えられた解決策は私にとってはうまくいきませんでしたが、同様のバージョンはうまくいきました...

これは複製されたリポジトリを使用するため、サブモジュールgit reposはトップリポジトリの.git dirに含まれています。すべてのカチオンは、トップリポジトリからのものです。

  1. .gitmodulesを編集し、問題のサブモジュールの「path = "設定を変更します。(ラベルを変更したり、このファイルをインデックスに追加したりする必要はありません。)

  2. .git / modules / name / configを編集し、問題のサブモジュールの「worktree = "設定を変更します

  3. 実行:

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

リポジトリがアトミック、または相対サブモジュールである場合、違いがあるのでしょうか。私の場合、それは相対でした(submodule / .gitは、topproject / .git / modules / submoduleへの参照です)


2

シェルスクリプトgit-submodule-moveを使用するだけです。


えっと、私はこの質問をもう一度調べて、投票数の多い回答の1つを使用しました。次に、下にスクロールして、忘れていた私の以前の回答を確認したいと思います。
Flimm 2014年

2

私は昨日この試練を経験しましたが、この答えは完璧に機能しました。明確にするために、ここに私の手順を示します。

  1. サブモジュールがチェックインされ、サーバーにプッシュされていることを確認してください。また、そのブランチがどこにあるかを知る必要があります。
  2. サブモジュールのURLが必要です!more .gitmodules一度サブモジュールを削除すると、それは周りに存在しないので使用します
  3. 今、あなたは使用することができdeinitrmその後、submodule add

コマンド

    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 

注: git mvはこれを行いません。全然。


3
良い要約。git mvただし、Gitの最新バージョンでは+1の方が適しています。
VonC 2014

@VonC私はgit 1.8.5でテストしましたmv。ありがとう!
Dan Rosenstark、2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.