· erock's pastes · raw

expires: 30 Jul, 2024

  1# rfc: `pico/git` a self-hosted git server
  3The goal is not to create another code forge here. The goal is to create a very
  4simple self-hosted git solution with the ability to collaborate with external
  5contributors. All the code owner needs to setup a running git server:
  7- A single golang binary
  8- sqlite to store patch requests and other repo metadata
 10All an external contributor needs is:
 12- An SSH keypair
 13- An SSH client
 15# patch requests
 17Email is great as a decentralized system to send and receive changes (patchsets)
 18to a git repo. However, setting up your email client and understanding the
 19potential gotchas during that flow cannot be understated. Further, because we
 20are leveraging the email protocol for communication and collaboration, we are
 21limited by its feature-set. In particular, it is not possible to make edits to
 22emails, so if there are typos or the contributor forgot to include some code or
 23a line in the cover letter, there is a lot of back-and-forth noise to make those
 26Further, when a contributor provides a patchset and receives feedback, the
 27contributor must submit another patchset via email. These are completely
 28separate and the only way to correlate them is via naming convention (e.g.
 29[PATCH] xxx v2). Now when reviewing patchsets submitted to a project, the user
 30must search for all versions of that particular patchset. These are separate
 31conversations with potentially very different patches spanning across the time
 32of a project. Maybe that's ok, but people are very used to a PR containing all
 33changes and reviews across time, and I think it makes a lot of sense to have a
 34single view of all conversations related to a change request.
 36Another issue with the email workflow is knowing how to properly reply to a
 37patchset. There is a lot of education on "doing patchsets right via email."
 39Github pull requests are easy to use, easy to edit, and easy to manage. The
 40downside is it forces the user to be inside their website to perform reviews.
 41For quick changes, this is great, but when you start reading code within a web
 42browser, there are quite a few downsides. At a certain point, it makes more
 43sense to review code inside your local development environment, IDE, etc.
 44Further, self-hosted solutions that mimick a pull request require a lot of
 45infrastructure in order to manage it. For example, before an external user who
 46wants to contribute to a repo, they first need to create an account and then
 47login. This adds quite a bit of friction for a self-hosted solution, not only
 48for an external contributor, but also for the code owner who has to provision
 49the infra.
 51Instead, I want to create a self-hosted git "server" that can handle sending and
 52receiving patches without the cumbersome nature of setting up email or the
 53limitations imposed by the email protocol. Further, I want the primary workflow
 54to surround the local development environment. Github is bringing the IDE to the
 55browser in order to support their workflow, I want to bring the workflow to the
 56local dev environment.
 58I see this as a hybrid between the github workflow of a pull request and sending
 59and receiving patches over email.
 61The basic idea is to leverage an SSH app to handle most of the interaction
 62between contributor and owner of a project. Everything can be done completely
 63within the terminal, in a way that is ergonomic and fully featured.
 65## format-patch workflow
 68# Owner hosts repo `noice.git` using pico/git
 70# Contributor clones repo
 71git clone
 73# Contributor wants to make a change
 74# Contributor makes changes via commits
 75git add -A && git commit -m "fix: some bugs"
 77# Contributor runs:
 78git format-patch --stdout | ssh pr noice
 79# > Patch Request has been created (ID: noice/1)
 81# Contributor can copy down patch request metadata:
 82rsync .
 83# Contributor edits patch request metadata, then runs:
 86# Owner can checkout patch:
 87ssh pr noice/1 | git am -3
 88# Owner can comment in code, then commit, then send another format-patch
 89# on top of it:
 90git format-patch --stdout | ssh pr noice/1 --review
 91# We do some magic in the UI to make this look like comments or someway to
 92# clearly mark as a review
 94# Owner can reject a pr:
 95ssh pr noice/1 --close
 96# (-maybe-) Owner can merge a pr:
 97ssh pr noice/1 --squash-n-merge
 99# Contributor can checkout reviews
100ssh pr noice/1 | git am -3
102# Commenting
103cat | txt noice/1
105# rinse and repeat
108The fundamental collaboration tool here is `format-patch`. Whether you a
109submitting code changes or you are reviewing code changes, it all happens in
110code. Both contributor and owner are simply creating new commits and generating
111patches on top of each other. This obviates the need to have a web viewer where
112the reviewing can "comment" on a line of code block. There's no need, apply the
113contributor's patches, write comments or code changes, generate a new patch,
114send the patch to the git server as a "review." This flow also works the exact
115same if two users are collaborating on a set of changes.
117This also solves the problem of sending multiple patchsets for the same code
118change. There's a single, central Patch Request where all changes and
119collaboration happens.
121We could figure out a way to leverage `git notes` for reviews / comments, but
122honestly, that solution feels brutal and outside the comfort level of most git
123users. Just send reviews as code and write comments in the programming language
124you are using. It's the job of the contributor to "address" those comments and
125then remove them in subsequent patches.
127## branch workflow
129It's definitely possible for us to figure out a way to let the contributor
130simply push a branch and create a patch request automatically, but there are
131some rough edges to figure out there in order for it to work well.
133The flow would be virtually the same as `format-patch` except the contributor
134would push a branch and we would automatically create a `format-patch` against
135the base branch and then funnel it into the Patch Request. We don't want
136external contributors to be able to push branches into the owner's git remote
137because that has all sorts of opportunities for abuse. Instead we need to figure
138out how to either fork the owner's repo and let the contributor push to that
139fork seamlessly, or we just generate patchsets based on the contributor's branch
140and the owner's base branch.
142This flow probably feels the most comfortable for Github users, but technically
143more difficult to implement. Right out of the gate we need to know what base
144branch the contributor wants to merge into. Then we need to figure out how to
145perform reviews and followup code changes.
147This feels feasible, but technically more difficult. Further, I still want to
148support patchsets via `format-patch` because it is a very elegant solution for
149simpler changes.
151# web interface
153The other idea is to make the git web viewer completely static. Whenever an
154owner pushes code, we generate all the static assets for that branch. We already
155have a working prototype [pgit]( that mostly
156works. Further, any patch request that gets submitted would also be statically
157generated. If we don't have a web portal with authentication and the ability to
158manage a repo / patch request inside the web viewer, then a static site becomes
159possible. This makes the web component of a git server much simpler, since it is
160just static assets. All we need to do is install a git hook that properly
161generates the static assets. For patch requests, everything comes through our
162SSH app so we can generate the assets when those commands are being run.
164# research