git submodule not pushed to production

Viewed 683

Have just created a new repository with two submodules. It works fine on local but when pushing to the production the submodules are not there. Each submodule root directory is present, but no files inside

git version 2.27.0

Create repo on production

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

Pushing to production from dev/local

git push production master

git status tells that everything is up to date. Even if it is called in the submodule folder. Have tried to delete the submodule folder on the local repository, commit/push to repository. Then git push production master and the root submodule folder was deleted on the production server. Then trying to add it again

# git submodule add git@github.com: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.

Then commiting to repository and then git push production master . The same problem. In production the root folders of the submodules are present but no files in the directories.

When I browse the repository on github, the submodules are correctly linked.

Everything works in the local repository

enter image description here

1 Answers

The submodule folders are not empty on github (or in local repo), but when pushing to production they are

That is expected: a submodule is composed of:

  • an URL registered in the .gitmodules
  • a gitlink, a special entry in the index which represents the SHA1 of the root tree of the submodule repository.

When you clone a remote repository with submodules (using the git clone --recurse-submodules option, those submodule repositories are cloned themselves, and checked out at the SHA1 represented by that gitlink.

"Pushing to production" is tricky because you are not supposed to push to a checked out (non-bare) repository (even thou you can technically do it).

It is better to push to a bare repository on production, which will use a post-receive hook to restore the files (including the submodule contents, using git restore --recurse-submodules)


After discussion:

  1. You need for the production server to have a public SSH key registered to your account, since the submodules are registered in the .gitmodules with an SSH URL.

  2. The post-receive script becomes:

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

With git submodule, you cannot set the working tree apparently

That means, if submodules are involved, you current folder must be the working tree.

Then you can do commands like git checkout/git restore with --recurse-submodules, or git submodule update --init, even with a different git-dir (--git-dir=/path/to/bare/repo.git).

The submodules will be updated because your current working tree is the right one.

If you are anywhere than /var/www/repo, even if you specify git --work-tree=/var/www/repo ..., none of the aforementioned commands git checkout/git restore with --recurse-submodules, or git submodule update --init will work for the submodules of your repo.
That is: Your /var/www/repo files will be restored, but the submodules will remain empty.

Related