Gitサブモジュールを追加するときにブランチ/タグを指定するにはどうすればよいですか?


756

どのように機能しgit submodule add -bますか?

特定のブランチを持つサブモジュールを追加すると、新しいクローンリポジトリ(の後git submodule update --init)は、ブランチ自体ではなく、特定のコミットになります(git statusサブモジュールでは、「現在ブランチ上にありません」と表示されます)。

私は上の任意の情報を見つけることができない.gitmodules.git/config、サブモジュールのブランチまたは任意の特定のコミットについてのようにどのようにGitのフィギュアそれを?

また、ブランチの代わりにタグを指定することは可能ですか?

バージョン1.6.5.2を使用しています。


3
あなたは持っている場合は、既存のサブモジュールはまだブランチを追跡されていないが、しかし、あなたは...それが今のブランチを追跡することを望むの下に私の答えを参照してください
VonC

回答:


745

注:Git 1.8.2では、ブランチを追跡する機能が追加されました。以下の回答の一部をご覧ください。


これに慣れるのは少し混乱しますが、サブモジュールはブランチ上にありません。それらは、あなたが言うように、サブモジュールのリポジトリの特定のコミットへの単なるポインタです。

つまり、他の誰かがリポジトリをチェックアウトするか、コードをプルし、gitサブモジュールを更新すると、サブモジュールはその特定のコミットにチェックアウトされます。

プロジェクトの全員が同じコミットでサブモジュールを持つことができるため、これは頻繁に変更されないサブモジュールに最適です。

サブモジュールを特定のタグに移動する場合:

cd submodule_directory
git checkout v1.0
cd ..
git add submodule_directory
git commit -m "moved submodule to v1.0"
git push

次に、submodule_directoryをそのタグに変更したい別の開発者がこれを行います

git pull
git submodule update --init

git pullサブモジュールディレクトリが指すコミットを変更します。 git submodule update実際に新しいコードにマージします。


8
それはとても良い説明です、ありがとう!そしてもちろん、あなたの答えを読んだ後、コミットがサブモジュール自体(submodule / .git / HEAD)内に保存されていることに気付きました。
Ivan

