This note records the basic steps for building a small Git server on a Raspberry Pi, adding SSH key access, creating a bare repository, and using a post-receive hook to deploy the master branch to a working directory.
Table of Contents
1. Set up the Git environment
Install Git and create a dedicated git user:
sudo apt-get update
sudo apt-get install git
sudo adduser git
A dedicated user keeps repository access separate from normal system users.
2. Generate an SSH key pair
On each client machine, generate a key pair:
ssh-keygen -t rsa -C "user@lazying.art"
The private key stays on the client, for example:
/home/pi/.ssh/id_rsa
Add each client’s public key to the Git user’s authorized keys file on the server:
/home/git/.ssh/authorized_keys
Make sure the .ssh directory and file permissions are acceptable to SSH:
sudo mkdir -p /home/git/.ssh
sudo chmod 700 /home/git/.ssh
sudo chmod 600 /home/git/.ssh/authorized_keys
sudo chown -R git:git /home/git/.ssh
3. Initialize the server-side repository
Create a directory for bare repositories and initialize one:
mkdir Git
cd Git
sudo git init --bare sample.git
sudo chown -R git:git sample.git
A bare repository is the normal format for a Git server. It stores Git data but does not keep a checked-out working tree.
To restrict the git user to Git operations, edit /etc/passwd:
sudo vim /etc/passwd
Change the user’s shell from Bash:
git:x:1001:1001:,,,:/home/git:/bin/bash
to git-shell:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
Before making this change, verify that git-shell exists on your system:
which git-shell
4. Push code to the Git server
In the project directory on the client, configure Git identity and push the first commit:
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
git add .
git commit -m "init commit"
git push -u origin master
If the remote has not been added yet, add it first. Replace the host and path with your server details:
git remote add origin git@192.168.1.108:/home/pi/Git/sample.git
5. Set up a deployment hook
Create a post-receive hook inside the bare repository:
vim sample.git/hooks/post-receive
Add the hook script:
#!/bin/bash
TARGET="/home/webuser/deploy-folder"
GIT_DIR="/home/webuser/www.git"
BRANCH="master"
while read oldrev newrev ref
do
# Only check out the branch that should be deployed.
if [ "$ref" = "refs/heads/$BRANCH" ];
then
echo "Ref $ref received. Deploying ${BRANCH} branch to production..."
git --work-tree=$TARGET --git-dir=$GIT_DIR checkout -f $BRANCH
else
echo "Ref $ref received. Doing nothing: only the ${BRANCH} branch may be deployed on this server."
fi
done
Then set ownership and execution permissions:
chown git:git hooks/post-receive
chmod +x hooks/post-receive
When a push triggers the hook, Git should print output from the remote server. A failed deployment caused by permissions may look like this:
Counting objects: 2, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 237 bytes | 23.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
remote: Ref refs/heads/master received. Deploying master branch to production...
remote: error: unable to create file main.py (Permission denied)
remote: error: unable to create file test.py (Permission denied)
remote: Already on 'master'
To 192.168.1.108:/home/pi/Git/printer.git
2e6a796..6085cd0 master -> master
This means the hook ran, but the git user could not write to the deployment directory. Change the owner of the deployment directory to git:
chown git:git /path/to/deployment/directory/
After fixing permissions, a successful push may look like this:
Counting objects: 2, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 239 bytes | 21.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
remote: Ref refs/heads/master received. Deploying master branch to production...
remote: Already on 'master'
To 192.168.1.108:/home/pi/Git/printer.git
6085cd0..b83c0d5 master -> master
Common client-side Git commands
Set the global Git user name and email:
git config --global user.name "username"
git config --global user.email "user@example.com"
Clone a newly created remote repository, add a README, and push it:
git clone https://git.aiiage.com:9999/song.yl/ReID.git
cd ReID
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
Push an existing local folder to a new remote repository:
cd existing_folder
git init
git remote add origin https://git.aiiage.com:9999/song.yl/ReID.git
git add .
git commit -m "Initial commit"
git push -u origin master
Point an existing Git repository at a new remote and push all branches and tags:
cd existing_folder
git remote rename origin old-origin
git remote add origin https://git.aiiage.com:9999/song.yl/ReID.git
git push -u origin --all
git push -u origin --tags
Reference: yllifesong, CSDN, <https://blog.csdn.net/yllifesong/article/details/81041156>.
