engineering blog at https://blog.tangled.sh

more

anirudh.fi 87e7fade 0d5ff41c

verified
+58 -56
+58 -56
pages/blog/pulls.md
··· 15 15 draft: true 16 16 --- 17 17 18 - 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] 18 + We've been having great fun building pull requests. It's a feature we sort of 19 + take for granted 26 20 27 21 We figured it would be fun to write about the engineering that went into 28 22 building this, especially because Tangled is federated and Git repos ··· 36 30 Creating a PR in Tangled starts with heading to `/pulls/new` in your 37 31 target repository. Once there, you're presented with three options: 38 32 39 - - paste a patch in the UI 40 - - compare two local branches (you'll see this only if you're a 33 + - Paste a patch 34 + - Compare two local branches (you'll see this only if you're a 41 35 collaborator on the repo) 42 - - compare across forks 36 + - Compare across forks 43 37 44 38 Whatever you choose, at the core of every PR is the patch. You either 45 39 supply it and make everyone's lives easier, or we generate it ourselves ··· 47 41 cool actually). We'll skip explaining the part where you click around on 48 42 the UI to create a new PR -- instead, let's talk about what comes after. 49 43 50 - 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. 44 + 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. 53 47 54 48 <figure class="max-w-[450px] m-auto flex flex-col items-center justify-center"> 55 49 <img class="h-auto max-w-full" src="/static/img/patch-pr-main.png"> 56 50 <figcaption class="text-center">A new pull request with a couple 57 - rounds of reviews.</figcaption> 51 + rounds of reviews. Thanks Jay!</figcaption> 58 52 </figure> 59 53 60 54 Rounds are a far superior to standard branch-based ··· 72 66 - It is possible to "interdiff" and observe changes made 73 67 across submissions (this is coming very soon to Tangled!) 74 68 75 - 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. 69 + 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. 78 72 79 73 ## fine, we'll make a patch ourselves 80 74 75 + Remember our patch from earlier? Yeah, let's get into how comparing branches works. 81 76 77 + [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 82 82 83 83 84 84 <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> 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 87 </figure> 88 88 89 89 90 - ## what's in a fork? 90 + [!!!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? 91 99 92 100 Forks are just "clones" of another repository. They aren't your typical 93 101 clones from `git clone` however, since we're operating on top of [bare ··· 116 124 117 125 [repo-record]: https://pdsls.dev/at://did:plc:hwevmowznbiukdf6uk5dwrrq/sh.tangled.repo/3lmrm7gu5dh22 118 126 119 - 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? 127 + 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. 122 129 123 130 ### ref comparisons across forks 124 131 125 - 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. 132 + 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. 129 140 130 - 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? 141 + <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> 133 145 134 - 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. 146 + 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. 139 151 140 - 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: 152 + 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: 144 155 145 156 ``` 146 157 +refs/heads/main:refs/hidden/feature-1/main 147 158 ``` 148 159 149 - 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 - 160 + 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.
static/img/merge-base.png

This is a binary file and will not be displayed.