2023-11-04 Using legit for my repos

After breakfast but before going shopping… blogging.

I've been using cgit for a long time on my server. Recently, I switched over to legit. The repositories are now served from a separate subdomain.

using cgit

a separate subdomain

Two days ago I noticed that legit wasn't showing all my repos. When I add some logging, it seemed that those repos cannot be opened by the underlying go-git library: "reference not found". Are these repos broken in obscure ways? I started chatting with legit's author, @icy@icyphox.sh.

As it turns out, the problem is that when I create a new bare repository on my server, its HEAD points to the default branch. In my case, that's the "main" branch.

However, if I check out somebody else's repository, that repository might not have a "main" branch. Many repositories have a "master" branch instead. That used to be the git default branch for many years and many repositories still use it. Some of my older repositories used it! Changing them all seemed like a big chore at the time and so I only went about it as I stumbled upon it.

When I decide to publish one of these repositories on my server using legit, the problem is that legit looks at the repository's HEAD and finds a reference to the "main" branch. If the repository doesn't have a "main" branch, then the result is a "reference not found" error.

My legit configuration file starts as follows:

repo:
  scanPath: /home/git
  readme:
    - readme
    - README
    - readme.md
    - README.md
  mainBranch:
    - main
    - master

The documentation for "repo.mainBranch" has this to say:

repo.mainBranch: main branch names to look for.

So the takeaway is this: It is not enough to have one of these two branches in your repository. The repository's HEAD also has to point one of these branches!

It took me a while to figure out what's causing this problem, based on logging the error to `git.Open`. If you get the "reference not found" error then the problem is that on the server, HEAD refers to a branch that doesn't exist. A typical example would be publishing a repository with a "master" branch to the server where you initialised the bare git repository with a default branch of "main". In this case, the default branch is "main" but it doesn't exist, which is where the error "reference not found" comes from. People attempting to clone the repository run into a similar problem; they get the message "warning: remote HEAD refers to nonexistent ref, unable to checkout".

One solution to this problem would be to rename whatever the default branch is in your repository to the default branch your server expects. In this case, rename "master" to "main" and push that change to the server:

git branch -m master main
git push -v origin origin/master\:refs/heads/main  \
  \:refs/heads/master

The alternative would be to change the default branch for this reopsitory on the server. Change into the bare git repository and change the default branch for this repository only from "main" to "master:

git symbolic-ref HEAD refs/heads/master

I chose the first approach for my repositories.

​#Administration ​#Git ​#Legit

Making the main branch the default branch

I just took the opportunity to find the repos that still used "master" as the default branch on the server:

cd /home/git
find . -name HEAD \
  -exec grep --quiet master '{}' ';' \
  -exec echo '{}' ';'

Then I changed into most of them, and switched the default branch:

sudo -u git git symbolic-ref HEAD refs/heads/main

And in parallel, I went through the same repositories on my laptop and renamed the "master" branch to the "main" branch, and pushed it:

git branch -m master main \
&& git push -v origin origin/master\:refs/heads/main \
  \:refs/heads/master

It's a lot of manual back and forth, but with two windows next to each other, it's just a lot of copy & paste & focus.