87

gitリポジトリであるフォルダがあります。いくつかのファイルと.gitmodulesファイルが含まれています。さて、私がそうするgit initgit submodule init、後者のコマンド出力は何もありません。gitが.gitmodulesファイルで定義されたサブモジュールをgit submodule add手動で再度実行せずに表示できるようにするにはどうすればよいですか?

更新:これは私の.gitmodulesファイルです:

[submodule "vim-pathogen"]
    path = vim-pathogen
    url = git://github.com/tpope/vim-pathogen.git
[submodule "bundle/python-mode"]
    path = bundle/python-mode
    url = git://github.com/klen/python-mode.git
[submodule "bundle/vim-fugitive"]
    path = bundle/vim-fugitive
    url = git://github.com/tpope/vim-fugitive.git
[submodule "bundle/ctrlp.vim"]
    path = bundle/ctrlp.vim
    url = git://github.com/kien/ctrlp.vim.git
[submodule "bundle/vim-tomorrow-theme"]
    path = bundle/vim-tomorrow-theme
    url = git://github.com/chriskempson/vim-tomorrow-theme.git

そしてここにこのディレクトリのリストがあります:

drwxr-xr-x  4 evgeniuz 100 4096 июня  29 12:06 .
drwx------ 60 evgeniuz 100 4096 июня  29 11:43 ..
drwxr-xr-x  2 evgeniuz 100 4096 июня  29 10:03 autoload
drwxr-xr-x  7 evgeniuz 100 4096 июня  29 12:13 .git
-rw-r--r--  1 evgeniuz 100  542 июня  29 11:45 .gitmodules
-rw-r--r--  1 evgeniuz 100  243 июня  29 11:18 .vimrc

だから、間違いなく、それはトップレベルにあります。gitディレクトリは変更されず、変更されるだけgit initです

4

7 に答える 7

115

git submodule init初期化のために、すでにインデックスにある(つまり「ステージングされた」)サブモジュールのみを考慮します。を解析する短いスクリプトを作成し、実行.gitmodulesごとにurl次のようにします。path

git submodule add <url> <path>

たとえば、次のスクリプトを使用できます。

#!/bin/sh

set -e

git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
    while read path_key path
    do
        url_key=$(echo $path_key | sed 's/\.path/.url/')
        url=$(git config -f .gitmodules --get "$url_key")
        git submodule add $url $path
    done

git-submodule.shこれは、スクリプト自体がファイルを解析する方法に基づいてい.gitmodulesます。

于 2012-06-29T08:54:32.943 に答える
15

@Mark Longairの回答を拡張して、次のプロセスのステップ2と3を自動化するbashスクリプトを作成しました。

  1. 「ボイラープレート」リポジトリのクローンを作成して、新しいプロジェクトを開始します
  2. .gitフォルダーを削除し、新しいリポジトリとして再初期化します
  3. サブモジュールを再初期化し、フォルダを削除する前に入力を求めます

#!/bin/bash

set -e
rm -rf .git
git init

git config -f .gitmodules --get-regexp '^submodule\..*\.path$' > tempfile

while read -u 3 path_key path
do
    url_key=$(echo $path_key | sed 's/\.path/.url/')
    url=$(git config -f .gitmodules --get "$url_key")

    read -p "Are you sure you want to delete $path and re-initialize as a new submodule? " yn
    case $yn in
        [Yy]* ) rm -rf $path; git submodule add $url $path; echo "$path has been initialized";;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac

done 3<tempfile

rm tempfile

注:サブモジュールは、ボイラープレートリポジトリと同じコミットではなく、マスターブランチの先端でチェックアウトされるため、手動で行う必要があります。

git configからの出力を読み取りループにパイプすると、入力のプロンプトで問題が発生したため、代わりに一時ファイルに出力します。私の最初のbashスクリプトの改善は大歓迎です:)


Mark、https ://stackoverflow.com/a/226724/193494、bash:readを使用しているループ内のネストされたインタラクティブ読み取り、およびこのソリューションに到達するのを助けてくれたtnettenba @ chat.freenode.netに大いに感謝します!

于 2013-03-08T20:06:49.727 に答える
7

優れた@MarkLongairの回答を拡張して、ブランチとリポジトリの名前に関するサブモジュールを追加します。

#!/bin/sh

set -e

git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
    while read path_key path
    do
        name=$(echo $path_key | sed 's/\submodule\.\(.*\)\.path/\1/')
        url_key=$(echo $path_key | sed 's/\.path/.url/')
        branch_key=$(echo $path_key | sed 's/\.path/.branch/')
        url=$(git config -f .gitmodules --get "$url_key")
        branch=$(git config -f .gitmodules --get "$branch_key" || echo "master")
        git submodule add -b $branch --name $name $url $path || continue
    done
于 2018-11-12T20:30:14.630 に答える
3

