Self-hosting a tiny git remote
There are plenty of full-featured git forges out there. If you’re a software developer, you’ve probably used GitHub, Bitbucket, and GitLab at some point – and you’re maybe familiar with Gitea, Gogs, or SourceHut.
All of this software is great, and each git forge has valuable features that save users time and effort when working on projects.
Sometimes, though, all I need is a simple git remote to sync a simple project. I don’t need issue trackers, wikis, continuous integration, or a way to manage patches coming from multiple contributors.
For these use cases, I have set up a tiny git remote that only I can access.
Create a synced directory
The first problem that needs solving: where should the remote live? I have chosen to use a simple synced directory.
There is nothing special about this directory. It is just another directory I intend to sync using some Dropbox-like file syncing software. (Don’t worry: I do not ever sync working directories. I’ll discuss this later.)
We have many ways to sync directories in 2020: whether you use a hosted service like Google Drive or use a self-hosted solution like ownCloud. I personally use Syncthing, which runs 24/7 on a media server in my living room – and then syncs to all my other devices whenever they’re connected to a network.
The directory I sync is simply called
Git. It lives in my user’s
If you’re asking yourself, “why not just use SSH?” right now, I suggest skipping to the Why not just use SSH? section of this article.
Add new repositories
The next problem is: how to get
project-directory from Computer A to Computer B. The short answer would be, “use the synced directory” – but I want to do this the right way.1
Git directory, I can start to initialize git repositories with the
git init --bare ~/Git/my-project.git
--bare flag means that the git repository being initialized (or cloned, actually) is not going to be a working directory.
If I try to change directory to my new repo, git even warns me about this:
cd ~/Git/my-project.git fatal: this operation must be run in a work tree
You can read more about using bare git repositories this way in the Pro Git book. Specifically, see 4.2 Git on the Server – Getting Git on a Server.
Push to repositories
I’m about ready to push work. So far, I’ve:
- Built a home for git repositories I want to sync:
- Made my first bare git repository at
Now, I can take any working directory and add my bare repository as a remote:
git remote add syncthing ~/Git/my-project.git
And when I’m ready to push my work from my branch (in this case
git push syncthing my-branch
When I’m ready to clone the project from another workstation, I just need to make sure my synced directory is available and fully synced. The messiest part of this is that (with Syncthing, at least) the synced directory may use a different path on my different workstations.
When I clone, it’s nice to manually set the
--origin so I’m mindful that I’m pushing to and pulling from my tiny git remote:
git clone --origin syncthing ~/Git/my-project.git
And if I forget (like I often do), I can always change the name of the remote later using
git remote rename:
git clone ~/Git/my-project.git my-project cd my-project git remote rename origin syncthing
My tiny git remote works great for small projects I don’t intend to share with anyone. But I think it’s important to highlight the caveats:
- If my syncing software fails (on the server or a client), I risk losing work.
- If this is my only git remote, I risk losing work. I must use multiple git remotes.
If my syncing software does fail, but I’ve already cloned my project on multiple workstations, I may be able to recover. That said, I do need to be conscious of the state of my syncing software if I want to successfully use my tiny remote.
Why not just use SSH?
Note that this section did not originally appear in this article.
Some readers have rightly pointed out that this setup is more complex and has more caveats than just pulling from your other workstations via SSH:
git remote add workstation_2 firstname.lastname@example.org:/home/benjaminwil/my-project
If I’m lucky:
126.96.36.199 is a static IP address that I already know. And if I’m really lucky: it’s just a domain name, like
benjaminwil.info. Luck has nothing to do with it, but you know what I mean.
The reasons that I prefer using a synced directory, as described in this article, are:
- There is built-in redundancy. Syncthing makes local copies of my latest changes whenever a workstation running Syncthing is on a network.
- I am lazy. I am too often wiping my secondary devices and not setting up SSH keys to my primary devices.
- I don’t personally have a static IP address at home. While there are ways to take care of that problem, I haven’t ventured down that path.
All that said, I also have a remote set up that I only access via SSH. It’s my “always off-site” backup, and it is very valuable to me.
I could technically work out of a project directory that’s actively being synced. But there are lots of files I don’t want to or need to sync.
Syncing would occur more slowly if I had to sync 200MB of NodeJS modules between workstations. And if I accidentally leave a process running on Workstation A and then start work from Workstation B, I could cause some weird problems for myself. ↩
I don’t have to add
.gitto the end of a bare git repo, but it’s a nice convention. ↩