dashboard / erock/git-pr / docs proposal #60 rss

open · opened on 2025-04-07T22:44:49Z by jolheiser
Help
checkout latest patchset:
ssh pr.pico.sh print pr-60 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print ps-X | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 60
add review to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add --review 60
accept PR:
ssh pr.pico.sh pr accept 60
close PR:
ssh pr.pico.sh pr close 60

Logs

jolheiser created pr with ps-125 on 2025-04-07T22:44:49Z

Patchsets

ps-125 by jolheiser on 2025-04-07T22:44:49Z

Patchset ps-125

docs proposal

jolheiser
2025-04-07T22:42:31Z
.gitignore
+2 -0
tmpl/docs.html
+235 -0
tmpl/index.html
+3 -222
web.go
+16 -0
Back to top

docs proposal

This is closer to what I was thinking for docs.
This keeps a lot of the exposition off the main page and moves it to a separate page.

Signed-off-by: jolheiser <git@jolheiser.com>
.gitignore link
+2 -0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
diff --git a/.gitignore b/.gitignore
index 755c339..17cca57 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,5 @@ __debug_bin
 /public/
 test.db
 review.patch
+git-web*
+git-ssh*
tmpl/docs.html link
+235 -0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
diff --git a/tmpl/docs.html b/tmpl/docs.html
new file mode 100644
index 0000000..f0fe451
--- /dev/null
+++ b/tmpl/docs.html
@@ -0,0 +1,235 @@
+{{template "base" .}}
+
+{{define "title"}}docs{{end}}
+
+{{define "meta"}}{{end}}
+
+{{define "body"}}
+<header class="group">
+  <h1 class="text-2xl">docs</h1>
+  <div>
+    <a href="/">dashboard</a> &middot;
+    <a href="https://github.com/picosh/git-pr">github</a> &middot;
+    <a href="https://youtu.be/d28Dih-BBUw">demo video</a>
+  </div>
+</header>
+<main class="group">
+  <details>
+    <summary>Intro</summary>
+
+    <div>
+      <p>
+        We are trying to build the simplest git collaboration tool. The goal is to make
+        self-hosting as simple as running an SSH server -- all without
+        sacrificing external collaborators time and energy.
+      </p>
+
+      <blockquote>
+        <code>git format-patch</code> isn't the problem and pull requests aren't the solution.
+      </blockquote>
+
+      <p>
+        We are combining mailing list and pull request workflows. In order to build the
+        simplest collaboration tool, we needed something as simple as generating patches
+        but the ease-of-use of pull requests.
+      </p>
+
+      <p>
+        The goal is not to create another code forge, the goal is to create a very
+        simple self-hosted git solution with the ability to collaborate with external
+        contributors. All the code owner needs to setup a running git server:
+      </p>
+
+      <ul>
+        <li>A single golang binary</li>
+      </ul>
+
+      <div>
+        All an external contributor needs is:
+      </div>
+
+      <ul>
+        <li>An SSH keypair</li>
+        <li>An SSH client</li>
+      </ul>
+
+      <p>Then everyone subscribes to our RSS feeds to receive updates to patch requests.</p>
+
+      <h2 class="text-xl">the problem</h2>
+
+      <p>
+        Email is great as a decentralized system to send and receive changes (patchsets)
+        to a git repo. However, onboarding a new user to a mailing list, properly
+        setting up their email client, and then finally submitting the code contribution
+        is enough to make many developers give up. Further, because we are leveraging
+        the email protocol for collaboration, we are limited by its feature-set. For
+        example, it is not possible to make edits to emails, everyone has a different
+        client, those clients have different limitations around plain text email and
+        downloading patches from it.
+      </p>
+
+      <p>
+        Github pull requests are easy to use, easy to edit, and easy to manage. The
+        downside is it forces the user to be inside their website to perform reviews.
+        For quick changes, this is great, but when you start reading code within a web
+        browser, there are quite a few downsides. At a certain point, it makes more
+        sense to review code inside your local development environment, IDE, etc. There
+        are tools and plugins that allow users to review PRs inside their IDE, but it
+        requires a herculean effort to make it usable.
+      </p>
+
+      <p>
+        Further, self-hosted solutions that mimic a pull request require a lot of
+        infrastructure in order to manage it. A database, a web site connected to git,
+        admin management, and services to manage it all. Another big point of friction:
+        before an external user submits a code change, they first need to create an
+        account and then login. This adds quite a bit of friction for a self-hosted
+        solution, not only for an external contributor, but also for the code owner who
+        has to provision the infra. Often times they also have to fork the repo within
+        the code forge before submitting a PR. Then they never make a contribution ever
+        again and keep a forked repo around forever. That seems silly.
+      </p>
+
+      <h2 class="text-xl">introducing patch requests (PR)</h2>
+
+      <p>
+        Instead, we want to create a self-hosted git "server" that can handle sending
+        and receiving patches without the cumbersome nature of setting up email or the
+        limitations imposed by the email protocol. Further, we want the primary workflow
+        to surround the local development environment. Github is bringing the IDE to the
+        browser in order to support their workflow, we want to flip that idea on its
+        head by making code reviews a first-class citizen inside your local development
+        environment.
+      </p>
+
+      <p>
+        We see this as a hybrid between the github workflow of a pull request and
+        sending and receiving patches over email.
+      </p>
+
+      <p>
+        The basic idea is to leverage an SSH app to handle most of the interaction
+        between contributor and owner of a project. Everything can be done completely
+        within the terminal, in a way that is ergonomic and fully featured.
+      </p>
+
+      <p>
+        Notifications would happen with RSS and all state mutations would result in the
+        generation of static web assets so it can all be hosted using a simple file web
+        server.
+      </p>
+
+      <h3 class="text-lg">format-patch workflow</h3>
+
+      <p>
+        The fundamental collaboration tool here is <code>format-patch</code>. Whether you a
+        submitting code changes or you are reviewing code changes, it all happens in
+        code. Both contributor and owner are simply creating new commits and generating
+        patches on top of each other. This obviates the need to have a web viewer where
+        the reviewing can "comment" on a line of code block. There's no need, apply the
+        contributor's patches, write comments or code changes, generate a new patch,
+        send the patch to the git server as a "review." This flow also works the exact
+        same if two users are collaborating on a set of changes.
+      </p>
+
+      <p>
+        This also solves the problem of sending multiple patchsets for the same code
+        change. There's a single, central Patch Request where all changes and
+        collaboration happens.
+      </p>
+
+      <p>
+        We could figure out a way to leverage <code>git notes</code> for reviews / comments, but
+        honestly, that solution feels brutal and outside the comfort level of most git
+        users. Just send reviews as code and write comments in the programming language
+        you are using. It's the job of the contributor to "address" those comments and
+        then remove them in subsequent patches. This is the forcing function to address
+        all comments: the patch won't be merged if there are comment unaddressed in
+        code; they cannot be ignored or else they will be upstreamed erroneously.
+      </p>
+    </div>
+  </details>
+
+  <details>
+    <summary>How do Patch Requests work?</summary>
+    <div>
+      Patch requests (PR) are the simplest way to submit, review, and accept changes to your git repository.
+      Here's how it works:
+    </div>
+
+    <ol>
+      <li>External contributor clones repo (<code>git-clone</code>)</li>
+      <li>External contributor makes a code change (<code>git-add</code> & <code>git-commit</code>)</li>
+      <li>External contributor generates patches (<code>git-format-patch</code>)</li>
+      <li>External contributor submits a PR to SSH server</li>
+      <li>Owner receives RSS notification that there's a new PR</li>
+      <li>Owner applies patches locally (<code>git-am</code>) from SSH server</li>
+      <li>Owner makes suggestions in code! (<code>git-add</code> & <code>git-commit</code>)</li>
+      <li>Owner submits review by piping patch to SSH server (<code>git-format-patch</code>)</li>
+      <li>External contributor receives RSS notification of the PR review</li>
+      <li>External contributor re-applies patches (<code>git-am</code>)</li>
+      <li>External contributor reviews and removes comments in code!</li>
+      <li>External contributor submits another patch (<code>git-format-patch</code>)</li>
+      <li>Owner applies patches locally (<code>git-am</code>)</li>
+      <li>Owner marks PR as accepted and pushes code to main (<code>git-push</code>)</li>
+    </ol>
+
+    <div>Example commands</div>
+
+    <pre># Owner hosts repo `test.git` using github
+
+      # Contributor clones repo
+      git clone git@github.com:picosh/test.git
+
+      # Contributor wants to make a change
+      # Contributor makes changes via commits
+      git add -A && git commit -m "fix: some bugs"
+
+      # Contributor runs:
+      git format-patch origin/main --stdout | ssh {{.MetaData.URL}} pr create test
+      # > Patch Request has been created (ID: 1)
+
+      # Owner can checkout patch:
+      ssh {{.MetaData.URL}} pr print 1 | git am -3
+
+      # Owner can comment (IN CODE), commit, then send another format-patch
+      # on top of the PR:
+      git format-patch origin/main --stdout | ssh {{.MetaData.URL}} pr add --review 1
+      # UI clearly marks patch as a review
+
+      # Contributor can checkout reviews
+      ssh {{.MetaData.URL}} print pr-1 | git am -3
+
+      # Owner can reject a pr:
+      ssh {{.MetaData.URL}} pr close 1
+
+      # Owner can accept a pr:
+      ssh {{.MetaData.URL}} pr accept 1
+
+      # Owner can prep PR for upstream:
+      git rebase -i origin/main
+
+      # Then push to upstream
+      git push origin main
+
+      # Done!
+    </pre>
+  </details>
+
+  <details>
+    <summary>First time user?</summary>
+
+    <div>
+      Using this service for the first time? Creating a patch request is simple:
+    </div>
+
+    <pre>git format-patch main --stdout | ssh {{.MetaData.URL}} pr create {repo}</pre>
+
+    <div>When running that command we will automatically create a user and a repo if one doesn't exist.</div>
+
+    <div>Want to submit a v2 of the patch request?</div>
+
+    <pre>git format-patch main --stdout | ssh {{.MetaData.URL}} pr add {prID}</pre>
+  </details>
+</main>
+{{end}}
\ No newline at end of file
tmpl/index.html link
+3 -222
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
diff --git a/tmpl/index.html b/tmpl/index.html
index 1e17819..2602743 100644
--- a/tmpl/index.html
+++ b/tmpl/index.html
@@ -3,9 +3,7 @@
 {{define "title"}}git-pr{{end}}
 
 {{define "meta"}}