4
これはgit 1.7.4.4では動作しないようです。cd my_submodule; git checkout [ref in submodule's repository利回りfatal: reference is not a tree: ...。まるでgit親リポジトリでのみ動作するかのようです。
James A. Rosen

3
頻繁に更新されるプロジェクトでも、gitサブモジュールを使用するのは良いことです。Linuxカーネルはそれを使用しており、それほど悪くはありません

10
あるgit checkout v1.0ブランチやタグ?
BernhardDöbler、2015年

8
タグをコミットの人間が読めるエイリアスと考えてください。そして、コミットは各ファイルの特定の状態のセットです。ブランチは、変更できることを除いて、基本的に同じものです。
deadbabykitten 2016

657

他の回答の集まりにすぎない回答をここに追加したいのですが、もっと完全なものになると思います。

これら2つがあると、Gitサブモジュールがあることがわかります。

  1. あなたの.gitmodulesようなエントリがあります:

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
    
  2. Gitリポジトリにサブモジュールオブジェクト(この例ではSubmoduleTestRepoという名前)があります。GitHubはこれらを「サブモジュール」オブジェクトとして表示します。またはgit submodule status、コマンドラインから実行します。Gitサブモジュールオブジェクトは特別な種類のGitオブジェクトであり、特定のコミットのSHA情報を保持します。

    を実行するたびにgit submodule update、サブモジュールにコミットのコンテンツが入力されます。の情報により、コミットの場所がわかります.gitmodules

    これ-bで、.gitmodulesファイルに1行追加するだけです。同じ例に従うと、次のようになります。

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
        branch = master
    

    注:.gitmodulesファイルではブランチ名のみがサポートされていますが、SHAとTAGはサポートされていません。(その代わりに、各モジュールのブランチのコミットはgit add .、たとえば" " を使用して追跡および更新でき、毎回ファイルgit add ./SubmoduleTestRepoを変更する必要はありません.gitmodules

    サブモジュールオブジェクトはまだ特定のコミットを指しています。-bオプションがあなたを買う唯一のことは、--remoteVogellaの答えに従ってアップデートにフラグを追加する能力です:

    git submodule update --remote
    

    サブモジュールが指すコミットにサブモジュールの内容を入力する代わりに、そのコミットをマスターブランチの最新のコミットで置き換え、サブモジュールにそのコミットを入力します。これは、djacobs7回答によって2つのステップで実行できます。サブモジュールオブジェクトが指しているコミットを更新したので、変更されたサブモジュールオブジェクトをGitリポジトリにコミットする必要があります。

    git submodule add -bブランチですべてを最新に保つ魔法のような方法ではありません。.gitmodulesファイル内のブランチに関する情報を追加するだけで、サブモジュールオブジェクトを指定したブランチの最新のコミットに更新してから、データを取り込むことができます。


14
この回答にはより多くの投票が必要です。私は過去1日間多くの投稿を読んでおり、これにより混乱がすべて解消されます。SVNの世界から来て外部を使用する-gitサブモジュールのブランチトラッキングがブランチからすべてを魔法のように最新の状態に保つと信じたいのですが、これは本当ではありません!明示的に更新する必要があります!おっしゃるように、変更されたサブモジュールオブジェクトをコミットする必要があります。
dtmland 2015年

12
このブランチ追跡はタグでも機能しますか?ブランチの代わりにタグを指定しましたが、.gitmodules実行後に$ git submodule update --init --remote TestModuleエラーが発生fatal: Needed a single revisionしましたUnable to find current origin/TestTag revision in submodule path 'TestModule'。実際のブランチでそれを行うとき、それは機能します。とにかく.gitmodules正確なコミットを指定せずにタグを指定する方法はありますか?
Hhut

5
これは機能していないようです。ハッシュを更新し.gitmodulesて実行git submodule updateしても何も起こりませんでしたか?
CMCDragonkai 2016

2
どういうわけかこれは私にとってはうまくいきません。現在のリビジョンを見つけることがSHAを持つユーザーIDをコミットし、私は常にエラーを取得」できません(私は二重のリビジョンHEADの数とその正しいチェック)私がマスターを使用するただし場合、それは動作します。。
infoclogged

2
SHAをブランチ属性に入力しても、私にはうまくいきません。この使用法はドキュメントでもサポートされていませんgit-scm.com/docs/gitmodules
Jakub Bochenski

340

(Git 2.22、2019年第2四半期に導入git submodule set-branch --branch aBranch -- <submodule_path>

まだブランチを追跡していない既存のサブモジュールがある場合は、次のように注意してくださいgit 1.8.2+を使用している場合):

  • 親リポジトリが、そのサブモジュールがブランチを追跡するようになったことを確認してください。

    cd /path/to/your/parent/repo
    git config -f .gitmodules submodule.<path>.branch <branch>
    
  • サブモジュールが実際にそのブランチの最新のものであることを確認してください:

    cd path/to/your/submodule
    git checkout -b branch --track origin/branch
      # if the master branch already exist:
      git branch -u origin/master master
    

         ( 'origin'は、サブモジュールが複製された上流のリモートリポジトリの名前です。そのサブモジュール
         のgit remote -v内部に表示されます。通常、 'origin'です)

  • 親リポジトリにサブモジュールの新しい状態を記録することを忘れないでください:

    cd /path/to/your/parent/repo
    git add path/to/your/submodule
    git commit -m "Make submodule tracking a branch"
    
  • そのサブモジュールの後続の更新では、--remoteオプションを使用する必要があります。

    # update your submodule
    # --remote will also fetch and ensure that
    # the latest commit from the branch is used
    git submodule update --remote
    
    # to avoid fetching use
    git submodule update --remote --no-fetch 
    

Git 2.10+(2016年第3四半期)では.、ブランチ名として' 'を使用できることに注意してください。

ブランチの名前はforのようsubmodule.<name>.branchに記録されます。の特別な値は、サブモジュール内のブランチの名前が現在のリポジトリ内の現在のブランチと同じ名前であることを示すために使用されます.gitmodulesupdate --remote
.

しかし、LubosDがコメントしように

ではgit checkout、従うブランチ名が " ."の場合、コミットされていない作業が強制終了されます。代わりに
使用してくださいgit switch

つまり、Git 2.23(2019年8月)以上です。

混乱git checkout」を参照してください


ブランチに続くすべてのサブモジュールを更新したい場合:

    git submodule update --recursive --remote

Dan Cameron彼の回答で指摘しいるように、更新された各サブモジュールの結果は、ほとんどの場合、切り離されたHEADなることに注意しください。

Clintm はコメントで、実行git submodule update --remoteして、結果のsha1がサブモジュールが現在オンになっているブランチと同じである場合、サブモジュールは何もせず、サブモジュールを「そのブランチ」に残し、ヘッドが切り離された状態ではないことに注意しています。 )

ブランチが実際にチェックアウトされていることを確認するため(そして、親リポジトリのサブモジュールを表す特別なエントリの SHA1は変更​​されません)、彼は次のように提案しています。

git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; git switch $branch'

各サブモジュールは引き続き同じSHA1を参照しますが、新しいコミットを行う場合、サブモジュールに追跡させたいブランチによって参照されるため、それらをプッシュすることができます。
サブモジュール内でプッシュした後、親リポジトリに戻って、変更したサブモジュールの新しいSHA1を追加、コミット、プッシュすることを忘れないでください。

使用に注意してください$toplevelお勧めします、コメントにすることによりアレクサンダーPogrebnyakを
$toplevel2010年5月にgit1.7.2で導入されました: commit f030c96

最上位ディレクトリの絶対パスが含まれます(どこに.gitmodulesあるか)。

dtmland 追加する コメントに

foreachスクリプトは、ブランチに従わないサブモジュールのチェックアウトに失敗します。
ただし、このコマンドは次の両方を提供します。

 git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; [ "$branch" = "" ] && git checkout master || git switch $branch' –

同じコマンドですが読みやすいです:

git submodule foreach -q --recursive \
    'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; \
     [ "$branch" = "" ] && \
     git checkout master || git switch $branch' –

umläute はコメント内の簡略化されたバージョンdtmlandのコマンドを改良します

git submodule foreach -q --recursive 'git switch $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

複数行:

git submodule foreach -q --recursive \
  'git switch \
  $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

Git 2.26(2020年第1四半期)より前のバージョンでは、サブモジュールで更新を再帰的にフェッチするように指示されたフェッチは、必然的に大量の出力を生成し、エラーメッセージを見つけるのが難しくなります。

このコマンドは、操作の最後にエラーが発生したサブモジュールを列挙するように教示されています

Emily Shaffer(によるコミット0222540(2020年1月16日)を参照してください。(合併によりJunio C浜野- -b5c71ccをコミットする、2020年2月5日)nasamuffin
gitster

fetch:サブモジュールのフェッチ中の失敗を強調します

サインオフ:Emily Shaffer

多くのサブモジュールがあるときにサブモジュールのフェッチが失敗した場合、1つ以上のフェッチがにフォールバックすると、失敗した唯一のサブモジュールフェッチからのエラーは、他のサブモジュールのアクティビティの下に埋もれfetch-by-oidます。
ユーザーが何かがうまくいかなかったことに気づくように、遅れて失敗を呼び出します。

ミューテックスfetch_finish()によって同期的に呼び出されるだけなので、run_processes_parallel,周りでは必要ありませんsubmodules_with_errors


1
質問:フォルダーsubModule1があり、マスターブランチを追跡する場合、結果のコマンドは次のようになります 。git config -f .gitmodules submodule.subModule1.branch master
BraveNewMath

1
で置き換えても、foreachスクリプトはハードコードされたに依存しません。<path><path>$toplevel/
Alexander Pogrebnyak 2013年

1
foreachこのスクリプトは、ブランチを、次のされていませんチェックアウトサブモジュールに失敗します。しかし、このコマンドは、両方のは、あなたに与えます:git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; [ "$branch" = "" ] && git checkout master || git checkout $branch'
dtmland

2
@dtmlandのスクリプトの簡略版を次に示します。git submodule foreach -q --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'
umläuteOct

1
おお!実際には、foreachスクリプトは不要です。--mergeまたは--rebaseスイッチを使用してサブモジュールの更新を実行するgit submodule update --remote --merge必要がありgit submodule update --remote --rebaseます:または。これらのコマンドは、リモートブランチの追跡を行います。
GregTom 2017

206

Git 1.8.2はブランチを追跡する可能性を追加しました。

# add submodule to track master branch
git submodule add -b branch_name URL_to_Git_repo optional_directory_rename

# update your submodule
git submodule update --remote 

Gitサブモジュールも参照


4
これはタグにも適用されますか?
ThorSummoner 2014

1
このようにサブモジュールを追加すると、.gitmodulesファイルにどのように反映されますか?
ユージーン

1
おかげで私はちょうど私がGitHubのGH-ページのウェブサイトと同期されたサブモジュールのフォルダを作成するためにヘルプをに関する情報を使用:で、完全な例github.com/o2platform/fluentnode/issues/22
Dinisのクルス

4
あなたはにロックすることができ、タグgit submodule add -b tags/<sometag> <url>使用すると、行として見ることができるbranch = tags/<sometag>.gitmodules
KCD

9
@KCDタグを使用してそれを実行できるgitのバージョン。鉱山は機能しませんか?
CMCDragonkai 2016

58

Gitサブモジュールの使用例。

  1. 新しいリポジトリを作成する
  2. 次に、別のリポジトリをサブモジュールとして複製します
  3. 次に、そのサブモジュールでV3.1.2というタグを使用します。
  4. そしてコミットします。

そして、それはこのように少し見えます:

git init 
vi README
git add README
git commit 
git submodule add git://github.com/XXXXX/xxx.yyyy.git stm32_std_lib
git status

git submodule init
git submodule update

cd stm32_std_lib/
git reset --hard V3.1.2 
cd ..
git commit -a

git submodule status 

多分それは役立ちます(私はブランチではなくタグを使用していますが)?


4
基本的にdjacobs7と同じ答えですが、とにかく感謝します:)
Ivan

1
あなたの後に変更をコミットできるはずですgit reset --hard V3.1.2か?git status親ディレクトリの「コミットするものは何もない」だけです。
Nick Radford

1
@Ivan:これがdjacobs7の応答と同じであることを説明できますか?私の知る限り、彼の応答には 'submodule add'コマンドも含まれていません。代わりに、モジュールの元のgitリポジトリへのリンクがなく、リポジトリが直接追加されています。少なくとも私がこのアプローチを試したとき、.gitmodulesにはリンクがありませんでした。
ミシェル・ミューラー

djacobs7の応答には、サブモジュールの追加から始まる説明全体が含まれていません。彼はあなたがすでにそれを持っていると仮定します。
CodeMonkey 2017

サブモジュールのコンテンツ全体を追跡オブジェクトとしてメインリポジトリに追加するだけではありませんか?
user1312695

38

私の経験では、スーパープロジェクトまたは将来のチェックアウトでブランチを切り替えると、サブモジュールが適切に追加および追跡されているかどうかに関係なく、サブモジュールの分離したHEADが発生します(つまり、@ djacobs7および@Johnny Zの回答)。

そして、手動で、またはスクリプトを介して正しいブランチを手動でチェックアウトする代わりに、gitサブモジュールforeachを使用できます。

これにより、ブランチプロパティのサブモジュール構成ファイルがチェックされ、設定されたブランチがチェックアウトされます。

git submodule foreach -q --recursive 'branch="$(git config -f <path>.gitmodules submodule.$name.branch)"; git checkout $branch'


いいね。+1。私は私の答えにあなたの命令を含めました。
VonC 2013年

33

Gitサブモジュールは少し奇妙です-それらは常に「切り離されたヘッド」モードにあります-彼らはあなたが期待するようなブランチの最新のコミットに更新しません。

しかし、これを考えると、これはある程度の意味があります。サブモジュールbarでリポジトリfooを作成するとします。変更をプッシュし、リポジトリfooからコミットa7402beをチェックアウトするように指示します。

次に、クローンを作成する前に、誰かがリポジトリバーへの変更をコミットするとします。

リポジトリーfooからコミットa7402beをチェックアウトすると、私がプッシュしたのと同じコードを取得することになります。そのため、サブモジュールは、明示的に指示してから新しいコミットを行うように指示するまで更新されません。

個人的には、サブモジュールはGitの最も混乱しやすい部分だと思います。サブモジュールを私よりよく説明できる場所はたくさんあります。Scott ChaconによるPro Gitをお勧めします。


私はいくつかのgitの本を読み始める時期だと思います。推奨に感謝します。
Ivan

申し訳ありませんが、あなたがa7402beにプッシュしたのと同じになるのか、あなたのバージョンのfooで最新のバーを取得するのかは明確ではありませんでした。ありがとう:)
mmm

