< ~wiki

hosting public git repos

Besides the Gitea instance of tildeverse, you could easily set up a read-only clone URL fetchable using git clone similar to this one:

$ git clone https://tilde.team/~kst/grm.tilde.git


If you are not interested in the details, you could use a minimal front end called git repo manager. It should take care of all the details for you.

creating a repo

On tilde.team, the structure of ~name/public_html/<path> is mapped to https://tilde.team/~name/<path> so anything inside the ~name/public_html directory is publicly accessible. If you want to create a publicly accessible git repository, all you need to do is to create a bare repository inside ~name/public_html:

$ cd ~/public_html
$ git init --bare my_repo.git
Initialized empty Git repository in /home/name/public_html/my_repo.git/

The .git suffix is a convention for bare repositories. If you have used GitHub, GitLab, or Gitea before, you should have noticed that the clone URLs all have the .git suffix.

After you have created the bare repository for your project, the URL


is not ready for clone yet. Because we are serving the repository using GET requests, or what git internally called the "dumb" HTTP protocol, git needs some extra info files for cloning the repository. They can be generated by

$ cd ~/public_html/my_repo.git
$ git update-server-info

Now you should be able to clone the repository using

$ git clone https://tilde.team/~name/my_repo.git
Cloning into 'my_repo'...
warning: You appear to have cloned an empty repository.


$ git update-server-info

command needs to be run after every update to the repository. This could be automated using the post-update git hook. Since the sample post-update hook in


already contains this command, we simply rename the sample hook

$ cd ~/public_html/my_repo.git
$ mv hooks/post-update.sample hooks/post-update

so that git will run this script after every update.

push via ssh

Note that the HTTP clone URL is read-only, so you can't push anything using this URL. Normally you would need to set up the "smart" protocol for authentication, but since we are using SSH already, we could use a remote path of the form name@host:path, similar to the arguments of scp, as the git remote url, so you could use

$ git clone name@tilde.team:~/public_html/my_repo.git

to clone the repository on your local machine, or

$ git clone ~/public_html/my_repo.git

if you want to work on the server directly. If you have already made some changes to the local repo, use

$ git remote set-url origin <url>

to update the remote URL. Now you should be able to push to your remote repo using

$ git push

if you have a correct SSH keypair setup.

web front end

Now that we have already figured out the push and clone access of our repository. You could call it an end here, but one of the most important features of git hosting services is a web interface so that people could browse and discuss the source code without cloning it.

For this, we could use stagit, which is a tool for generating static HTML pages from a git repository. The generated web pages are even browsable using terminal browsers such as elinks, w3m, and lynx. For example, try

$ lynx https://tilde.team/~kst/git/grm.tilde/file/TUTORIAL.html

Since tilde.team already have libgit2 installed, simply clone the repo and build it:

$ git clone git://git.codemadness.org/stagit
$ cd stagit
$ make
$ cp stagit stagit-index ~/bin/

Here, we will assume that the index page of stagit, which lists all the repos you have, is


and the index page of each repository is


To build the HTML pages for my_repo, we first make the corresponding directory

$ mkdir -p ~/public_html/git/my_repo
$ cd ~/public_html/git/my_repo

and add some metadata to your bare git repo

$ echo 'a cool project' > ~/public_html/my_repo.git/description
$ echo 'https://tilde.team/~name/my_repo.git' > ~/public_html/my_repo.git/url
$ echo 'name' > ~/public_html/my_repo.git/owner

then run

$ stagit ~/public_html/my_repo.git

to generate HTML files in the current directory. You could link index.html to log.html

$ ln -sf log.html index.html

so that the URL


is pointed to the commit log page.

To generate the repository index, go back to

$ cd ~/public_html/git/

and run

$ stagit-index ~/public_html/my_repo.git > index.html

Note that the output will be empty if my_repo has no commits. In general, use

$ stagit-index repo_dir1 repo_dir2 ... > index.html

to generate index for multiple repositories. you should also copy over or symlink some asset files in stagit's repository, such as style.css, logo.png, etc. to




you could also modify the source code of stagit to use a common location for the assets.

Because the web pages generated by stagit is static, you need to run stagit and stagit-index after each push operation to your repository in order to update the HTML files. This process can be easily automated using a post-receive hook. An example of the post-receive hook can be found here. To install it:

$ cd ~/public_html/my_repo.git/hooks
$ curl -o stagit-post-receive https://tilde.team/~kst/bin/stagit-post-receive
$ chmod +x stagit-post-receive

Now you should see something like this when you do a git push

$ git push
remote: [my_repo] stagit HTML pages... done!

a minimal front end for stagit

Since the process of creating repositories and recompiling stagit pages can be very tedious, there is a simple front end called git repo manager (grm) to deal with the chore, see the readme if you want to use grm to automate this process.

If you want to host git repositories on your own server, you could use the git daemon to better manage the visibility of your repositories. The remote address exposed by the git daemon will have git:// prefix. Check out the master branch of grm if you want to use git daemon instead.

accepting patches

Hosting git repositories this way means there will be no fancy features such as issues and pull requests, but git have built-in support for email workflows.

Contributors could format their commits to patches using

$ git format-patch

and use the

$ git send-email <patches>

command (see here) to send the patches to you, and you could apply the patches by piping the email message or attached patches to the git am command

$ git am < <patch>

See the blog post of Drew DeVault for using git with mutt, and check out aerc if you want a modern alternative for mutt built from such workflow.