6

Is it possible to include submodules when using the following code in a post-update hook?

GIT_WORK_TREE=/path/to/directory git checkout -f

What other options would I have to distribute code, including submodules from a post-update hook?

Thanks.

iliveinapark
  • 327
  • 4
  • 13

1 Answers1

11

The question "Using git submodule update --init on a post hook" mentions the error message you could see if using this in your post-update hook:

GIT_WORK_TREE=/path/to/directory git submodule update --init

That would give a:

remote: You need to run this command from the toplevel of the working tree.

So it is best to cd directly in the target repo and run your command from there:

export GIT_DIR=$(pwd)

cd /path/to/target/workingtree

git checkout -f master
git submodule update --init --recursive

However, as shown in "How do I init/update a git submodule in a working tree after pushing to a bare working directory?":

It looks like when your running "git submodule update" you can't set the GIT_WORK_TREE:
it will try to use this as the working tree for the submodule, not for the super project.

The blog post "Git push with submodules: a how-to guide" by Aaron Adams describe similar error messages as the OP iliveinapark shows in the comments:

Sadly, this doesn't work, I suspect because my repo is a bare repo.
The error that I get following these commands is:

fatal: This operation must be run in a work tree

If, to overcome the above error, I use something like:

git --git-dir=<my bare repo> --work-tree=<where I export to> submodule update --init --recursive 

I get:

fatal: working tree '<where I export to>' already exists. Clone of '<submodule repo>' into submodule path '<submodule path>' failed

The blog post mentioned above suggests an approach based on a non-bare repo (which usually isn't recommended for pushing to, but is necessary in this case) :

Using Git to manage a website with submodules: the right way

First, let’s create a universal post-receive hook, one that I won’t need to change on a per-repository basis:

[aaron@aaronadams]$ cat > /usr/local/share/git-core/templates/hooks/post-receive.sample
#!/bin/sh
#
# 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
do
:
done

# 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
[aaron@aaronadams]$ chmod +x /usr/local/share/git-core/templates/hooks/post-receive.sample

Now let’s go ahead and break all the rules.

We’re going to:

  • initialize a non-bare Git repository, right in our website directory;
  • make sure it can receive from git push;
  • explicitly set its working tree to its parent directory;
  • and enable our hook we just created.
[aaron@aaronadams]$ cd /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca
[aaron@aaronadams]$ git init && git config --bool receive.denyCurrentBranch false && git config --path core.worktree ../ && mv .git/hooks/post-receive.sample .git/hooks/post-receive
Initialized empty Git repository in /var/www/vhosts/aaronadams.ca/sites/staging.aaronadams.ca/.git/

Finally, on our local machine, we’ll change our remote to reflect the location of our new repository, and push.

[aaron@aaronadams]$ git remote set-url staging aaron@aaronadams.ca:sites/staging.aaronadams.ca
[aaron@aaronadams]$ git push staging master
remote: Submodule 'codeigniter' (git://github.com/EllisLab/CodeIgniter.git) registered for path 'codeigniter'
remote: Cloning into 'codeigniter'...
remote: Submodule path 'codeigniter': checked out 'fd24adf31255822d6aa9a5d2dce9010ad2ee4cf0'
To aaron@aaronadams.ca:sites/staging.aaronadams.ca
 * [new branch]      master -> master

Holy crap, it worked!

Not only is this method compatible with submodules, it also requires just one command to set up a new remote repository (which, okay, consists of four commands).
It also keeps the repository and the working tree in the same place; and with no absolute paths required in our configuration or hook files, it’s now completely portable as well.


The OP iliveinapark mentions though:

This became a bit too fiddly, though, so I went with a simple forced checkout, and will manage updating my submodules manually.

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • http://stackoverflow.com/questions/8271839/how-can-i-init-update-git-submodules-in-a-remote is also interesting – VonC Apr 15 '13 at 06:07
  • Thanks for the reply. Sadly, this doesn't work, I suspect because my repo is a bare repo. The error that I get following these commands is: `fatal: This operation must be run in a work tree` – iliveinapark Apr 16 '13 at 04:11
  • If, to overcome the above error, I use something like: `git --git-dir= --work-tree= submodule update --init --recursive` I get: `fatal: working tree '' already exists. Clone of '' into submodule path '' failed` – iliveinapark Apr 16 '13 at 04:18
  • @iliveinapark ok, I have edited the answer and reference an alternative approach. – VonC Apr 16 '13 at 06:24
  • Thanks for your contribution, VonC. This became a bit too fiddly, though, so I went with a simple forced checkout, and will manage updating my submodules manually. I do appreciate your efforts, though. – iliveinapark Apr 17 '13 at 06:41
  • @iliveinapark ok, I have added your conclusion to this answer, for more visibility. – VonC Apr 17 '13 at 06:46
  • For the record, I had to find a new approach again when I had to work with git-svn for a particular client. There was just no way to get submodules to `dcommit`. Instead, I set up my former submodules as remotes, using `fetch` and `read-tree` to update them as necessary. It's far less fiddly than submodules, which I've since abandoned completely. If you're interested, my process is documented here: http://stackoverflow.com/a/14718080/802414 – Aaron Adams Aug 14 '13 at 20:03