Deploy submodules via GIT

I have been using submodules to download and maintain Kirby Core and the Panel for my project as described in this article. Everything works like a charm on my local machine. But so far I have not been able to automatically deploy the submodules to my own server.


  • I am not using any 3rd party deploy service and would like to keep it this simple.
    The push is handled by a post-receive hook. But when I try to extent it to update the submodules it does not work:
  • GIT_WORK_TREE=…/…/_myproject git submodule update --init --recursive

The problem is definitely related rather to GIT than to Kirby, but I am curious if anyone can share a simple solution or idea as this would be really helpful to keep the Kirby Core up-to-date with every push.

Many thanks, Matt

I followed the suggestions at this site and haven’t had any issues:

I am also using submodules for plugins. It has worked really well so far.

Thanks, jpangborn. I found his article, too, and actually run into the same problems “doing it the wrong way”.

As I am not a GIT expert + using an universal post-receive hook seems too much of an overhead for my project I am really unsure how to implement his solution. From my understanding I conclude that the key to success is:

creating an additional(?) non-bare repository inside your working-tree?
explicitly set its working tree to its parent directory

Having a more simple explanation for GIT newbies would really help.

I followed the “Doing it the right way section.” with a minor modification that I didn’t set the post-receive hook as the default. That changes the following command:

git init && git config --bool receive.denyCurrentBranch false && git config --path core.worktree ../ && mv .git/hooks/post-receive.sample .git/hooks/post-receive

Instead, I use:

git init && git config --bool receive.denyCurrentBranch false && git config --path core.worktree ../

Once done, I set the post-receive hook to the following script (from the page).

# An example hook script to update the working tree, including its
# submodules, after receiving a push.
# This hook requires core.worktree to be explicitly set, and
# receive.denyCurrentBranch to be set to false.
# To enable this hook, rename this file to "post-receive".

# Read standard input or hook will fail
while read oldrev newrev refname

# Unset GIT_DIR or the universe will implode
unset GIT_DIR

# Change directory to the working tree; exit on failure
cd `git config --get core.worktree` || exit

# Force checkout
git checkout --force

# Force update submodules
git submodule update --init --recursive --force

Hope that helps. I am using this method for a Kirby site with two remotes. I have a development remote that I push the dev branch to and production remote that I push the master branch to. Works great.

Thanks again, I find your translation of aaron’s concepts into git command examples very helpful.
One more question for clarification:

my current project structure looks something like this
/myproject_git (containing the git repo and therefor the post-receive hook)
/myproject (containg all project files, kirby core including the submodules)

do you init an additional git inside /myprojects (explicitly for the submodules)?
or do you setup the (existing) /myproject_git with your command?

For a previous site, I used a similar git setup. Had a setup like the following:

I had the GIT repository separate from the work tree. So the repository was at:

The work tree was at

I had a post-receive hook that forced a checkout. But this method doesn’t work when you introduce submodules. The way it fails seems like a bug or a lack for forethought when updating the submodules. There doesn’t seem to be any way to create the post-receive hook that will allow you to update the submodules with this type of structure. In order to implement the method that works, I had to create a different structure on the remote. Now I have:

with the work tree the same as above. In the first example, there is a bare repository with a disconnected work tree. The second is a standard Git repository. I prefer the structure of the bare repository, but it won’t work for updating the submodules.

Since I could modify the .htaccess file to prevent access to the .git folders, I went ahead with standard repository style even though it doesn’t feel as right to me. There is some reasons why you wouldn’t want to push to a non-bare repository, but I can’t recall them right now and I haven’t had any issues. You need to be careful if you make changes on the server.

If you really need or want to maintain the bare repository style, I have seen a suggestion that you could use two repositories. I haven’t tried it because it felt like too much setup. Initialize a bare repository like the initial example above. Push all the content to it. Then clone the repository into the project folder. In the post-receive hook of the bare repository, instead of checking it out, you would change directories to the project folder and execute a pull from the bare repository. If you feel like it is needed, I could spend some time to set it up and then post the steps and the post-receive hook.

1 Like

Many thanks for the very detailed description - it seems like you really nailed the problem. Really appreciate it!

I think now my mistake was to assume that my kind of automated deployment setup could handle submodules, too. But it seems a little bit more difficult. Would be still interesting to see your solution for bare repositories, but regarding my current GIT skillset - and what I could research about the pros/cons of bare/non-bare repositories yesterday - I will rather stick with my current setup for my project. Splitting the repo & worktree and working without an additional .htaccess seems cleaner and easier to me.

For the future maybe it would be still nice to have a small & simple deployment guide for Kirby, which points out all this pitfalls and offers some easy step-by-step suggestions. This would probably enable more people to use Kirby’s great concept to its full potential.