I'm in the process of setting up a deployment script. The basic process is:
- Push changes to a bare repository on the server
- Then based on new tags will create a new folder for the release.
- Use git archive to move the files into the release directory
- Runs some migrations scripts and puts it live (if all is successful).
The issue is my repository contains a submodule, which doesn't get put in the archive, and therefore doesn't get put in the release directory.
I've seen git-archive-all, but that doesn't work on a bare repository.
If its not possible, I'm considering,
- making the repository not bare, and updating the working copy, which would allow me to use git-archive-all. Or
- having a second bare repository of the submodule on the server, which I could get an archive from (would have to look into this to make sure I'm getting the right revision).
If your submodule is in a repo accessible from the server, I would rather have a post-receive hook which would
- update a full non-bare repo (so a second repo beside your original bare one), including the submodule (
git submodule update --init
)
git archive
from that second repo (you would be sure to get the right version since the non-bare repo would reference the right version of the submodule)
Since the non-bare repo would contain the parent repo and its submodules, git archive-all
would be able to detect the .git
subdirectories and would archive everything.
If the submodule isn't accessible from the server, that means:
- it needs to be pushed in its own repo on the server
- the submodule in the parent repo needs to be reference with a relative path, in order for the parent repo to still be able to retrieve said submodule once pushed on the server.
I use this python package https://github.com/Kentzo/git-archive-all. You can install it by using
pip install git-archive-all
On OSX, you can install it also using brew install git-archive-all
This should do the trick: https://github.com/meitar/git-archive-all.sh/wiki
Here it is as a few-liner:
prefix=$(basename "$(pwd -P)")
{
git ls-files
git submodule foreach --recursive --quiet \
'git ls-files --with-tree="$sha1" | sed "s#^#$path/#"'
} | sed "s#^#$prefix/#" | xargs tar -c -C.. -f "$prefix.tar.xz" --
Run the following after the regular archive command:
git submodule foreach 'cd REPO_ROOT/$path && git archive HEAD | tar -x -C TARGET_ROOT/$path'
Here the REPO_ROOT is where your repo stands and the TARGET_ROOT is where you put your archived version. (I assume that you have a TARGET_ROOT folder where the expanded version of the first git archive
call. If you want a final zip/tar, you can tar/zip the final folder)
git submodule foreach
provides the $path
variable. See git help submodule
foreach section for more details.