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.
Pulling with submodules. Once you have set up the submodules you can update the repository with fetch/pull like you would normally do. To pull everything including the submodules, use the --recurse-submodules and the --remote parameter in the git pull command .
A git submodule is a record within a host git repository that points to a specific commit in another external repository. Submodules are very static and only track specific commits. Submodules do not track git refs or branches and are not automatically updated when the host repository is updated.
In most cases, Git submodules are used when your project becomes more complex, and while your project depends on the main Git repository, you might want to keep their change history separate. Using the above as an example, the Room repository depends on the House repository, but they operate separately.
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) :
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 [email protected]: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 [email protected]: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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With