6
問題は、「ブランチXにこのサブモジュールを保持する」というオプションが必要であることです。これにより、自動的に更新したい場合は、それを実行できます。これは、更新するすべてのプラグインのスーパープロジェクトを再保存する必要なく、プラグインがすべてGitリポジトリであるWordPressインストールの管理など、サブモジュールをはるかに便利にします。
jerclarke 2012年

@jeremyclark git clone git://github.com/git/git.gitとその機能をプッシュ...... = D
Alastair

1
Gitの最も混乱する部分は、10年以上の開発の後でも、私の仕事を成し遂げるのに役立つツールは依然として非常に悪いユーザーエクスペリエンスを持っていることです。理由は、私を超えて、Gitのすべてで指を見せられるのを楽しむことです。時間。
0xC0000022L 2019

20

サブモジュールのブランチを切り替えるには(リポジトリの一部としてサブモジュールがすでにあると仮定):

  • cd サブモジュールを含むリポジトリのルートに
  • .gitmodules編集用に開く
  • 以下の行を追加するpath = ...url = ...branch = your-branchサブモジュールごとにと表示されます。ファイルを保存します.gitmodules
  • 次に、ディレクトリを変更せずに $ git submodule update --remote

...これにより、変更されたサブモジュールごとに、指定されたブランチの最新のコミットが取り込まれます。


