You already have a Git server

(maurycyz.com)

Comments

jonhohle 26 October 2025
I feel like something was lost along the way.

    git init —-bare
will give you a git repo without a working set (just the contents typically in the .git directory). This allows you to create things like `foo.git` instead of `foo/.git`.

“origin” is also just the default name for the cloned remote. It could be called anything, and you can have as many remotes as you’d like. You can even namespace where you push back to the same remotes by changing fetch and push paths. At one company it was common to push back to `$user/$feature` to avoid polluting the root namespace with personal branches. It was also common to have `backup/$user` for pushing having a backup of an entire local repo.

I often add a hostname namespace when I’m working from multiple hosts and then push between them directly to another instead of going back to a central server.

For a small static site repo that has documents and server config, I have a remote like:

    [remote “my-server”]
    url = ssh+git://…/deploy/path.git
    fetch = +refs/heads/*:refs/remotes/my-server
    push = +refs/heads/*:refs/remotes/my-laptop
So I can push from my computer directly to that server, but those branches won’t overwrite the server’s branches. It acts like a reverse `git pull`, which can be useful for firewalls and other situations where my laptop wouldn’t be routable.
kragen 26 October 2025
You probably want to use a bare repository (git init --bare) rather than `git config receive.denyCurrentBranch updateInstead`, which will cause your pushes to fail if you edit anything locally in the checkout. For http://canonical.org/~kragen/sw/dev3/ I run a pull from the post-update hook of http://canonical.org/~kragen/sw/dev3.git, http://canonical.org/~kragen/sw/dev3.git/hooks/post-update, which is short enough that I'll just include it here:

    #!/bin/sh
    set -e

    echo -n 'updating... '
    git update-server-info
    echo 'done. going to dev3'
    cd /home/kragen/public_html/sw/dev3
    echo -n 'pulling... '
    env -u GIT_DIR git pull
    echo -n 'updating... '
    env -u GIT_DIR git update-server-info
    echo 'done.'
You can of course also run a local site generator here as well, although for dev3 I took a lighter-weight approach — I just checked in the HEADER.html file that Apache FancyIndexing defaults to including above the file directory listing and tweaked some content-types in the .htaccess file.

This could still fail to update the checkout if it has local changes, but only if they create a merge conflict, and it won't fail to update the bare repo, which is probably what your other checkouts are cloned from and therefore where they'll be pulling from.

thyristan 26 October 2025
Maybe I'm too old, but are there people that really didn't know that any ssh access is sufficient for using git?
jrm4 26 October 2025
Cannot emphasize this whole notion enough; Very roughly, Github is to git what gmail is to email.

It's mostly probably fine if that's the thing most of everybody wants to use and it works well; but also it's very unwise to forget that the point was NEVER to have a deeply centralized thing -- and that idea is BUILT into the very structure of all of it.

eqvinox 26 October 2025

  git clone ssh://username@hostname/path/to/repo
this is equivalent to:

  git clone username@hostname:path/to/repo
and if your usernames match between local and remote:

  git clone hostname:path/to/repo
(if the path has no leading /, it is relative to your home directory on the remote)
seba_dos1 26 October 2025
Just make the repository on the server side bare and you won't have to worry about checked out branches or renaming ".git" directory.
imiric 26 October 2025
I've used Git over SSH for several years for personal projects. It just works with no additional overhead or maintenance.

Tip: create a `git` user on the server and set its shell to `git-shell`. E.g.:

  sudo useradd -m -g git -d /home/git -s /usr/bin/git-shell git
You might also want to restrict its directory and command access in the sshd config for extra security.

Then, when you need to create a new repository you run:

  sudo -u git git init --bare --initial-branch=main /home/git/myrepo.git
And use it like so:

  git clone git@myserver:myrepo.git
Or:

  git remote add myserver git@myserver:myrepo.git
  git push -u myserver main
This has the exact same UX as any code forge.

I think that initializing a bare repository avoids the workarounds for pushing to a currently checked out branch.

ninkendo 26 October 2025
I remember the first time I tried git, circa 2006, and the first 3 commands I tried were:

    git init
    git commit -am Initial\ commit
    git clone . ssh://server/path/to/repo
And it didn’t work. You have to ssh to the remote server and “git init” on a path first. How uncivilized.

Bitkeeper and a few other contemporaries would let you just push to a remote path that doesn’t exist yet and it’d create it. Maybe git added this since then, but at the time it seemed like a huge omission to me.

bitbasher 26 October 2025
I have been doing this for many years.

If you want a public facing "read only" ui to public repositories you can use cgit (https://git.zx2c4.com/cgit/about/) to expose them. That will enable others to git clone without using ssh.

I keep my private repositories private and expose a few public ones using cgit.

prmph 26 October 2025
The more I use git, the more I discover more depth to it.

So many features and concepts; it's easy to think you understand the basics, but you need to dig deep into it's origin and rationale to begin to grasp the way of thinking it is built around.

And the API surface area is much larger than one would think, like an iceberg

So I find it really weirdly low level in a way. Probably what is needed is is a higher-level CLI to use it in the most sensible, default way, because certainly the mental model most people use it with is inadequate.

tonymet 26 October 2025
My favorite git trick is using etckeeper & git subtree to manage multiple machines from a single repo . A single git repo can “fan out” to dozens of instances . It’s useful even for “managed” hosts with terraform because etckeeper snapshots config with every change, catching bugs in the terraform config.

During the dev / compile / test flow, git makes a lightweight CI that reduces the exposure to your primary repo . Just run `watch -n 60 make` on the target and push using `git push` . The target can run builds without having any access to your primary (GitHub) repo.

simonw 26 October 2025
> It’s also backed up by default: If the server breaks, I’ve still got the copy on my laptop, and if my laptop breaks, I can download everything from the server.

This is true, but I do also like having backups that are entirely decoupled from my own infrastructure. GitHub personal private accounts are free and I believe they store your data redundantly in more than one region.

I imagine there's a way to setup a hook on your own server such that any pushes are then pushed to a GitHub copy without you having to do anything else yourself.

mmaaz 27 October 2025
Some time ago, I was on a team of researchers collaborating with a hospital to build some ML models for them. I joined the project somewhat late. There was a big fuss over the fact that the hospital servers were not connected to the internet, so the researchers couldn't use GitHub, so they had been stalled for months. I told them that before GitHub there was `git`, and it is already on the servers... I "set up" a git system for them.
BatteryMountain 27 October 2025
In interviews, I've literally asked senior devops engineers and senior software engineers if they have hosted their own git servers and how to initialise one and not a single one has mentioned git init --bare..... which is disconcerting. They can deploy appliances (like gitlab, gitea) and build pipelines just fine, but none of them realized how git actually works underneath and how simple it all is.
sam_lowry_ 27 October 2025
It's slightly more complicated to host your own git server on a generic linux box, because of file permissions.

I wrote a HOWTO a few weeks ago: http://mikhailian.mova.org/node/305

donatj 26 October 2025
Back when I started at my current job... 15 years ago... We had no central git server. No PR workflow. We just git pull-ed from each others machines. It worked better than you would expect.

We then went to using a central bare repo on a shared server, to hosted gitlab(? I think - it was Ruby and broke constantly) eventually landing on GitHub

tangotaylor 26 October 2025
Beware of using this to publish static sites: you can accidentally expose your .git directory to the public internet.

I got pwned this way before (by a pentester fortunately). I had to configure Apache to block the .git directory.

AoifeMurphy 27 October 2025
Self hosting Git isn’t just geek freedom, it’s a mindset of redundancy. I’ve had repos vanish due to platform bans that’s when it really hit me that “distributed” isn’t just a design, it’s a reminder of responsibility.
ezst 26 October 2025
As a git user "not by choice" (my preference going for mercurial every single day), I never understood why git needs this distinction between bare/non-bare (or commit vs staging for that matter). Seems like yet another leaky abstraction/bad design choice.
brendyn 27 October 2025
So my friend and I were trying to learn some coding together. We had our laptops on the same wifi and I wanted us to use git without depending on GitHub, but I was completely stumped as to how to actually connect us together. I don't want us to setup SSH servers on each other's laptops, giving each other full access to our computers, and sending patches to each other across the living room seems overkill when we're just sitting around hacking away on our keyboards wanting to share what we've come up with every few minutes or so. I still have no idea how I would solve this. Maybe I'd just try coding with a syncthing directory shared between us, but then that's totally giving up on git
globular-toast 26 October 2025
The proper way to do this to make a "bare" clone on the server (a clone without a checked out branch). I was doing this in 2010 before I even signed up to GitHub.
cycomanic 26 October 2025
I suspect many who always use git remotely don't know that you can easily work with local repositories as well using the file protocol, git clone file:///path/to/repository will create a clone of the repository at the path.

I used that all the time when I had to move private repositories back and forth from work, without ssh access.

gwd 26 October 2025
Git post-update hooks to do deployment FTW. I looked into the whole push-to-github to kick off CI and deployment; but someone mentioned the idea of pushing over ssh to a repo on your server and having a post-update hook do the deployment, and that turned out to be much simpler.
johnisgood 26 October 2025
I am surprised how little software engineers (even those that use) know about git.
timmg 26 October 2025
There was a brief period when Google Cloud had support for hosting git on a pay-per-use basis. (I think it was called Google Cloud Repositories.) It had a clunky but usable UI.

I really preferred the idea of just paying for what I used -- rather than being on a "freemium" model with GitHub.

But -- as many things with Google -- it was shutdown. Probably because most other people do prefer the freemium model.

I wonder if this kind of thing will come back in style someday, or if we are stuck with freemium/pro "tiers" for everything.

quasarj 26 October 2025
This is, in fact, what git was made for
patal 26 October 2025
How would I sync access, if more than one people ssh-pushes onto the git repo? I assume syncing be necessary.
singpolyma3 26 October 2025
One note, xcode and maybe some other clients can't use http "dumb mode". Smart mode is not hard to set up, but it's a few lines of server config more than this hook.

TIL about the update options for checked out branch. In practise though usually you want just the .git "bare" folder on server

m463 27 October 2025
You can do it with just directories too.

  mkdir -p repo/project
  cd repo/project
  git init --bare

  cd ../..
  git clone repo/project
  cd project
  (do git stuff)
1oooqooq 26 October 2025
this article is very bad advice. this way things are extremely brittle and there's a reason all those settings are disabled by default. you will lose data, save from very specific use cases

the vastly superior way is 'git bare' which is a first class supported command without hacky settings.

binary132 26 October 2025
This is definitely nice but it doesn’t really support the full range of features of Git, because for example submodules cannot be local references. It’s really just easier to set up gitolite and use that in almost the same exact way but it’s much better.
isolay 27 October 2025
I wonder what's the missing link between this manual setup and something like gitea. Is gitea just automation of this?
XorNot 26 October 2025
My git "server" is a folder of bare git repositories in home directory which I share with Syncthing.

It'd be great if there was more specific support. But in practice? No problems so far.

whirlwin 26 October 2025
This is how Heroku has been doing it for years since it started out 10+ years ago.

$ git push heroku master

So you'll have to make sure to push to e.g. GitHub as well for version control.

mberning 26 October 2025
I do something similar. I create a bare repo on my dropbox folder or nas mount. Then checkout from bare repo file path to some place where I will be doing all the work.
lukasnxyz 27 October 2025
I do this for blog posts, but for server side work I just rsync my dir, much easier
Froztnova 26 October 2025
Huh, y'know I shouldn't be surprised that this is possible given what I know about ssh and git. Yet I am.
JimmaDaRustla 27 October 2025
Git is not a client/server architecture
nicce 26 October 2025
Interesting. I am just trying to decide between self-hosting Forgejo and other options for hosting Git in own private network.
iwontberude 26 October 2025
“By default, git won’t let you push to the branch that is currently checked out”

TIL that people use non-bare git.

shravani_05_01 27 October 2025
I have instagram id hack please
OhMeadhbh 27 October 2025
Yup. I do something similar: HTTPS://BI6.US/GI/B
cncjchsue7 27 October 2025
git push prod

Until you have more users than dollars that's all you need.

ziofill 26 October 2025
What is it with code on blog posts where fonts have uneven size and/or font types (e.g. italics mixed in with regular)? I see this from time to time and I wonder if it’s intentional.
ctm92 26 October 2025
you don't even need ssh, you can also just store the remote on a local or remote file system
hk1337 26 October 2025
You could just put a bare repo on a usb drive and pass it around but I wouldn’t recommend it.
gijoeyguerra 26 October 2025
There’s also git daemon.
TZubiri 27 October 2025
Hmm. I typically have:

- a prod server ( and a test server) with a git repo.

- a local machine with the git repo.

- a git server where code officially lives, nowadays just a github.

If I were to simplify and run my own git server of the third kind, I would probably not run a server for the sole purpose of hosting code, it would most likely run on the prod/test server.

So essentially I would be eliminating one node and simplifying. I don't know, maybe there's merits to having an official place for code to be in. Even if just semantics.

I know you can also use branches to have a "master" branch with code and then have migrations just be merging from master into a prod branch, but then again, I could have just master branches, but if it's on the test server then it's the test branch.

I don't know if spendint time reinventing git workflows is a very efficient use of brain juice though.

max_ 26 October 2025
I tried this and it is never as smooth as described.

Why is GitHub popular? its not because people are "dumb" as others think.

Its because GitHub "Just Works".

You don't need obscure tribal knowledge like seba_dos1 suggests [0] or this comment https://news.ycombinator.com/item?id=45711294

The official Git documentation for example has its own documentation that I failed to get work. (it is vastly different from what OP is suggesting)

The problem with software development is that not knowing such "tribal knowledge" is considered incompetence.

People don't need to deal with obscure error messages which is why they choose GitHub & why Github won.

Like the adge goes, "Technology is best when it is invisible"

[0] https://news.ycombinator.com/item?id=45711236

[1] https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-...