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

more

anirudh.fi 87e7fade 0d5ff41c

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