gitサブモジュールが本番環境にプッシュされていません

Nov 26 2020

2つのサブモジュールを持つ新しいリポジトリを作成しました。ローカルでは正常に動作しますが、本番環境にプッシュすると、サブモジュールはありません。各サブモジュールのルートディレクトリは存在しますが、内部にファイルはありません

git version 2.27.0

本番環境でリポジトリを作成する

git --bare init
cd hooks && touch post-receive && chmod +x post-receive

cat hooks/post-receive
#/bin/sh
git --work-tree=/var/www/repo --git-dir=/var/git_repos/repo.git checkout -f

開発/ローカルから本番環境へのプッシュ

git push production master

git statusすべてが最新であることを示します。サブモジュールフォルダで呼び出された場合でも。ローカルリポジトリのサブモジュールフォルダを削除しようとしました。リポジトリにコミット/プッシュします。次にgit push production master、本番サーバーでルートサブモジュールフォルダーが削除されました。その後、もう一度追加しようとしています

# git submodule add [email protected]:alias/repo_name.git php/repo/repo_name
Cloning into '/var/www/project/php/repo/repo_name'...
remote: Enumerating objects: 19, done.
remote: Counting objects: 100% (19/19), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 19 (delta 8), reused 19 (delta 8), pack-reused 0
Receiving objects: 100% (19/19), 8.62 KiB | 8.62 MiB/s, done.
Resolving deltas: 100% (8/8), done.

次に、リポジトリにコミットしてからgit push production master。同じ問題。本番環境では、サブモジュールのルートフォルダーは存在しますが、ディレクトリにファイルはありません。

githubでリポジトリを参照すると、サブモジュールが正しくリンクされています。

すべてがローカルリポジトリで機能します

回答

VonC Nov 28 2020 at 03:24

サブモジュールフォルダーはgithub(またはローカルリポジトリ)では空ではありませんが、本番環境にプッシュすると空になります

これは予想されることです。サブモジュールは次のもので構成されます。

  • に登録されているURL .gitmodules
  • 、gitlinkサブモジュールリポジトリのルートツリーのSHA1を表すインデックス内の特別なエントリ。

サブモジュールを使用してリモートリポジトリのクローンを作成すると(git clone --recurse-submodulesオプションを使用すると、それらのサブモジュールリポジトリ自体がクローンされ、そのgitlinkで表されるSHA1でチェックアウトされます。

「本番環境へのプッシュ」は、チェックアウトされた(ベアではない)リポジトリにプッシュすることを想定していないため、注意が必要です(技術的にはプッシュできます)。

本番環境でベアリポジトリにプッシュすることをお勧めします。これにより、受信後フックを使用してファイルを復元します(を使用してサブモジュールの内容を含むgit restore --recurse-submodules)


議論の後:

  1. サブモジュールはSSHURLで登録されているため、本番サーバーではアカウントに公開SSHキーを登録する必要があり.gitmodulesます。

  2. 受信後のスクリプトは次のようになります。

    #!/bin/bash
    cd /var/www/repo
    git --git-dir=/var/git_repos/repo.git --work-tree=. restore --recurse-submodules :/
    

を使用するとgit submodule、明らかに作業ツリーを設定できません

つまり、サブモジュールが関係している場合は、現在のフォルダーが作業ツリーである必要があります。

次に、別のgit-dir()を使用しても、git checkout/ git restorewith --recurse-submodules、またはgit submodule update --init、などのコマンドを実行できます--git-dir=/path/to/bare/repo.git

現在の作業ツリーが正しいため、サブモジュールが更新されます。

/var/www/repoを指定しても、以外の場所にいる場合git --work-tree=/var/www/repo ...は、前述のコマンドgit checkout/ git restorewithのいずれも--recurse-submodules、またはgit submodule update --initリポジトリのサブモジュールでは機能しません。
つまり/var/www/repo、ファイルは復元されますが、サブモジュールは空のままになります。