含まれているリポジトリに保存されているコミットにGitサブモジュールポインターを戻す方法は?


128

メインのgitリポジトリにgitサブモジュールがあります。私が理解しているように、メインリポジトリはSHA値(どこかに...)を格納し、それが「リンクされている」サブモジュールの特定のコミットをポイントしています。

私は自分のサブモジュールに入り、と入力しましたgit checkout some_other_branch。どのコミットから来たのか私にはわかりません。

メインリポジトリとサブモジュールが再び同期するように、そのポインターを元に戻したいと思います。

私の最初の(おそらく素朴な)本能は言うgit reset --hardことでした-それは他のすべてのために働くようです。驚いたことに、このシナリオでは機能しませんでした。

したがって、と入力しgit diffて、サブモジュールポインターが以前使用していたSHA IDを書き留めてから、サブモジュールに移動git checkout [SHA ID]するとわかりましたが、確かにもっと簡単な方法があるはずです。

私はまだgitサブモジュールについて学習しているので、わからない概念の単語がある場合は、自由に私の用語を修正してください。

回答:


167

サブモジュールを更新して、親リポジトリが本来あるべきものと同期するようにします。これは、更新コマンドの目的です。

サブモジュールのマンページから:

登録されたサブモジュールを更新します。つまり、欠落しているサブモジュールを複製し、
包含のインデックスで指定されたコミットをチェックアウトします
リポジトリ。これにより、以下の場合を除き、サブモジュールHEADが切り離されます。
--rebaseまたは--mergeが指定されているか、キーのサブモジュールです。$ name.update
リベースまたはマージするように設定されています。

これを実行すると、すべてがうまくいくはずです:

git submodule update

4
どういうわけか、私にとっては追加する必要がありました--init。これがないと、サブモジュールはの状態のままになり(new commits)ます。私のサブモジュールはすでに初期化されていますが。
Ambidex 2014

@Ambidexはい、--initこのすべてにおいてオプションは非常に重要です。サブモジュールがhttps経由で複製されたため、ユーザー名とパスワードの入力を求められました。両方のフォルダーに移動し、sshチェックアウトにプロトコルを使用するようにリモートを設定しました。
A-Dubb

1
サブモジュールコミットハッシュが変更され、
ステージング

--recursiveを追加して、すべてのサブモジュールに移動する必要がないようにすることができます
Gaspa79

21

サブモジュールが指すコミットを変更するには、サブモジュールでそのバージョンをチェックアウトしてから、含まれているリポジトリに戻り、その変更を追加してコミットする必要があります。

または、サブモジュールをトップリポジトリがポイントするバージョンにしたい場合は、を実行しますgit submodule update --recursive--initクローンしたばかりの場合は追加します。

また、git submoduleサブモジュールコマンドを使用しないと、ポイントしているコミットが表示されます。同期していない場合、コミットの前に-または+が表示されます。

サブモジュールが含まれているツリーを見ると、commitブロブまたはツリーである残りのサブモジュールとは対照的に、サブモジュールがとしてマークされていることがわかります。

特定のコミットがあなたができるサブモジュールを指すことを確認するには:

git ls-tree <some sha1, or branch, etc> Submodule/path

次に、コミットなどをログに渡すなどして、必要に応じて確認できます(git-dirgitコマンドレベルのオプションを使用すると、サブモジュールにcdする必要がなくなります)。

git --git-dir=Submodule/path log -1 $(<the above statement>)

以下のコマンドが役に立ちました(サブモジュールと自分のモジュールの変更もすべて無視したかったのです):git submodule update --init --recursive
Rajesh Goel

6

私が遭遇したもう1つのケースは、破棄したいサブモジュールに段階的ではない変更がある場合です。git submodule updateはその変更を削除せず、親ディレクトリのgit reset --hardも削除しません。サブモジュールディレクトリに移動して、git reset --hardを実行する必要があります。したがって、親モジュールとサブモジュールの両方でステージングされていない変更を完全に破棄したい場合は、次のようにします。

親:

git reset --hard

git submodule update

サブモジュール内:

git reset --hard

5

git ls-tree HEAD「superproject」フォルダーで使用して、サブモジュールの元のコミットを確認します。次に、サブモジュールディレクトリに移動し、を使用git log --oneline --decorateして、元のコミットがどのブランチにあるかを確認します。最後に、git checkout original-commit-branch

私が設定したいくつかのテストディレクトリを使用すると、コマンドは次のようになります。

$ git --version
git version 1.7.4.1
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   sm2 (new commits)
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git ls-tree HEAD
100644 blob 76813a07ae558db274cefc6d903ec24323fdeb0d    .gitmodules
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    main
160000 commit 7c5889497938cd5699a9234a98ee93947e52b1ed  sm1
160000 commit f68bed61cba6f94cef57554f2cf46a45a4a0d337  sm2
$ cd sm2
$ git log --oneline --decorate
5b8d48f (HEAD, foo1) foo1.1
f68bed6 (origin/master, origin/HEAD, master) Initial commit.
$ git checkout master
Switched to branch 'master'
$ cd ..
$ git status
# On branch master
nothing to commit (working directory clean)

「スーパープロジェクト」はコミット時にsm2サブモジュールを表示しますf68bed6が、sm2にはにHEADがあり5b8d48fます。サブモジュールコミットにf68bed6は3つのブランチがあり、サブモジュールディレクトリでのチェックアウトに使用できます。


ありがとうダン、パーフェクト!
アレック


1

サブモジュールと私のモジュールの変更も無視したかった

以下のコマンドは私を助けました:

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