···1515draft: true
1616---
17171818-We're having great fun building pull requests -- so far you can create a
1919-PR on Tangled using one of three ways:
2020-2121-- paste a diff in the UI
2222-- compare two local branches within the same repository
2323-- compare across forks
2424-2525-[!!!reword this]
1818+We've been having great fun building pull requests. It's a feature we sort of
1919+take for granted
26202721We figured it would be fun to write about the engineering that went into
2822building this, especially because Tangled is federated and Git repos
···3630Creating a PR in Tangled starts with heading to `/pulls/new` in your
3731target repository. Once there, you're presented with three options:
38323939-- paste a patch in the UI
4040-- compare two local branches (you'll see this only if you're a
3333+- Paste a patch
3434+- Compare two local branches (you'll see this only if you're a
4135collaborator on the repo)
4242-- compare across forks
3636+- Compare across forks
43374438Whatever you choose, at the core of every PR is the patch. You either
4539supply it and make everyone's lives easier, or we generate it ourselves
···4741cool actually). We'll skip explaining the part where you click around on
4842the UI to create a new PR -- instead, let's talk about what comes after.
49435050-We call it "rounds". Each round consists of a code review, and updating
5151-the patch results in a new round. Rounds are -- obviously -- 0-indexed.
5252-Here's an example.
4444+We call it "rounds". Each round consists of a code review: your patch recieves
4545+scrutiny, and updating the patch in response, results in a new round. Rounds are
4646+obviously 0-indexed. Here's an example.
53475448<figure class="max-w-[450px] m-auto flex flex-col items-center justify-center">
5549 <img class="h-auto max-w-full" src="/static/img/patch-pr-main.png">
5650 <figcaption class="text-center">A new pull request with a couple
5757-rounds of reviews.</figcaption>
5151+rounds of reviews. Thanks Jay!</figcaption>
5852</figure>
59536054Rounds are a far superior to standard branch-based
···7266- It is possible to "interdiff" and observe changes made
7367 across submissions (this is coming very soon to Tangled!)
74687575-This [post](https://mitchellh.com/writing/github-changesets)
7676-by Mitchell Hashimoto goes into further detail on what can
7777-be achieved with round-based-review.
6969+This [post by Mitchell
7070+Hashimoto](https://mitchellh.com/writing/github-changesets) goes into further
7171+detail on what can be achieved with round-based reviews.
78727973## fine, we'll make a patch ourselves
80747575+Remember our patch from earlier? Yeah, let's get into how comparing branches works.
81767777+[you gotta talk about]
7878+- merge and merge check?
7979+- merge base thing
8080+- sh.tangled.repo.patch lexicon
8181+- nice segue into the fork section
828283838484<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
8585- <img class="h-auto max-w-full" src="/static/img/pr-flow.png">
8686- <figcaption class="text-center">Simplified pull request flow.</figcaption>
8585+ <img class="h-auto max-w-full" src="/static/img/merge-base.png">
8686+ <figcaption class="text-center">Merge base caption here! [!!!change this!]</figcaption>
8787</figure>
888889899090-## what's in a fork?
9090+[!!!do we want this? use it to explain the patch merge/check process maybe]
9191+<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
9292+ <img class="h-auto max-w-full" src="/static/img/pr-flow.png">
9393+ <figcaption class="text-center">Simplified pull request flow.</figcaption>
9494+</figure>
9595+9696+9797+9898+## quick detour: what's in a fork?
919992100Forks are just "clones" of another repository. They aren't your typical
93101clones from `git clone` however, since we're operating on top of [bare
···116124117125[repo-record]: https://pdsls.dev/at://did:plc:hwevmowznbiukdf6uk5dwrrq/sh.tangled.repo/3lmrm7gu5dh22
118126119119-Great, we've got a fork on your knot now. You can now work on your
120120-change safely here -- but how do you now propose a pull request from
121121-your fork?
127127+Great, we've got a fork on your knot now. You can now work on your change safely
128128+here -- but let's get back to how we generate a patch across forks.
122129123130### ref comparisons across forks
124131125125-Great, so we now understand the anatomy of a PR and how comparing
126126-branches (or more generally, refs) works. Astute readers would've
127127-realised that so far, this only works *within* the same repository --
128128-and not across forks, which is another git repository entirely.
132132+We'll admit: we ... skipped some sneaky bits about forks earlier. Here's the
133133+concept: since we already have all the necessary components to compare two local
134134+refs, why not simply "localize" the remote ref?
135135+136136+In simpler terms, we instruct Git to fetch the target branch from the original
137137+repository and store it in your fork under a special name. This approach allows
138138+us to compare your changes against the most current version of the branch you're
139139+trying to contribute to, all while remaining within your fork.
129140130130-We'll admit: we ... omitted some sneaky bits about forks earlier. The
131131-idea is simple: we already have all the pieces needed to compare two
132132-local refs, so why not just "localize" the remote ref?
141141+<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
142142+ <img class="h-auto max-w-full" src="/static/img/hidden-ref.png">
143143+ <figcaption class="text-center">Hidden tracking ref.</figcaption>
144144+</figure>
133145134134-That's where our hidden tracking refs come in. When you create a pull
135135-request from a fork, we create a refspec that tracks the remote branch,
136136-which we then use to produce a diff. A refspec is a rule that tells Git
137137-how to map references between a remote and your local repository during
138138-fetch or push.
146146+We call this a "hidden tracking ref." When you create a pull request from a
147147+fork, we establish a refspec that tracks the remote branch, which we then use to
148148+generate a diff. A refspec is essentially a rule that tells Git how to map
149149+references between a remote and your local repository during fetch or push
150150+operations.
139151140140-Let's say your fork has a feature branch called `feature-1`, and you're
141141-making a pull request into the `main` branch of the original repository.
142142-We fetch the remote `main` into a local hidden ref using a refspec like
143143-this:
152152+For example, if your fork has a feature branch called `feature-1`, and you want
153153+to make a pull request to the `main` branch of the original repository, we fetch
154154+the remote `main` into a local hidden ref using a refspec like this:
144155145156```
146157+refs/heads/main:refs/hidden/feature-1/main
147158```
148159149149-And since we already have a remote (`origin`, by default) towards the
150150-original repo (we just cloned it, rememeber?), we're able to `fetch`
151151-this refspec and bring the remote `main` to our local hidden ref. Each
152152-PR gets its own little hidden ref and hence the
153153-`refs/hidden/:localRef/:remoteRef` format. We keep this ref up to date
154154-whenever you push new commits to your feature branch, ensuring that the
155155-comparison -- and any potential merge conflicts -- are always based on
156156-the latest target branch state.
157157-158158-159159-<figure class="max-w-[550px] m-auto flex flex-col items-center justify-center">
160160- <img class="h-auto max-w-full" src="/static/img/hidden-ref.png">
161161- <figcaption class="text-center">Hidden tracking ref.</figcaption>
162162-</figure>
163163-164164-160160+Since we already have a remote connection (`origin`, by default) to the original
161161+repository (remember, we cloned it earlier), we can use `fetch` with this
162162+refspec to bring the remote `main` branch into our local hidden ref. Each pull
163163+request gets its own hidden ref, hence the `refs/hidden/:localRef/:remoteRef`
164164+format. We keep this ref updated whenever you push new commits to your feature
165165+branch, ensuring that comparisons -- and any potential merge conflicts -- are always
166166+based on the latest state of the target branch.