···15draft: true
16---
1718-We're having great fun building pull requests -- so far you can create a
19-PR on Tangled using one of three ways:
20-21-- paste a diff in the UI
22-- compare two local branches within the same repository
23-- compare across forks
24-25-[!!!reword this]
2627We figured it would be fun to write about the engineering that went into
28building this, especially because Tangled is federated and Git repos
···36Creating a PR in Tangled starts with heading to `/pulls/new` in your
37target repository. Once there, you're presented with three options:
3839-- paste a patch in the UI
40-- compare two local branches (you'll see this only if you're a
41collaborator on the repo)
42-- compare across forks
4344Whatever you choose, at the core of every PR is the patch. You either
45supply it and make everyone's lives easier, or we generate it ourselves
···47cool actually). We'll skip explaining the part where you click around on
48the UI to create a new PR -- instead, let's talk about what comes after.
4950-We call it "rounds". Each round consists of a code review, and updating
51-the patch results in a new round. Rounds are -- obviously -- 0-indexed.
52-Here's an example.
5354<figure class="max-w-[450px] m-auto flex flex-col items-center justify-center">
55 <img class="h-auto max-w-full" src="/static/img/patch-pr-main.png">
56 <figcaption class="text-center">A new pull request with a couple
57-rounds of reviews.</figcaption>
58</figure>
5960Rounds are a far superior to standard branch-based
···72- It is possible to "interdiff" and observe changes made
73 across submissions (this is coming very soon to Tangled!)
7475-This [post](https://mitchellh.com/writing/github-changesets)
76-by Mitchell Hashimoto goes into further detail on what can
77-be achieved with round-based-review.
7879## fine, we'll make a patch ourselves
8008100000828384<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
85- <img class="h-auto max-w-full" src="/static/img/pr-flow.png">
86- <figcaption class="text-center">Simplified pull request flow.</figcaption>
87</figure>
888990-## what's in a fork?
000000009192Forks are just "clones" of another repository. They aren't your typical
93clones from `git clone` however, since we're operating on top of [bare
···116117[repo-record]: https://pdsls.dev/at://did:plc:hwevmowznbiukdf6uk5dwrrq/sh.tangled.repo/3lmrm7gu5dh22
118119-Great, we've got a fork on your knot now. You can now work on your
120-change safely here -- but how do you now propose a pull request from
121-your fork?
122123### ref comparisons across forks
124125-Great, so we now understand the anatomy of a PR and how comparing
126-branches (or more generally, refs) works. Astute readers would've
127-realised that so far, this only works *within* the same repository --
128-and not across forks, which is another git repository entirely.
0000129130-We'll admit: we ... omitted some sneaky bits about forks earlier. The
131-idea is simple: we already have all the pieces needed to compare two
132-local refs, so why not just "localize" the remote ref?
0133134-That's where our hidden tracking refs come in. When you create a pull
135-request from a fork, we create a refspec that tracks the remote branch,
136-which we then use to produce a diff. A refspec is a rule that tells Git
137-how to map references between a remote and your local repository during
138-fetch or push.
139140-Let's say your fork has a feature branch called `feature-1`, and you're
141-making a pull request into the `main` branch of the original repository.
142-We fetch the remote `main` into a local hidden ref using a refspec like
143-this:
144145```
146+refs/heads/main:refs/hidden/feature-1/main
147```
148149-And since we already have a remote (`origin`, by default) towards the
150-original repo (we just cloned it, rememeber?), we're able to `fetch`
151-this refspec and bring the remote `main` to our local hidden ref. Each
152-PR gets its own little hidden ref and hence the
153-`refs/hidden/:localRef/:remoteRef` format. We keep this ref up to date
154-whenever you push new commits to your feature branch, ensuring that the
155-comparison -- and any potential merge conflicts -- are always based on
156-the latest target branch state.
157-158-159-<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
160- <img class="h-auto max-w-full" src="/static/img/hidden-ref.png">
161- <figcaption class="text-center">Hidden tracking ref.</figcaption>
162-</figure>
163-164-
···15draft: true
16---
1718+We've been having great fun building pull requests. It's a feature we sort of
19+take for granted
0000002021We figured it would be fun to write about the engineering that went into
22building this, especially because Tangled is federated and Git repos
···30Creating a PR in Tangled starts with heading to `/pulls/new` in your
31target repository. Once there, you're presented with three options:
3233+- Paste a patch
34+- Compare two local branches (you'll see this only if you're a
35collaborator on the repo)
36+- Compare across forks
3738Whatever you choose, at the core of every PR is the patch. You either
39supply it and make everyone's lives easier, or we generate it ourselves
···41cool actually). We'll skip explaining the part where you click around on
42the UI to create a new PR -- instead, let's talk about what comes after.
4344+We call it "rounds". Each round consists of a code review: your patch recieves
45+scrutiny, and updating the patch in response, results in a new round. Rounds are
46+obviously 0-indexed. Here's an example.
4748<figure class="max-w-[450px] m-auto flex flex-col items-center justify-center">
49 <img class="h-auto max-w-full" src="/static/img/patch-pr-main.png">
50 <figcaption class="text-center">A new pull request with a couple
51+rounds of reviews. Thanks Jay!</figcaption>
52</figure>
5354Rounds are a far superior to standard branch-based
···66- It is possible to "interdiff" and observe changes made
67 across submissions (this is coming very soon to Tangled!)
6869+This [post by Mitchell
70+Hashimoto](https://mitchellh.com/writing/github-changesets) goes into further
71+detail on what can be achieved with round-based reviews.
7273## fine, we'll make a patch ourselves
7475+Remember our patch from earlier? Yeah, let's get into how comparing branches works.
7677+[you gotta talk about]
78+- merge and merge check?
79+- merge base thing
80+- sh.tangled.repo.patch lexicon
81+- nice segue into the fork section
828384<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
85+ <img class="h-auto max-w-full" src="/static/img/merge-base.png">
86+ <figcaption class="text-center">Merge base caption here! [!!!change this!]</figcaption>
87</figure>
888990+[!!!do we want this? use it to explain the patch merge/check process maybe]
91+<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
92+ <img class="h-auto max-w-full" src="/static/img/pr-flow.png">
93+ <figcaption class="text-center">Simplified pull request flow.</figcaption>
94+</figure>
95+96+97+98+## quick detour: what's in a fork?
99100Forks are just "clones" of another repository. They aren't your typical
101clones from `git clone` however, since we're operating on top of [bare
···124125[repo-record]: https://pdsls.dev/at://did:plc:hwevmowznbiukdf6uk5dwrrq/sh.tangled.repo/3lmrm7gu5dh22
126127+Great, we've got a fork on your knot now. You can now work on your change safely
128+here -- but let's get back to how we generate a patch across forks.
0129130### ref comparisons across forks
131132+We'll admit: we ... skipped some sneaky bits about forks earlier. Here's the
133+concept: since we already have all the necessary components to compare two local
134+refs, why not simply "localize" the remote ref?
135+136+In simpler terms, we instruct Git to fetch the target branch from the original
137+repository and store it in your fork under a special name. This approach allows
138+us to compare your changes against the most current version of the branch you're
139+trying to contribute to, all while remaining within your fork.
140141+<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
142+ <img class="h-auto max-w-full" src="/static/img/hidden-ref.png">
143+ <figcaption class="text-center">Hidden tracking ref.</figcaption>
144+</figure>
145146+We call this a "hidden tracking ref." When you create a pull request from a
147+fork, we establish a refspec that tracks the remote branch, which we then use to
148+generate a diff. A refspec is essentially a rule that tells Git how to map
149+references between a remote and your local repository during fetch or push
150+operations.
151152+For example, if your fork has a feature branch called `feature-1`, and you want
153+to make a pull request to the `main` branch of the original repository, we fetch
154+the remote `main` into a local hidden ref using a refspec like this:
0155156```
157+refs/heads/main:refs/hidden/feature-1/main
158```
159160+Since we already have a remote connection (`origin`, by default) to the original
161+repository (remember, we cloned it earlier), we can use `fetch` with this
162+refspec to bring the remote `main` branch into our local hidden ref. Each pull
163+request gets its own hidden ref, hence the `refs/hidden/:localRef/:remoteRef`
164+format. We keep this ref updated whenever you push new commits to your feature
165+branch, ensuring that comparisons -- and any potential merge conflicts -- are always
166+based on the latest state of the target branch.
000000000