git clone https://github.com/picosh/git-pr.git
1# patchbin
2
3A pastebin for patches, supercharged for git collaboration.
4
5Contributions are designed to be anonymous: the quality of your work is what matters. No signup required, just connect with an SSH key.
6
7The target project doesn't need to run patchbin for someone to submit a patch request against it. It works like a pull request, except both sides collaborate by sending rounds of patchsets: a contributor sends patches, a reviewer replies with their own patches on top, back and forth, as commits rather than comments. The result is a collaborative workspace built entirely out of patches. Reviewing means pulling the code down, not clicking through a diff viewer. Issues work the same way: an issue is just a patch request without any code attached yet, and anyone can follow up with a real patch request on top of it.
8
9There's no accept or reject step. A patch request is simply active or inactive: active ones go inactive after 30 days without activity. When a reviewer is happy with the code, they pull it, merge it, and push upstream themselves; there's nothing to manage here beyond that.
10
11## quickstart
12
13Submit a patch request (starts as a draft, visible only to you):
14
15```
16git format-patch main --stdout | ssh {url} pr create {repo}
17```
18
19Open it so others can see it (also enables RSS notifications):
20
21```
22ssh {url} pr open {prID}
23```
24
25Checkout the latest patchset from a patch request:
26
27```
28ssh {url} print pr-{prID} | git am -3
29```
30
31Add a follow-up patchset (e.g. after addressing review comments):
32
33```
34git format-patch main --stdout | ssh {url} pr add {prID}
35```
36
37Help guide:
38
39```
40ssh {url} help
41```
42
43## commands
44
45### pr - manage patch requests
46
47- `pr create {repo}` - submit a new PR from stdin (starts as draft)
48 ```
49 git format-patch main --stdout | ssh {url} pr create {repo}
50 ```
51- `pr add {prID}` - add a new patchset to an existing PR from stdin
52 ```
53 git format-patch main --stdout | ssh {url} pr add {prID}
54 ```
55- `pr open {prID} [--comment]` - transition draft open, enables RSS notifications
56 ```
57 ssh {url} pr open {prID}
58 ```
59- `pr draft {prID} [--comment]` - transition open draft, disables RSS notifications
60 ```
61 ssh {url} pr draft {prID}
62 ```
63- `pr edit {prID} {title}` - rename a PR
64 ```
65 ssh {url} pr edit {prID} "new title"
66 ```
67- `pr summary {prID}` - show metadata, patchsets, and patches for a PR
68 ```
69 ssh {url} pr summary {prID}
70 ```
71- `pr ls [repo] [--draft|--open|--active|--inactive|--mine]` - list PRs
72 ```
73 ssh {url} pr ls {repo} --open
74 ```
75
76### issue - text-only patch requests
77
78- `issue create {repo} [--title]` - submit a new issue from stdin (starts as open)
79 ```
80 echo "steps to reproduce..." | ssh {url} issue create {repo} --title "bug: crash on startup"
81 ```
82
83### ps - manage patchsets
84
85- `ps rm {patchsetID}` - remove a patchset and its patches (creator only)
86 ```
87 ssh {url} ps rm ps-{patchsetID}
88 ```
89
90### print - print patches for checkout
91
92- `print pr-{prID}` - print the latest patchset for a PR
93 ```
94 ssh {url} print pr-{prID} | git am -3
95 ```
96- `print ps-{patchsetID}` - print a specific patchset
97 ```
98 ssh {url} print ps-{patchsetID} | git am -3
99 ```
100
101### logs - event history
102
103- `logs [--pr ID] [--pubkey]` - list event logs, optionally filtered to a PR or your own activity
104 ```
105 ssh {url} logs --pr {prID}
106 ```
107
108## self-hosting
109
110patchbin needs a `patchbin.toml` config file and a data directory (for the sqlite db and SSH host keys).
111
112[Copy](./patchbin.toml) or create a `patchbin.toml` file inside a `./data` directory:
113
114```
115mkdir -p data
116cp patchbin.toml ./data/patchbin.toml
117vim ./data/patchbin.toml
118```
119
120### docker-compose
121
122The included `docker-compose.yml` pulls the published image and mounts a local data directory:
123
124```
125services:
126 patchbin:
127 image: ghcr.io/picosh/pico/patchbin:latest
128 restart: always
129 volumes:
130 - ./data/patchbin/data:/app/data
131```
132
133Place `patchbin.toml` inside `./data/patchbin/data`, then run:
134
135```
136docker compose up -d
137```
138
139### docker image
140
141Run the image directly, mounting your data directory to `/app/data`:
142
143```
144docker run -d -v ./data:/app/data ghcr.io/picosh/pico/patchbin:latest
145```
146
147`patchbin.toml` must live inside the mounted `./data` directory, since that's the default config path the binary looks for.
148
149### from go source
150
151Clone the repo, then build and run the binary:
152
153```
154make build
155./build/patchbin --config ./data/patchbin.toml
156```
157
158Or without the Makefile:
159
160```
161go build -o ./build/patchbin ./cmd/patchbin
162./build/patchbin --config ./data/patchbin.toml
163```
164
165### done
166
167Access the SSH app:
168
169```
170ssh -p 2222 localhost help
171```
172
173Access the web app:
174
175```
176curl localhost:3000
177```