-<link rel="alternate" type="application/atom+xml"
-      title="RSS feed for git collaboration server"
-      href="/rss" />
+<link rel="alternate" type="application/atom+xml" title="RSS feed for git collaboration server" href="/rss">
 {{end}}
 
 {{define "body"}}
@@ -13,8 +11,7 @@
   <h1 class="text-2xl">git-pr</h1>
   <div>
     <span>A pastebin supercharged for git collaboration</span> &middot;
-    <a href="https://github.com/picosh/git-pr">github</a> &middot;
-    <a href="https://youtu.be/d28Dih-BBUw">demo video</a>
+    <a href="/docs">docs</a>
   </div>
 
   {{if .MetaData.Desc}}
@@ -22,222 +19,6 @@
     <div>{{.MetaData.Desc}}</div>
   </div>
   {{end}}
-
-  <details>
-    <summary>Intro</summary>
-
-    <div>
-      <p>
-        We are trying to build the simplest git collaboration tool. The goal is to make
-        self-hosting as simple as running an SSH server -- all without
-        sacrificing external collaborators time and energy.
-      </p>
-
-      <blockquote>
-        <code>git format-patch</code> isn't the problem and pull requests aren't the solution.
-      </blockquote>
-
-      <p>
-        We are combining mailing list and pull request workflows. In order to build the
-        simplest collaboration tool, we needed something as simple as generating patches
-        but the ease-of-use of pull requests.
-      </p>
-
-      <p>
-        The goal is not to create another code forge, the goal is to create a very
-        simple self-hosted git solution with the ability to collaborate with external
-        contributors. All the code owner needs to setup a running git server:
-      </p>
-
-      <ul><li>A single golang binary</li></ul>
-
-      <div>
-        All an external contributor needs is:
-      </div>
-
-      <ul>
-        <li>An SSH keypair</li>
-        <li>An SSH client</li>
-      </ul>
-
-      <p>Then everyone subscribes to our RSS feeds to receive updates to patch requests.</p>
-
-      <h2 class="text-xl">the problem</h2>
-
-      <p>
-        Email is great as a decentralized system to send and receive changes (patchsets)
-        to a git repo. However, onboarding a new user to a mailing list, properly
-        setting up their email client, and then finally submitting the code contribution
-        is enough to make many developers give up. Further, because we are leveraging
-        the email protocol for collaboration, we are limited by its feature-set. For
-        example, it is not possible to make edits to emails, everyone has a different
-        client, those clients have different limitations around plain text email and
-        downloading patches from it.
-      </p>
-
-      <p>
-        Github pull requests are easy to use, easy to edit, and easy to manage. The
-        downside is it forces the user to be inside their website to perform reviews.
-        For quick changes, this is great, but when you start reading code within a web
-        browser, there are quite a few downsides. At a certain point, it makes more
-        sense to review code inside your local development environment, IDE, etc. There
-        are tools and plugins that allow users to review PRs inside their IDE, but it
-        requires a herculean effort to make it usable.
-      </p>
-
-      <p>
-        Further, self-hosted solutions that mimic a pull request require a lot of
-        infrastructure in order to manage it. A database, a web site connected to git,
-        admin management, and services to manage it all. Another big point of friction:
-        before an external user submits a code change, they first need to create an
-        account and then login. This adds quite a bit of friction for a self-hosted
-        solution, not only for an external contributor, but also for the code owner who
-        has to provision the infra. Often times they also have to fork the repo within
-        the code forge before submitting a PR. Then they never make a contribution ever
-        again and keep a forked repo around forever. That seems silly.
-      </p>
-
-      <h2 class="text-xl">introducing patch requests (PR)</h2>
-
-      <p>
-        Instead, we want to create a self-hosted git "server" that can handle sending
-        and receiving patches without the cumbersome nature of setting up email or the
-        limitations imposed by the email protocol. Further, we want the primary workflow
-        to surround the local development environment. Github is bringing the IDE to the
-        browser in order to support their workflow, we want to flip that idea on its
-        head by making code reviews a first-class citizen inside your local development
-        environment.
-      </p>
-
-      <p>
-        We see this as a hybrid between the github workflow of a pull request and
-        sending and receiving patches over email.
-      </p>
-
-      <p>
-        The basic idea is to leverage an SSH app to handle most of the interaction
-        between contributor and owner of a project. Everything can be done completely
-        within the terminal, in a way that is ergonomic and fully featured.
-      </p>
-
-      <p>
-        Notifications would happen with RSS and all state mutations would result in the
-        generation of static web assets so it can all be hosted using a simple file web
-        server.
-      </p>
-
-      <h3 class="text-lg">format-patch workflow</h3>
-
-      <p>
-        The fundamental collaboration tool here is <code>format-patch</code>. Whether you a
-        submitting code changes or you are reviewing code changes, it all happens in
-        code. Both contributor and owner are simply creating new commits and generating
-        patches on top of each other. This obviates the need to have a web viewer where
-        the reviewing can "comment" on a line of code block. There's no need, apply the
-        contributor's patches, write comments or code changes, generate a new patch,
-        send the patch to the git server as a "review." This flow also works the exact
-        same if two users are collaborating on a set of changes.
-      </p>
-
-      <p>
-        This also solves the problem of sending multiple patchsets for the same code
-        change. There's a single, central Patch Request where all changes and
-        collaboration happens.
-      </p>
-
-      <p>
-        We could figure out a way to leverage <code>git notes</code> for reviews / comments, but
-        honestly, that solution feels brutal and outside the comfort level of most git
-        users. Just send reviews as code and write comments in the programming language
-        you are using. It's the job of the contributor to "address" those comments and
-        then remove them in subsequent patches. This is the forcing function to address
-        all comments: the patch won't be merged if there are comment unaddressed in
-        code; they cannot be ignored or else they will be upstreamed erroneously.
-      </p>
-    </div>
-  </details>
-
-  <details>
-    <summary>How do Patch Requests work?</summary>
-      <div>
-        Patch requests (PR) are the simplest way to submit, review, and accept changes to your git repository.
-        Here's how it works:
-      </div>
-
-      <ol>
-        <li>External contributor clones repo (<code>git-clone</code>)</li>
-        <li>External contributor makes a code change (<code>git-add</code> & <code>git-commit</code>)</li>
-        <li>External contributor generates patches (<code>git-format-patch</code>)</li>
-        <li>External contributor submits a PR to SSH server</li>
-        <li>Owner receives RSS notification that there's a new PR</li>
-        <li>Owner applies patches locally (<code>git-am</code>) from SSH server</li>
-        <li>Owner makes suggestions in code! (<code>git-add</code> & <code>git-commit</code>)</li>
-        <li>Owner submits review by piping patch to SSH server (<code>git-format-patch</code>)</li>
-        <li>External contributor receives RSS notification of the PR review</li>
-        <li>External contributor re-applies patches (<code>git-am</code>)</li>
-        <li>External contributor reviews and removes comments in code!</li>
-        <li>External contributor submits another patch (<code>git-format-patch</code>)</li>
-        <li>Owner applies patches locally (<code>git-am</code>)</li>
-        <li>Owner marks PR as accepted and pushes code to main (<code>git-push</code>)</li>
-      </ol>
-
-      <div>Example commands</div>
-
-      <pre># Owner hosts repo `test.git` using github
-
-# Contributor clones repo
-git clone git@github.com:picosh/test.git
-
-# Contributor wants to make a change
-# Contributor makes changes via commits
-git add -A && git commit -m "fix: some bugs"
-
-# Contributor runs:
-git format-patch origin/main --stdout | ssh {{.MetaData.URL}} pr create test
-# > Patch Request has been created (ID: 1)
-
-# Owner can checkout patch:
-ssh {{.MetaData.URL}} pr print 1 | git am -3
-
-# Owner can comment (IN CODE), commit, then send another format-patch
-# on top of the PR:
-git format-patch origin/main --stdout | ssh {{.MetaData.URL}} pr add --review 1
-# UI clearly marks patch as a review
-
-# Contributor can checkout reviews
-ssh {{.MetaData.URL}} print pr-1 | git am -3
-
-# Owner can reject a pr:
-ssh {{.MetaData.URL}} pr close 1
-
-# Owner can accept a pr:
-ssh {{.MetaData.URL}} pr accept 1
-
-# Owner can prep PR for upstream:
-git rebase -i origin/main
-
-# Then push to upstream
-git push origin main
-
-# Done!
-</pre>
-  </details>
-
-  <details>
-    <summary>First time user?</summary>
-
-    <div>
-      Using this service for the first time?  Creating a patch request is simple:
-    </div>
-
-    <pre>git format-patch main --stdout | ssh {{.MetaData.URL}} pr create {repo}</pre>
-
-    <div>When running that command we will automatically create a user and a repo if one doesn't exist.</div>
-
-    <div>Want to submit a v2 of the patch request?</div>
-
-    <pre>git format-patch main --stdout | ssh {{.MetaData.URL}} pr add {prID}</pre>
-  </details>
 </header>
 
 <main>
