repos / git-pr

a self-hosted git collaboration server
git clone https://github.com/picosh/git-pr.git

Eric Bower  ·  2025-02-21

README.md

  1![git-pr-logo](logo.png)
  2
  3# `pico/git-pr` a self-hosted git collaboration server
  4
  5We are trying to build the simplest git collaboration tool. The goal is to make
  6self-hosting a git server as simple as running an SSH server -- all without
  7sacrificing external collaborators time and energy.
  8
  9> `git format-patch` isn't the problem and pull requests aren't the solution.
 10
 11We are combining mailing list and pull request workflows. In order to build the
 12simplest collaboration tool, we needed something as simple as generating patches
 13but the ease-of-use of pull requests.
 14
 15The goal is not to create another code forge here. The goal is to create a very
 16simple self-hosted git solution with the ability to collaborate with external
 17contributors. All the code owner needs to setup a running git server:
 18
 19- A single golang binary
 20
 21All an external contributor needs is:
 22
 23- An SSH keypair
 24- An SSH client
 25
 26# demo video
 27
 28https://youtu.be/d28Dih-BBUw
 29
 30# the problem
 31
 32Email is great as a decentralized system to send and receive changes (patchsets)
 33to a git repo. However, onboarding a new user to a mailing list, properly
 34setting up their email client, and then finally submitting the code contribution
 35is enough to make many developers give up. Further, because we are leveraging
 36the email protocol for collaboration, we are limited by its feature-set. For
 37example, it is not possible to make edits to emails, everyone has a different
 38client, those clients have different limitations around plain text email and
 39downloading patches from it.
 40
 41Github pull requests are easy to use, easy to edit, and easy to manage. The
 42downside is it forces the user to be inside their website to perform reviews.
 43For quick changes, this is great, but when you start reading code within a web
 44browser, there are quite a few downsides. At a certain point, it makes more
 45sense to review code inside your local development environment, IDE, etc. There
 46are tools and plugins that allow users to review PRs inside their IDE, but it
 47requires a herculean effort to make it usable.
 48
 49Further, self-hosted solutions that mimic a pull request require a lot of
 50infrastructure in order to manage it. A database, a web site connected to git,
 51admin management, and services to manage it all. Another big point of friction:
 52before an external user submits a code change, they first need to create an
 53account and then login. This adds quite a bit of friction for a self-hosted
 54solution, not only for an external contributor, but also for the code owner who
 55has to provision the infra. Often times they also have to fork the repo within
 56the code forge before submitting a PR. Then they never make a contribution ever
 57again and a forked repo lingers. That seems silly.
 58
 59# introducing patch requests (PR)
 60
 61Instead, we want to create a self-hosted git "server" that can handle sending
 62and receiving patches without the cumbersome nature of setting up email or the
 63limitations imposed by the email protocol. Further, we want the primary workflow
 64to surround the local development environment. Github is bringing the IDE to the
 65browser in order to support their workflow, we want to flip that idea on its
 66head by making code reviews a first-class citizen inside your local development
 67environment. This has an interesting side-effect: the owner is placed in a more
 68collaborative role because they must create at least one patch to submit a
 69review. They are already in their local editor, they are already creating a git
 70commit and "pushing" it, so naturally it is easier to make code changes during
 71the review itself.
 72
 73We see this as a hybrid between the github workflow of a pull request and
 74sending and receiving patches over email.
 75
 76The basic idea is to leverage an SSH app to handle most of the interaction
 77between contributor and owner of a project. Everything can be done completely
 78within the terminal, in a way that is ergonomic and fully featured.
 79
 80The web view is mostly for discovery.
 81
 82Notifications would happen with RSS and all state mutations would result in the
 83generation of static web assets so the web views can be hosted using a simple
 84web file server.
 85
 86## format-patch workflow
 87
 88```bash
 89# Owner hosts repo `test.git` using github
 90
 91# Contributor clones repo
 92git clone git@github.com:picosh/test.git
 93
 94# Contributor wants to make a change
 95# Contributor makes changes via commits
 96git add -A && git commit -m "fix: some bugs"
 97
 98# Contributor runs:
 99git format-patch origin/main --stdout | ssh pr.pico.sh pr create test
100# > Patch Request has been created (ID: 1)
101
102# Owner can checkout patch:
103ssh pr.pico.sh pr print 1 | git am -3
104# Owner can comment (IN CODE), commit, then send another format-patch
105# on top of the PR:
106git format-patch origin/main --stdout | ssh pr.pico.sh pr add --review 1
107# UI clearly marks patch as a review
108
109# Contributor can checkout reviews
110ssh pr.pico.sh pr print 1 | git am -3
111
112# Owner can reject a pr:
113ssh pr.pico.sh pr close 1
114
115# Owner can accept a pr:
116ssh pr.pico.sh pr accept 1
117
118# Owner can prep PR for upstream:
119git rebase -i origin/main
120
121# Then push to upstream
122git push origin main
123
124# Done!
125```
126
127The fundamental collaboration tool here is `format-patch`. Whether you are
128submitting code changes or reviewing them, it all happens in code. Both
129contributor and owner are simply creating new commits and generating patches on
130top of each other. This obviates the need to have a web viewer where the
131reviewer can "comment" on a line of code block. There's no need, apply the
132contributor's patches, write comments or code changes, generate a new patch,
133send the patch to the git server as a "review." This flow also works the exact
134same if two users are collaborating on a set of changes.
135
136This also solves the problem of sending multiple patchsets for the same code
137change. There's a single, central Patch Request where all changes and
138collaboration happens.
139
140We could figure out a way to leverage `git notes` for reviews / comments, but
141honestly, that solution feels brutal and outside the comfort level of most git
142users. Just send reviews as code and write comments in the programming language
143you are using. It's the job of the contributor to "address" those comments and
144then remove them in subsequent patches. This is the forcing function to address
145all comments: the patch won't be merged if there are comment unaddressed in
146code; they cannot be ignored or else they will be upstreamed erroneously.
147
148# installation and setup
149
150## setup
151
152[Copy](./git-pr.toml) or create a `git-pr.toml` file inside `./data` directory:
153
154```bash
155mkdir data
156vim ./data/git-pr.toml
157# configure file
158```
159
160## docker
161
162Run the ssh app image:
163
164```bash
165docker run -d -v ./data:/app/data ghcr.io/picosh/pico/git-ssh:latest
166```
167
168Run the web app image:
169
170```bash
171docker run -d -v ./data:/app/data ghcr.io/picosh/pico/git-web:latest
172```
173
174## golang
175
176Clone this repo and then build the go binaries:
177
178```bash
179make build
180```
181
182```bash
183./build/ssh --config ./data/git-pr.toml
184```
185
186```bash
187./build/web --config ./data/git-pr.toml
188```
189
190## done!
191
192Access the ssh app:
193
194```bash
195ssh -p 2222 localhost help
196```
197
198Access the web app:
199
200```bash
201curl localhost:3000
202```
203
204# roadmap
205
206> [!IMPORTANT]\
207> This project is being actively developed and we have not reached alpha status
208> yet.
209
2101. Commenting system (git notes?)
2111. Support a `diff` workflow (convert `git diff` into mbox patch format)
2121. Moderation tooling
2131. Adapter to statically generate web view
214
215## ideas
216
2171. TUI?
2181. PR build steps? (e.g. ci/cd, status checks, merge checks)
2191. Bulk modify PRs? (rsync, sftp, sshfs)