My self-hosted Git workflow with GitGen
Here is my workflow for self-hosting Git repositories on a shared hosting service with GitGen.
The assumption is that I already have a Git repository on my local machine. My repositories are created with SHA256 by default because that future is coming. Therefore, the further assumption is that SHA256 is what will also live on the remote bare repo.
Why bare on remote?
GitHub et al are bare repositories and I follow the same principle. The working directory lives on my local machine and any other remote ‘clones’. Since I do not perform any actual work on the repo which lives on my remote server, there is no need to have that as a full working directory.
Create the remote bare repo
My publishing workflow begins by creating a bare repository on the remote server.
git init --bare NEWREPO -b main --object-format=sha256
I then create a hook:
cd NEWREPO/hooks
touch post-receive && chmod 750 post-receive
Next, I add the instruction to update the bare repo when a new push comes in.
nano post-receive
I add the following to post-receive:
#!/bin/bash
git update-server-info
Save it and exit.
To allow the cloning of my repositories, the post-receive hook exposes them over “dumb” HTTP. This is because no smart HTTP is permitted by my host and SSH cloning is only allowed if access is explicitly granted.
The local workflow with GitGen
For each new repo, I cheat by manually editing its config file to add the remote and branch details.
[remote "origin"]
url = https://git.cybrkyd.com/repository/NEWNAME
fetch = +refs/heads/*:refs/remotes/origin/*
pushurl = ssh://blah.blah/git.cybrkyd.com/repository/NEWNAME
[branch "main"]
remote = origin
merge = refs/heads/main
I then make sure to add something meaningful to the description file since GitGen makes use of that.
At this point, a simple git push works to update the remote with any local commits. As I do not particularly want to run GitGen manually after each commit, I have created an alias to take care of this for me. I could have used a pre-push hook but that would mean adding the hook to each and every local repo. There are also global hooks but that is not for me.
A simple alias does the job really well.
alias gpush='git push && cd /home/cybr/Work/git-gen && bash run.sh'
My run.sh contains the following:
#!/bin/sh
python3 gitgen.py
rsync -avP -e 'ssh' "/home/cybr/Work/git-gen/git-website/" "my_host:~/git.cybrkyd.com"
When I commit to any of my repos, I run the alias gpush and this happens:
- git push
- GitGen runs to generate the static site
- The files are sent to my server via Rsync.
I’m currently experimenting with caching the GitGen build so as to not generate all repos each and every time I run it. That, and sending the entire site with Rsync after each generation as well. Soon, very soon.
