100 lines
3.0 KiB
Markdown
100 lines
3.0 KiB
Markdown
# Introduction
|
|
|
|
This document describes how to setup a Git hook
|
|
to enable the update of a repository when a new commit is received.
|
|
|
|
This effectively is an implementation of a **Push-to-Deploy**
|
|
update/continuous integration strategy.
|
|
|
|
For the described approach to work, the Git server and the deployment target
|
|
must be running on the same machine.
|
|
However, the files do not need to be accessible by both Git and the application server.
|
|
That is why a safe indirection over root is necessary.
|
|
|
|
The deployment tree is a working directory of the Git repository.
|
|
This has the advantage that no files accidentally get overwritten by Git.
|
|
For example, for projects using PHP, this might be important.
|
|
Although the increased amount of storage space is a tradeoff,
|
|
it can be optimized by reducing the history depth of the repository
|
|
from time to time.
|
|
A brief hint hereof can be found at the end of this document.
|
|
|
|
The main work of the implementation is done by a universal script.
|
|
Actually, it could be used in any situation where a safe update
|
|
of a repository is needed.
|
|
|
|
# Files
|
|
|
|
The following files are used to describe the implementation:
|
|
|
|
* `/path/to/main.git`
|
|
The main bare repository receiving the updates.
|
|
* `/path/to/deploy-target`
|
|
The deployment target directory.
|
|
It is a working directory of a git repository.
|
|
* `/path/to/safe-update`
|
|
The safe update script which is listed below.
|
|
|
|
## Universal Safe Update
|
|
|
|
Copy the file [git-safe-update.sh](../scripts/git-safe-update.sh) and make it executable.
|
|
|
|
It can be used to update any repository. It takes two arguments:
|
|
|
|
1. Path of a non-bare Git repository
|
|
2. Intended owner of the files
|
|
|
|
The `chown` line at the end of the script is the reason
|
|
why the script needs to be run as root.
|
|
The chapter below describes how to configure `sudo` to enable root access.
|
|
|
|
Note that the user always knows what is going on in case of a failure.
|
|
|
|
## Git Hook
|
|
|
|
Install the following script as the `post-receive` hook.
|
|
In this case to `/path/to/main.git/hooks/post-receive`.
|
|
|
|
It executes `safe-update` only when the master branch is updated.
|
|
|
|
```sh
|
|
#!/bin/sh
|
|
|
|
read oldid newid ref
|
|
if [ "$ref" = "refs/heads/master" ]; then
|
|
sudo /path/to/safe-update /path/to/deploy-target www-data.www-data
|
|
fi
|
|
```
|
|
|
|
## Deployment Target Git Configuration
|
|
|
|
Because the Git repository lies on the same machine,
|
|
and is owned by a different user, it is safer to use
|
|
a `file:` URL as the remote.
|
|
The *master* branch is assumed to be a deployable version.
|
|
Hence, use the following command to add the remote:
|
|
|
|
cd /path/to/deploy-target
|
|
git init
|
|
git remote add -t master origin file:///path/to/main.git
|
|
git fetch --depth=1
|
|
git checkout master
|
|
|
|
## Sudo Configuration
|
|
|
|
Paste the following line to `/etc/sudoers.d/safe-update`
|
|
or append it to `/etc/sudoers`:
|
|
|
|
git ALL=(root) NOPASSWD: /path/to/safe-update
|
|
|
|
This enables user `git` to run `safe-update` as `root` without password.
|
|
So be careful..!
|
|
|
|
# Miscellaneous
|
|
|
|
To "forget" old git history, I had success with the following commands:
|
|
|
|
rm -r .git/objects
|
|
mkdir .git/objects
|
|
git fetch --depth=1
|