923

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

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

.gitmodulesサブモジュールのブランチまたは.git/config特定のコミットに関する情報が見つからないので、Gitはどのようにそれを理解しますか?

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

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

4

13 に答える 13

882

注: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実際には新しいコードにマージされます。

于 2009-11-22T09:19:34.167 に答える
874

ここに答えを追加したいのですが、それは実際には他の答えの集合体にすぎませんが、もっと完全かもしれないと思います。

これらの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に1行追加するだけです。.gitmodulesしたがって、同じ例に従うと、次のようになります。

    [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
    

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

    git submodule add -bブランチですべてを最新の状態に保つ魔法の方法ではありません。これは、ファイル内のブランチに関する情報を追加するだけであり.gitmodules、サブモジュールオブジェクトを、指​​定されたブランチの最新のコミットに更新してから入力するオプションを提供します。

于 2013-09-14T02:33:57.213 に答える
427

(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四半期)では、ブランチ名として''を使用できることに注意してください。

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

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

を使用git checkoutすると、フォローするブランチ名が「.」の場合、コミットされていない作業が強制終了されます。代わりに
使用してください。git switch

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

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


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

    git submodule update --recursive --remote

ダンキャメロンが彼の答えで述べているように、更新されたサブモジュールごとに、結果はほとんどの場合、切り離された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を追加、コミット、およびプッシュすることを忘れないでください。

AlexanderPogrebnyakによるコメント$toplevelで推奨されているの使用に注意してください。2010年5月にgit1.7.2で導入されました:commitf030c96
$toplevel

これには、最上位ディレクトリの絶対パスが含まれます(ここで、.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()によるcommit 0222540(2020年1月16日)を参照してください。( Junio C Hamanoによってマージされました---コミットb5c71cc、2020年2月5日nasamuffin
gitster

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

サインオフ-作成者:Emily Shaffer

サブモジュールの数が多いときにサブモジュールのフェッチが失敗した場合、複数のフェッチがフォールバックすると、失敗した唯一のサブモジュールのフェッチによるエラーが他のサブモジュールのアクティビティに埋もれてしまいますfetch-by-oid
何かがうまくいかなかったこと、そしてどこでユーザーが気付くように、遅れて失敗を呼びかけなさい

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


Git 2.28(2020年第3四半期)では、スクリプト化された「gitサブモジュール」Porcelainコマンドの一部の書き換えが続行されることに注意してください。今回は" git submodule set-branch"サブコマンドの番です。

Shourya Shukla()によるcommit 2964d6e(2020年6月2日)を参照してください。( Junio C Hamanoによってマージされました---コミット1046282、2020年6月25日periperidip
gitster

submodule:ポートサブコマンド'set-branch'シェルからCへ

メンター:Christian
Couderメンター:Kaartic Sivaraam
支援:Denton Liu
支援:Eric Sunshine
支援:ĐoànTrầnCôngDanh
署名者:Shourya Shukla

サブモジュールサブコマンド'set-branch'を組み込みに変換し、を介して呼び出しますgit submodule.sh

于 2013-09-14T06:59:18.890 に答える
272

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

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

# update your submodule
git submodule update --remote 

Gitサブモジュールも参照してください

于 2013-04-03T08:44:33.253 に答える
69

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 

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

于 2009-11-22T09:53:15.883 に答える
43

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

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

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

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

于 2013-11-09T04:54:45.243 に答える
40

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

ただし、これについて考えると、ある程度意味があります。サブモジュールバーを使用してリポジトリfooを作成するとします。変更をプッシュして、リポジトリfooからcommita7402beをチェックアウトするように指示します。

次に、クローンを作成する前に、誰かがリポジトリバーに変更をコミットしたと想像してください。

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

個人的には、サブモジュールはGitの最も紛らわしい部分だと思います。私よりもサブモジュールをうまく説明できる場所はたくさんあります。スコット・チャコンのプロギットお勧めします。

于 2009-11-22T05:22:58.740 に答える
23

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

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

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

于 2016-06-12T13:34:53.900 に答える
14

私の.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-"
于 2015-04-01T16:27:47.347 に答える
4

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

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

于 2015-10-22T14:35:13.230 に答える
4

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

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

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

致命的:単一の改訂が必要

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

于 2018-05-29T15:52:16.390 に答える
3

git submodule add -b development --name branch-name- https://branch.git

于 2019-03-07T09:04:07.217 に答える
2

既存の回答には、2番目のステップが欠落しており、詳細が過負荷になっています。

既存のサブモジュールを切り替えて、新しいリモートURLや新しいブランチを追跡するには:

  1. の真実の情報源を編集し.gitmodulesます。

たとえば、

[submodule "api"]
    path = api
    url = https://github.com/<original_repo>/api.git

[submodule "api"]
    path = api
    url = https://github.com/<another_repo>/api.git
    branch = work-in-progress
  1. を実行して.git/modules指定された、編集されたばかりの信頼できる情報源からgitinによってキャッシュされたサブモジュールの説明を更新します。.gitmodulesgit submodule sync

  2. を使用して、作業コピーのチェックアウトされたサブモジュールを更新しますgit submodule update --init --recursive --remote

  3. 変更をコミットします。

于 2022-02-08T00:15:08.757 に答える