10

これは.gitconfigファイルにあります。まだドラフトですが、現時点では有用であることが判明しています。サブモジュールをブランチに再接続するのに役立ちます。

[alias]

######################
#
#Submodules aliases
#
######################


#git sm-trackbranch : places all submodules on their respective branch specified in .gitmodules
#This works if submodules are configured to track a branch, i.e if .gitmodules looks like :
#[submodule "my-submodule"]
#   path = my-submodule
#   url = git@wherever.you.like/my-submodule.git
#   branch = my-branch
sm-trackbranch = "! git submodule foreach -q --recursive 'branch=\"$(git config -f $toplevel/.gitmodules submodule.$name.branch)\"; git checkout $branch'"

#sm-pullrebase :
# - pull --rebase on the master repo
# - sm-trackbranch on every submodule
# - pull --rebase on each submodule
#
# Important note :
#- have a clean master repo and subrepos before doing this !
#- this is *not* equivalent to getting the last committed 
#  master repo + its submodules: if some submodules are tracking branches 
#  that have evolved since the last commit in the master repo,
#  they will be using those more recent commits !
#
#  (Note : On the contrary, git submodule update will stick 
#to the last committed SHA1 in the master repo)
#
sm-pullrebase = "! git pull --rebase; git submodule update; git sm-trackbranch ; git submodule foreach 'git pull --rebase' "