同様の問題がありました。git submodule init黙って失敗していた。

私がしたとき:

git submodule add <url> <path>

私が得た:

The following path is ignored by one of your .gitignore files: ...

.gitignore(d)パスが原因である可能性があると思います。

于 2014-06-27T00:20:32.040 に答える
3

@mark-longairによるスクリプトの更新バージョン。これはブランチもサポートし、サブモジュールの一部がすでにに存在する場合を処理し、.git/config必要に応じてサブモジュールパスと同じ名前の既存のディレクトリをバックアップします。

git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
    while read path_key path
    do
        url_key=$(echo $path_key | sed 's/\.path/.url/');
        branch_key=$(echo $path_key | sed 's/\.path/.branch/');
        # If the url_key doesn't yet exist then backup up the existing
        # directory if necessary and add the submodule
        if [ ! $(git config --get "$url_key") ]; then
            if [ -d "$path" ] && [ ! $(git config --get "$url_key") ]; then
                mv "$path" "$path""_backup_""$(date +'%Y%m%d%H%M%S')";
            fi;
            url=$(git config -f .gitmodules --get "$url_key");
            # If a branch is specified then use that one, otherwise
            # default to master
            branch=$(git config -f .gitmodules --get "$branch_key");
            if [ ! "$branch" ]; then branch="master"; fi;
            git submodule add -f -b "$branch" "$url" "$path";
        fi;
    done;

# In case the submodule exists in .git/config but the url is out of date

git submodule sync;

# Now actually pull all the modules. I used to use this...
#
# git submodule update --init --remote --force --recursive
# ...but the submodules would check out in detached HEAD state and I 
# didn't like that, so now I do this...

git submodule foreach --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)';
于 2020-01-07T19:34:05.360 に答える
1

git configしばらく経ちましたが、一度だけ呼び出し、スクリプトを必要とせず、ブランチも処理するこのバージョンを共有したいと思います。

git config -f .gitmodules --get-regexp '^submodule\.' | perl -lane'
$conf{$F[0]} = $F[1]}{
@mods = map {s,\.path$,,; $_} grep {/\.path$/} keys(%conf);
sub expand{$i = shift; map {$conf{$i . $_}} qw(.path .url .branch)}
for $i (@mods){
    ($path, $url, $branch) = expand($i);
    print(qq{rm -rf $path});
    print(qq{git submodule add -b $branch $url $path});
}
'

唯一の副作用はコマンドの出力であり、何も実行されないため、コマンドを実行する前に監査できます。

これは、コンソールでの単純なコピーアンドペーストで機能しますが、シェルスクリプトを挿入するのは簡単です。

出力例:

rm -rf third-party/dht
git submodule add -b post-0.25-transmission https://github.com/transmission/dht third-party/dht
rm -rf third-party/libutp
git submodule add -b post-3.3-transmission https://github.com/transmission/libutp third-party/libutp
rm -rf third-party/libb64
git submodule add -b post-1.2.1-transmission https://github.com/transmission/libb64 third-party/libb64
rm -rf third-party/libnatpmp
git submodule add -b post-20151025-transmission https://github.com/transmission/libnatpmp third-party/libnatpmp
rm -rf third-party/miniupnpc
git submodule add -b post-2.0.20170509-transmission https://github.com/transmission/miniupnpc third-party/miniupnpc
rm -rf third-party/libevent
git submodule add -b post-2.0.22-transmission https://github.com/transmission/libevent third-party/libevent
于 2018-03-13T02:02:42.947 に答える
0

zshユーザーの場合は、DRY_RUN=1実行されるコマンドを確認するためのサポートがありgit、の代わりにファイルの解析にのみ使用する関数を試してくださいsed

gsub_file() {(
  set -eu

  cd "$(git rev-parse --show-toplevel)"

  submodule_paths=(
    "${(@f)$(git config --file ./.gitmodules --get-regexp "path" | awk '{ print $2 }')}"
  )
  submodule_urls=(
    "${(@f)$(git config --file ./.gitmodules --get-regexp "url" | awk '{ print $2 }')}"
  )
  submodule_branches=(
    "${(@f)$(git config --file ./.gitmodules --get-regexp "branch" | awk '{ print $2 }')}"
  )

  sh_c() {
    echo + "$*"
    if [ "${DRY_RUN-}" ]; then
      return
    fi
    eval "$@"
  }

  for (( i=1; i <= ${#submodule_paths[@]}; i++ )) do
    p="${submodule_paths[$i]}"
    if [ -d "$p" ]; then
      continue
    fi

    url="${submodule_urls[$i]}"
    unset b
    if [ "${submodule_branches[$i]-}" ]; then
      b="-b ${submodule_branches[$i]}" 
    fi
    sh_c git submodule add "${b-}" "$url" "$p"
  done
)}
于 2020-09-14T09:57:37.097 に答える