@@ -255,4 +36,4 @@ git push origin main
 <footer class="mt">
   <a href="/rss">rss</a>
 </footer>
-{{end}}
+{{end}}
\ No newline at end of file
web.go link
+16 -0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
diff --git a/web.go b/web.go
index cab9357..09f1ec6 100644
--- a/web.go
+++ b/web.go
@@ -339,6 +339,21 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
 	}
 }
 
+func docsHandler(w http.ResponseWriter, r *http.Request) {
+	web, err := getWebCtx(r)
+	if err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Set("content-type", "text/html")
+	tmpl := getTemplate("docs.html")
+	err = tmpl.ExecuteTemplate(w, "docs.html", nil)
+	if err != nil {
+		web.Backend.Logger.Error("cannot execute template", "err", err)
+	}
+}
+
 type UserData struct {
 	UserID    int64
 	Name      string
@@ -1131,6 +1146,7 @@ func StartWebServer(cfg *GitCfg) {
 	http.HandleFunc("GET /r/{user}", ctxMdw(ctx, userDetailHandler))
 	http.HandleFunc("GET /rss/{user}", ctxMdw(ctx, rssHandler))
 	http.HandleFunc("GET /rss", ctxMdw(ctx, rssHandler))
+	http.HandleFunc("GET /docs", ctxMdw(ctx, docsHandler))
 	http.HandleFunc("GET /", ctxMdw(ctx, indexHandler))
 	http.HandleFunc("GET /syntax.css", ctxMdw(ctx, chromaStyleHandler))
 	embedFS, err := getEmbedFS(embedStaticFS, "static")