# git sm-diff will diff the master repo *and* its submodules
sm-diff = "! git diff && git submodule foreach 'git diff' "

#git sm-push will ask to push also submodules
sm-push = push --recurse-submodules=on-demand

#git alias : list all aliases
#useful in order to learn git syntax
alias = "!git config -l | grep alias | cut -c 7-"

3

Quackを使用して、特定のモジュールを別のGitリポジトリからプルします。提供されたリポジトリのコードベース全体を使わずにコードをプルする必要があります-その巨大なリポジトリからの非常に特定のモジュール/ファイルが必要であり、更新を実行するたびに更新する必要があります。

だから私たちはこのようにしてそれを達成しました:

構成を作成する

name: Project Name

modules:
  local/path:
    repository: https://github.com/<username>/<repo>.git
    path: repo/path
    branch: dev
  other/local/path/filename.txt:
    repository: https://github.com/<username>/<repo>.git
    hexsha: 9e3e9642cfea36f4ae216d27df100134920143b9
    path: repo/path/filename.txt

profiles:
  init:
    tasks: ['modules']

上記の構成では、最初のモジュール構成で指定されているように、提供されたGitHubリポジトリから1つのディレクトリを作成し、もう1つは特定のリポジトリからファイルをプルして作成します。

他の開発者は実行する必要があるだけです

$ quack

そして、上記の構成からコードを引き出します。


2

サブモジュールのブランチを選択する唯一の効果は--remotegit submodule updateコマンドラインでオプションを渡すと、Gitは分離されたHEADモード(デフォルトの--checkout動作が選択されている場合)でその選択されたリモートブランチの最新のコミットをチェックアウトすることです。

サブモジュールの浅いクローンで作業する場合、Gitサブモジュールにこのリモートブランチトラッキング機能を使用するときは特に注意が必要です。この目的でサブモジュール設定で選択するブランチは、の間に複製されるブランチではありませんgit submodule update --remote。あなたも合格した場合は--depth、パラメータをして、あなたがクローンしたいブランチについてのGit指示していない - と、実際にあなたがすることはできませんgit submodule update、コマンドライン!! -、明示的なパラメーターがない場合のgit-clone(1)ドキュメントで説明されているように暗黙的に動作するため、プライマリブランチのみが複製されます。git clone --single-branch--branch

当然のことですが、git submodule updateコマンドによってクローンステージが実行された後、サブモジュール用に以前に設定したリモートブランチの最新のコミットのチェックアウトが最終的に試行されます。これがプライマリコミットでない場合は、そのコミットではありません。ローカルの浅いクローンなので、失敗します

致命的:単一のリビジョンが必要

サブモジュールパス 'mySubmodule'で現在のオリジン/ NotThePrimaryBranchリビジョンが見つかりません


エラーを修正する方法-単一のリビジョンが必要ですか?
NidhinSPradeep

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.