[HN Gopher] In Praise of Stacked PRs ___________________________________________________________________ In Praise of Stacked PRs Author : kiyanwang Score : 151 points Date : 2022-07-24 16:12 UTC (6 hours ago) (HTM) web link (benjamincongdon.me) (TXT) w3m dump (benjamincongdon.me) | somehnacct3757 wrote: | I like to figure out what all my PRs will be during the planning | phase, optimizing for reviewer cognitive load and incremental | development of shippable features. | | I never need to stack PRs cuz I can work on the next one while | the first one is under review and rebase once it's merged. I can | see if the review phase is long at your company that this | wouldn't work. But I prefer it if possible. | | One thing I hate about stacked PR delivery is ppl go dark for a | month building this whole new world and if you have architecture | concerns in the root PR they will resist them because it means | rebasing and changing all the downstream PRs as well. Bad | incentives all around. | arxanas wrote: | You might be interested in https://github.com/gitext-rs/git- | stack, which perfectly implements your workflow where you only | put up one PR but continue to work locally on the next commits. | | > ppl go dark for a month building this whole new world | | I think this isn't specific to stacking PRs. You can put 100 | commits in a PR and submit it at once, or you can make 100 PRs | and submit them all at once, and have the same problems either | way. Ideally, you put up your first few commits or PRs early so | that they can get reviewed. | TazeTSchnitzel wrote: | Stacked reviews is a very natural pattern if you're using a | system like Gerrit, where the unit of review is not a whole | branch, but individual commits. Since they are commits, the | reviews can have any kind of relationship that commits can have. | I think it's a great system, including for some other reasons (it | encourages amending and rebasing commits during the review | process, which results in a very clean git history). After using | Gerrit professionally for several years I wonder how I ever lived | with GitHub-style pull requests. | baq wrote: | github pull request review process, UI and the whole experience | is very much the worst thing about github for me. there's | literally one feature that I like (C-g, suggest a one-click | committable change in a comment) and everything else is better | in gerrit. | rsstack wrote: | We switched to using https://graphite.dev/ after yet-another huge | epic that caused a mess of PRs and one PR that touched 100+ files | and included dozens of semi-related changed. It's been a blessing | so far. | zeroonetwothree wrote: | Graphite is amazing! Would definitely recommend everyone try it | at least :) | rco8786 wrote: | Hope you like merge conflicts and rebase hell as people start to | comment and ask for changes | nateroling wrote: | I've played with this idea a bit. In my experience it felt like a | hack to work around the fact that individual PRs took a while to | get merged. | | An alternative solve is to work in a way that allows PRs to be | merged more quickly, ie pairing, mobbing, or prioritizing getting | reviews done asap. | avl999 wrote: | It is more about being unblocked than however long it takes for | the PR to be merged in even if it is really fast. It is not | always possible to pair/mod on a change. | | Getting folks to quickly review PRs is difficult as doing so | breaks the flow state of other people and results in constant | thrashing and context switching between the work they are doing | are reviewing PRs. | | Even if the team is committed to quickly reviewing PRs, you are | always going to have times when a bunch of people are in a | meeting, while a couple are at lunch and a couple are knee deep | in another issue and no one can look at your PRs for hours and | you need to keep yourself unblocked. | tennis_80 wrote: | Yeah I agree. If you can merge things into a central branch | quickly, it's much better. | | In my experience with this sort of process you spend quite a | lot of time managing your different branches, especially once | you start getting feedback and requests for changes. Then | keeping everything in sync. Git helps make this quicker but | it's still effort & cognitive load. | knoebber wrote: | I like to do this to address PR feedback, mostly because we use | bitbucket, and it's UI for reviewing individual commits sucks. | agentultra wrote: | It depends on the project being worked on. If the main branch | changes often enough that you need to merge master before you | merge the branch you'll spend a lot of time propagating changes. | | And then there's the problem of _large codebases_. Without a | really good cache strategy for builds all of the branch switching | and merging will cause a lot of rebuilds. For some languages and | large projects that can be 20+ minutes for a fresh build on each | switch. That's enough time to get distracted by emails or hacker | news. | | I'm a big fan of small commits, often and breaking down changes | but it does require a large amount of automation and tooling to | support well. | jackblemming wrote: | There's so many articles on trivial things like this and using | pretty syntax and less articles on things that actual matter: | architecture and design. It's a bit disheartening to hear | software engineers argue of if you should put periods in commit | titles or if so and so syntax is more readable. | tunesmith wrote: | How would you align this with Jira stories? Our team tries to | maintain a one-PR-per-story flow. Partly for QA purposes, we | don't want multiple QA cycles per story. | | Of course, we still have giant PRs that touch 50-100 files and | take forever to code review. | | And yet, for those stories in question, they do make it to prod | faster than if they were broken apart into multiple 1-2 point | stories. | | I imagine as always the answer is "invest in better tooling". | More robust automated tests, push-button millisecond-deployments, | etc... | arxanas wrote: | Basically: you don't :) | | I've only ever found this workflow to work if you can attach | multiple commits/code reviews to single higher-level work items | in your project management software. There's simply too much | overhead if you try to correlate project management items one- | to-one with commits/code reviews. | krooj wrote: | I've tried this method of taking a large change and breaking it | up into smaller, more easily digestible PRs, and it didn't work. | Unless you're working with folks that are directly invested in | the change, you'll very quickly discover that people have | memories worse than goldfish. So, it's a lose-lose situation: | can't really do stacked PRs and large PRs will let bugs and other | defects through. | avl999 wrote: | There is a tradeoff... smaller, digestible PRs result in | thorougher and faster reviews but it gives up the "1000 feet | view" of the larger feature as far as the reviewer is | concerned. | | Large PRs preserve the larger "1000 feet view" of what you are | working on but are likely to be slower to get responses on and | most likely less thorough thus a larger chance of things being | missed. | | Almost everyone I've worked with prefers smaller review so I | just accept that trade-off of 1 | culi wrote: | Can't this easily be resolved by just using feature branches? | Make your small PRs into the feature branch but then you still | have the ability to compare the branch to main as a whole and | get that wider context | Sol- wrote: | We have some people in our company that use tools like Graphite | to implement this pattern on top of Github and I don't know if | I'm a big fan. | | Maybe just a matter of developer discipline, but in my experience | people tend to create large stacks of 3+ PRs that then take a | while to resolve. Yeah sure, without these tools the code would | also exist somewhere, but at least you don't have your pull | request list full with PRs that aren't yet ready because the | upstream PRs haven't been approved yet. You anyways have to (or | should) review things stricly serially, so the additional PRs | existing are not super useful either. Maybe as context for the | reviewer to see the future work. | | Also for some reason these tools seem to encourage people to put | unrelated changes in the stack that could be based directly on | master. Probably because they are anyways working on their stack | and integrating some unrelated fix they just did into the current | stack is easier than rebasing/changing your current context. But | that's just a minor pet peeve. | | That said, I would still like a tool that lets me manage stacked | branches just for myself. Not exposing them as Github PRs or so, | but to organize my work into different branches. Executing a | chain of rebases of branch N -> (N-1) can get quite annoying | manually. Probably some arcane git magic to (interactively) | rebase branch N->(N-1)->...1 in one command exists already. | arxanas wrote: | > Probably some arcane git magic to (interactively) rebase | branch | | There is not really a command for that yet, short of adding a | bunch of `exec` steps to your interactive rebase manually. See | https://news.ycombinator.com/item?id=32217204 for an upcoming | command. | | You might enjoy using https://github.com/gitext-rs/git-stack, | which specifically tries to let you manage stacked branches | locally while not exposing tons of PRs to your coworkers. | | git-branchless itself also lets you manage stacked branches in | various ways. For example, you can do `git checkout <branch>`, | `git commit --amend`, and then `git restack` to rebase all the | descendant branches sensibly. You can use it on the local side | of things only and then use Github PRs as normal. | wakeupcall wrote: | Also a big fan of https://gitlab.com/wavexx/git-assembler | (and previously topgit). Works with the basic idea that you | can rebuild branches by combining, merging or rebasing | automatically on top of others. I frequently use this to | build a local branch which is an amalgamation of the main | branch + required patches so that I can work (and later | submit) on a clean branch without being blocked. | doktorhladnjak wrote: | We use GitHub Enterprise where I work now. I do sometimes do | stacked PRs but GHE does not make it easy. The rebasing and merge | conflict resolution can be a headache although git rebase --onto | helps a lot. | | I previously worked somewhere that used Phabricator. Its "stacked | diffs" worked great. I'd use it all the time when working on | complex, multipart changes. | arxanas wrote: | Try out the linked tool git-branchless | (https://github.com/arxanas/git-branchless, I'm the author). It | should help you restore Phabricator-like workflows. In | particular, check out the `git sync`, `git restack`, and `git | move` commands for handling rebasing and conflict resolution. | davvid wrote: | There is active work related to teaching "git rebase" to natively | support stacked branches in the Git core currently being worked | on by Derrick Stolee [1]. | | If you "stack" your changes across multiple inter-dependent | branches it looks like "git rebase" is going to learn how to | update related branches using a new "update-ref" command | (alongside "squash", "fixup", "exec", etc) that gets activated | automatically through a "git rebase --update-refs" command-line | flag and config option. | | (This is from Derrick, not me) | | """ This is a feature I've wanted for quite a while. When working | on the sparse index topic, I created a long RFC that actually | broke into three topics for full review upstream. These topics | were sequential, so any feedback on an earlier one required | updates to the later ones. I would work on the full feature and | use interactive rebase to update the full list of commits. | However, I would need to update the branches pointing to those | sub-topics. | | This series adds a new --update-refs option to 'git rebase' | (along with a rebase.updateRefs config option) that adds 'git | update-ref' commands into the TODO list. This is powered by the | commit decoration machinery. | | """ | | This is under active development (I don't believe the topic has | been merged yet) so it's still open for feedback and refinement | on the git development mailing list. Thanks Derrick! | | [1] https://public- | inbox.org/git/pull.1247.git.1654263472.gitgit... | timhh wrote: | That sounds great! I have partly solved this issue in my | autorebase tool (https://github.com/Timmmm/autorebase) - it | basically rebases every branch, and fixes the commit time so | that stacked branches get preserved even after a rebase just | because the hashes all match properly. | | That obviously doesn't work if you modify or drop any of the | commits, so this option is very welcome! | dcow wrote: | I'm going to be a little crass for a moment: people don't know | how to use their tools! Why are we even talking about "stacked | PRs" and "branchless" workflows?! It's clear the author is | documenting their git learning process and that's great, really. | _But I'm just surprised how pedantic people get about forcing | others to use a tool in a way that caters to their own limited | understanding of it._ Or, even worse, caters to limitations in | the 3rd party UI being used to interface with it (ye ol' git vs | GitHub problem). Learn your tool and then you can worry about the | higher order things that are supported by it. | dcow wrote: | I feel similar about languages and style-guides, but I didn't | want to conflate the two in my previous comment. Unless you are | a royal newb and just learning to write code (which is fine, | everybody has to learn), you're probably writing code in a way | that best expresses your intent or goal given your | understanding of the language. Let people do that! If you know | the language you can handle encountering different styles and | structures. Otherwise you're just forcing your preferred subset | of hoe the language can be used to express things. I just don't | like regression to the mean. | kqr wrote: | This is something I've come to realise as I've matured as a | developer. I just don't care what style you write in, if you | don't use all the syntactic sugar, etc. I care where you draw | your module boundaries, which units depend on which, and if | you've handled edge cases, and so on. That's what's going to | matter in the end. That's where I'll have to spend a lot of | time figuring stuff out. Not syntax. | dcow wrote: | Exactly. I've seen style-perfect lint-free "write once" | spaghetti code that drops edge cases and error conditions | left and right, and I've seen "ugly" but clean code that | needs no introduction and works perfectly to boot. I worry | that auto-formatters (not to discredit their upsides) do | sometimes give people a false sense that they're writing | good code. | seoaeu wrote: | This comment would be more compelling if it gave any hint about | what aspect of the tooling the author didn't understand or what | they should be doing differently. | dcow wrote: | I'm not talking about the author, specifically or criticizing | them directly. I'm lamenting how often I encounter people | putting intense amounts of effort into arguing about how git | _should_ be used. My hypothesis is that if people understood | their tools better before getting all evangelical about | forcing their entire eng team to work in their style, others | wouldn 't have to spend so much time trying to convince them | that other styles are exist and are valid. | | Compare with a construction site: there are obvious uses for | tools and there are less obvious uses and I haven't been on a | single one where tools are only used specifically in one way | for the entirety of the project. They're used dynamically by | different people with different experiences in order to | complete the project. Nobody forces other workers to use a | specific grip when holding their hammer... | johnfn wrote: | I'm not understanding how stacking PRs is inconsistent with | knowing git well. | dcow wrote: | That's not what I'm saying at all. My comment is a meta | comment about why we even need to write grand defenses of | these practices in the first place. I've been "stacking | PRs" forever... when it makes sense to do so. There's no | golden git usage pattern. I've seen the industry all the | rave about gitflow. And then it wasn't cool anymore with | tags being the preference. Now it's cool to just forgo | branch names entirely? I've watched teams fight over | whether every PR should be exactly one commit because | they don't realize that you don't always have to squash | merge if you want two unrelated changes pulled in at the | same time--just keep the commits clean and revert doesn't | care. My point is that if you know how to use the tool | none of this really matters and all seems quite | distracting. I no problem with people sharing what works | for them, that's great (as is this article, abstractly). | morelisp wrote: | I can't be certain what dcow is referring to but there | are a few things that point to confusion, or maybe an | overambitious attempt at simplification. | | For example, _Stacking PRs keeps the author unblocked. | Authors don't need to wait on a particular change to be | merged before starting to build something on top of those | changes._ | | This will fundamentally be up to the author's git skill | whether or not they are presenting the PRs to reviewers / | mergers as stacked. If they're skilled git users there's | little to no cost presenting them one at a time and | keeping the not-yet-PRd branches fresh. If they're not | skilled git users, they have no hope of managing multiple | PRs effectively only be virtue of presenting them all at | once. | | Or: _Since stacking PRs allows you to create a DAG of | dependent changes, this natually allows you to manage | code changes that need to be submitted in a particular | order._ | | Assuming this is in a single repository, a fast-forward- | only commit policy alone ensures this. | | Or: _stacked PRs use branches, and can have multiple | commits in a single atomic change; stacked commits use a | single commit as the unit of atomic change._ | | Stacked PRs usually use branches, but stacked commits | also still use at least one branch and could have more. | In both the commit is the unit of atomic change, because | that's what a commit is. | | I'll also add I find the entire language around | "branchless" workflows in git confusing, not just from | this author. There is no such thing; considering one | special branch as "not a branch" or your local and remote | and someone else's remote as the "same branch" just | because they have the same name is a holdover from | older/other VC tools. We don't do any new git users a | pedagogical or practical favor by clinging to that view. | arxanas wrote: | git-branchless author here. By "branchless", I mean | literally using detached HEAD as the primary state of | development. If you're using tools like Gerrit or | Phabricator, you never have to explicitly make a branch | to get your code merged. If using GitHub, then branches | are unavoidable, but it can be nice to do branchless | development as part of rapid prototyping (see | https://github.com/arxanas/git- | branchless/wiki/Workflow:-div...). | | Another term you could use is "anonymous branching". This | is not technically accurate in the above workflows, but | it captures the essence pretty well in Git, more so than | "branchless". | morelisp wrote: | But when you call it "anonymous branching" you lay bare | that the only advantage is that you don't need to name | your work "branch", and meanwhile you have a workflow | that's needlessly incompatible with most other git | tooling. | | In particular, since this is the one I see usually called | out as a benefit of branchless: | | _Stock Git does not have good ways of rebasing a | sequence of branches._ | | A sequence of branches can be rebased by rebasing (or | otherwise rewriting) the longest one (the only one you'll | need locally) then pushing the individual commits in the | current branch to the remote under any relevant branch | names. This doesn't take zero time, but with good git UIs | it will take less time than remembering `git move`, and | it's not especially hard to do with the stock CLI either. | arxanas wrote: | > But when you call it "anonymous branching" you lay bare | that the only advantage is that you don't need to name | your work branch | | Sure, I'm only responding to what you were saying about | "There is no such thing; considering one special branch | as 'not a branch'". There is such a thing in that there | is no branch involved in the detached HEAD state. It's | not some kind of Git misunderstanding. I think you might | be referring to trunk-based development and always | building off of the remote main branch instead of having | your own local copy, which is unrelated to being | "branchless", for the reasons you stated. | | For many people (particularly those on Github!), a | branchless workflow won't help, so you're free to not use | it. In my opinion, it's a workflow that is better | compatible than stock Git with code review tools like | Gerrit and Phabricator. | | I personally argue that anonymous branching is useful | even in some branch-based workflows. Mainly, if Git | branches are so lightweight to use, why do we also use | the command `git stash`, instead of just always creating | a new branch for our temporary work? One benefit of | anonymous branching is that it consolidates these | workflows in a convenient way. Some people don't stash | changes or feel that branching in those cases is | heavyweight, so anonymous branching doesn't help them at | all. | | > then pushing the individual commits in the current | branch to the remote under any relevant branch names | | If I'm understanding correctly, every time you rebase the | longest branch, for each commit in the branch, you would | manually run e.g. `git push <commit> origin:my-branch- | name`? That seems like it would take a lot of time to me. | Is the tacit assumption here that you don't have a lot of | commits in your branch, so this doesn't take a lot of | time? | morelisp wrote: | > There is such a thing in that there is no branch | involved in the detached HEAD state. | | But at the very least there's still an existing remote | branch, which is the ultimate merge target, for example - | perhaps even multiple. Since we're talking about | coordination, there's also the actual state at the remote | vs. my view of the remote vs. my teammates' views of the | remote. But we don't think about this too much, because | we can synchronize easily as long as the remote branch | has a name. Taking the name off the branch makes it more | difficult to do anything with someone else's work other | than merge it, e.g. pass a changeset back and forth or | hand over a half-complete task. | | > why do we also use the command `git stash`, instead of | just always creating a new branch for our temporary work? | | I have no idea actually, because I don't. I haven't run | git stash manually since I learned about autostash, and | even before that it wasn't for temporary work but for | changes I decided I wanted somewhere else only after | writing them. Temporary work mostly does get a branch | (usually as a new commit on top of my current local | branch). | | > If I'm understanding correctly, every time you rebase | the longest branch, for each commit in the branch, you | would manually run e.g. `git push <commit> origin:my- | branch-name`? | | Close, except I'd scroll down the list of commits and | type `P o RET TAB branch-name` (or something to that | effect, it'd be slightly different if I have several | remotes). This would take perhaps ~0.5 seconds per branch | and not require me to context switch to a terminal. | | It does take longer for people using less powerful | clients, but virtually all do provide some way to do it | even it means a few right-clicks on a menu and clicking | some "OK" buttons, and there's value in everyone using | analogous operations. And the people using those clients | usually can't reliably recover from a large class of "git | broke" mistakes, assistance from git-branchless or not, | so handing them a CLI and a prayer is out of the | question. And even the "long version" is pretty | negligible (like, maybe 10 seconds per branch?) compared | to everything else you should do to make your changeset | approachable for review. | arxanas wrote: | Which Git client do you use, and also, how do you | remember all the remote branch names? | | > And even the "long version" is pretty negligible (like, | maybe 10 seconds per branch?) | | I notice that mainly the differences in opinion with | regards to workflow is disagreement about "how long is | too long" for various operations :) | morelisp wrote: | Magit, and the remote branch names are visible in the log | view and easy to enter via tab completion. (We're still | talking about stacked PRs right? Median stacked at any | given time is probably 2 and p90 is maybe 4? Max I've | ever seen is ~10 and that was quite a fucked up situation | for plenty of other reasons.) | | 10 seconds would certainly be too long for me. It is | obviously not too long for them, or they'd learn some | keyboard shortcuts to get the easy 5 out of the way to | begin with. But regardless, it's all pretty much dwarfed | by things that need actual brainpower like re-reading my | commit messages for grammatical errors / broken links / | etc. | arxanas wrote: | I see, thanks for the information. I often stack 10+ | commits, so I don't think your workflow would be | reasonable for me. (For example, here, I have 11 finished | commits and 3 in progress: | https://github.com/arxanas/git-branchless/pull/451 -- but | I don't actually use stacked PRs on Github, particularly | if no one is reviewing my code. Most of my stacking is at | work with Phabricator anyways, which handles this | better.) | morelisp wrote: | It's only necessary to push ten branches, one per commit, | if you intend ten separate, let's say, "review events" | though. For that example we would have fewer than that | nor would we want that many. I do stack 10+ commits | fairly regularly but that may be only 1-2 reviews. | | (I'm not familiar with Phabricator, only Gerrit and | GH/GL, as well as some more manual Workflows.) | arxanas wrote: | Right, in this case, I would prefer 10 separate review | events. Other than for code review purposes themselves, I | would want CI to run on each of these commits | individually, rather than only on the result at the end. | djur wrote: | This isn't "how to use a hammer", though, it's more like | "how to evaluate the completion of work", which is | definitely something working teams have to agree on. git | itself is almost irrelevant to the discussion, other than | its native feature set having some influence on the | options. | morelisp wrote: | If this was just about team review workflow I wouldn't | expect to find "easier to rollback" and "don't need to | wait on a particular change to be merged" to be on the | list of upsides, as these are properties of the | repository structure and not the review workflow. | surfmike wrote: | Graphite (https://graphite.dev/) has been a good tool at our | startup to manage stacked PRs, I recommend checking them out. | jasonhansel wrote: | Why not just break up your change into small components, then | merge each one into master separately, hiding the change behind a | feature flag until the whole thing is done? | travisb wrote: | Your suggestion comes after the changes are merged. That is, | you wouldn't normally merge anything to master without having | it reviewed. | | Stacked PRs is _how_ you can break up your changes into small | components to merge more quickly and block development less. | | With stacked PRs the changes are broken into smaller pieces | because a later PR can depend on an earlier PR. This means it | can be developed while earlier PRs are still under review. It | also means each review is smaller and therefore likely to | complete more quickly. | | Stacked PRs can also work like patch series in the Linux Kernel | development where a large change is broken into smaller | independent changes done in the logical order, even if their | order of discovery was probably reverse. For example, if you | discover you need a refactor or bug fix while halfway through | developing a feature. In that case you simply insert a PR | earlier in the stack/graph which contains just that isolated | fix. | | In your feature flag example, a common patten would be to have | a dozen or so stacked PRs. The early ones do necessary | refactors and bug fixes. The middle few add the feature flag | and code. The last make the feature flag the default and delete | the now obsolete !feature path. Then the prereqequites (which | you didn't discover until half-way through) can be reviewed and | merged quickly. The meat of the feature is broken up into | easily digestible pieces for quick review, but reviewers can | get a sense of the entire feature by considering the PR series | as a whole; this is especially useful where one PR adds some | infrastructure that a later PR uses but both PRs together would | be too large to effectively review. As PRs are ready to merge, | they can. Often the last couple of PRs which make the feature | the default and delete the obsolete code do not merge for quite | some time, but they were written when everything was still | fresh in the developers head. | arxanas wrote: | I am the author of the linked tool git-branchless. Happy to | answer any questions about stacked PR workflows here or on GitHub | discussions https://github.com/arxanas/git-branchless/discussions | or Discord https://discord.gg/caYQBJ82A4. | ridiculous_fish wrote: | Plugging my own tool: if you like to cultivate a stack of | commits, you'll know how awkward git makes it to edit previous | commits. With git-prev-next you can run 'git prev 3' and then | 'git commit --amend'. | | https://github.com/ridiculousfish/git-prev-next | maxekman wrote: | `git rebase -i origin/main` (or HEAD~N or any other base) with | the e/edit action on selected commit will do the same with only | built in functionality. | ridiculous_fish wrote: | Yep, and git-prev-next is built on interactive rebase. It's | just a lot faster to run `git prev`, compared to `git rebase | -i HEAD^^` and then muck around in a text editor. | arxanas wrote: | The mentioned tool `git-branchless` (I am the author) also | supports `git prev 3` followed by `git commit --amend`. See | https://github.com/arxanas/git-branchless/wiki/Command:-git-... | fallingknife wrote: | This just shows that people will go to any length to | procrastinate PR reviews. The truth is that to be an effective | team, reviews need to be highest priority because they are | blockers. There is just no way around it. | macintux wrote: | Any categorical assertion like that feels wrong. Not all | projects, all teams, all problems are the same. | loloquwowndueo wrote: | Bzr has a pipelines plug-in which does basically this. Branches | can be stacked on top of each other forming a "pipeline", and | propagating changes from one branch to the dependent / subsequent | ones is achieved with one command, "bzr pump". | | Bzr has no concept of rebasing, so what you get is a simple | merge, but with very little work on your part. | is0tope wrote: | I've usually kept a rule that you should avoid stacking, and if | you must only one level deep. The fact that you have to stack in | the first place typically suggests that PRs aren't being merged | fast enough. Stacking in my personal experience usually leads to | merge conflict hell as changes and PR suggestions get merged | underneath you. | ignormies wrote: | Something I often use stacked diffs for is deprecation -> | removal flows. | | 1. Deprecate old feature + add opt-in support for replacement | 2. Make replacement default with opt-out for old pattern 3. | Completely remove old feature and the opt-out functionality | | I can write the entire stack of diffs upfront, have them | individually reviewed but still linked, and ensure they're | merged in the correct order. | | The bottleneck for merging isn't in the review process, but in | the deprecation. It wouldn't make sense to land all three of | these changes as fast as review/merge would allow; that would | skip the deprecation period. | wpietri wrote: | Ooh, good point. I'm suspicious of stacked diffs generally, | but this seems like a good example where we truly don't | expect to learn anything after the initial deploy. | kqr wrote: | But is it really effective use of your time to make changes | to the code that you know won't be relevant for weeks or | months? You could spend the same time on other changes that | would start earning you money tomorrow, instead. | tablespoon wrote: | > But is it really effective use of your time to make | changes to the code that you know won't be relevant for | weeks or months? | | It totally is, because it doesn't wastefully discard the | mental context needed to make the follow on changes. Task | switching unnecessarily incurs significant costs. | | > You could spend the same time on other changes that would | start earning you money tomorrow, instead. | | Maybe in some bare-bones startup context that can't afford | to think beyond next week, but most organizations aren't | like that. | ignormies wrote: | Having the change implemented from start-to-finish | demonstrates a finished and thorough design. It also allows | review to happen with the complete change at the forefront | of the reviewers' minds. | | Kicking the completion of the implementation of a change | you've started landing to an unspecified future date | indicates poor engineering rigor imo. It's just begging for | the change to perpetually be half-migrated and never | finished. | majormajor wrote: | Sometimes? | | Consider also the stakeholder who gets annoyed whenever the | dev team wants to work on something that would take longer | than a week to turn around, and limits the things they'll | ask for to those estimated at a week. So bigger things can | never get done at all, and you'll just be looking for a | local maxima instead of having the chance to make more | significant changes. | | Sometimes it's worth it to prep and clean up as you go. | Knowing when it's worth it and when it isn't is one thing | that makes some devs more valuable long-term than others. | chrisseaton wrote: | > The fact that you have to stack in the first place typically | suggests that PRs aren't being merged fast enough. | | Unless PRs are merged instantly, I'm always going to be waiting | after one PR is opened, before I can work on the next, unless I | stack, aren't I? | | Is your definition of 'fast enough' instantly? If not, how does | this work? | delecti wrote: | If your second PR is ready before the first PR is merged, | then two of the likliest outcomes are that either PR reviews | are taking too long, or the second PR is small enough that it | could have just been part of the first. Alternatively, the | review is taking a long time because the first PR was | bad/controversial, in which case the assumptions of the | second PR might need to be reevaluated anyway. | dairylee wrote: | Neither of those cases need to be true for a second PR to | be ready before the first has been merged. | | For example you do your first PR, mark it ready for review. | While doing it you notice there's some refactoring you | could do to some tangentially related code. It's very | conceivable that the second refactoring PR could be ready | pretty quickly. | wowokay wrote: | No? You can create a new branch and start working on the next | thing. Why would you be waiting on your PR to complete unless | you didn't split your work correctly. | chrisseaton wrote: | What if the next thing depends on the previous thing? | fuzzy2 wrote: | Then your new branch starts at the tip of the previous | one. | | You can (/will have to) rebase later. | chrisseaton wrote: | I thought that was what stacked PRs are - maybe not? | majormajor wrote: | Two top-level scenarios here: | | * you're working on the same part of the code | | * you aren't working on the same part of the code | | The second scenario is common but also trivial here since you | can just have parallel branches going, so I'm gonna assume | more the first - working on something that's building on top | of what you just put up for review. | | Let's say the review is done in 2 hours. If you're already | done with the followup, IMO you may be erring too far on the | side of "small PRs." If you aren't, you just rebase on top of | whatever changes had to be made, if any, to the first one, | once it lands on the primary branch. | | If, on the other hand, the review isn't done for 2 days... | then that's a PR turnaround time problem for sure. | | But I strongly disagree with the people saying "multiple | dependent PRs suggests the work wasn't split up properly" - | there's nothing worse than a mega-PR of thousands of lines | for the sake of doing a "single feature" all in one shot vs | having to possibly pause and rebase periodically after | review. It's _even more painful_ when this mega-PR requires | fundamental changes that could 've been caught earlier, but | now will take longer to adjust, and then will stay open for a | while and likely result in merge conflicts as a result. | californical wrote: | You can branch off of a PR, but someone should review and | merge your first PR before your second is ready to be up in a | PR again. | | Also, trying to make units of work so that they don't need to | overlap like that can be useful too | nightpool wrote: | This is why I think it's really really important that all PR | reviews be _synchronous_ , so that there's never any time | spent twiddling your thumbs or context switching onto another | change. Also it just makes it much easier to review a PR when | you can sit down and actually talk about it in real time with | the author, rather than having the ping messages back and | forth interminably until you reach an agreement | wizofaus wrote: | In one of my first jobs, code reviews were done exactly | like this, with the the reviewer (my boss) and I sitting | together at one computer going through the changes. It | definitely has benefits but it's still important to ensure | recommendations/concerns etc. get written down and doesn't | necessarily help if there's a need to go away and make | significant changes based on the outcomes of discussions. | But while the back & forth discussion that often occurs | during review can benefit from being synchronous, it might | still be some time before your coworker has available time | to participate in such a session, so it's still likely | you'll need something else to work on in the mean time. | nightpool wrote: | > and doesn't necessarily help if there's a need to go | away and make significant changes based on the outcomes | of discussions. | | See, I disagree, because this is absolutely the place | where it helps the most--you can now go away and keep | working on the same task without having to context switch | to anything else or remember where you were or what you | were working on. So you're never in a state where you're | blocked and can't work on your ticket, and you don't have | anything else to do or have to pick up another ticket and | start learning about a whole completely separate problem. | (And yes, definitely everything still needs to be written | down, it's important to walk away knowing which changes | you need to make, and why!) | | > it might still be some time before your coworker has | available time to participate in such a session, so it's | still likely you'll need something else to work on in the | mean time. | | In teams I've worked on, the expectation is that an | engineers highest priority is always unblocking another | engineer, so this very rarely happened. Unless they had | an interview to go to or some kind of meeting--and in | that case, you could always just ping somebody else. | | Obviously it's a style of work that relies really heavily | on everyone sharing the same timezone and work hours, but | it works really well to eliminate time lost to context | switching and minimize the amount of time engineers spend | blocked waiting on someone else. | wizofaus wrote: | But if you're expecting another dev to always be | available to help you with a review, then _they 're_ the | ones having to "context-switch", interrupting their own | work. The reality is context-switching is something that | comes with the territory if you're working as part of a | team developing software. Which isn't to say there aren't | opportunities to minimise the disruption it causes, but | the idea that you can more or less eliminate it seems | like wishful thinking. Perhaps there's a case for | minimising it for more junior devs that aren't as capable | of dealing with it, though it's equally possible younger | brains are better at it! | nightpool wrote: | I think maybe we're using different definitions of the | term "context-switch". Certainly it's an _interruption_ , | but I don't really think that sitting down with another | engineer to do a focused code review where they've | already written out a PR description and thought hard | about the problem is comparable to starting a brand new | branch or picking it up after a while away and trying to | juggle 2, 3, or 4 in-progress tickets. | wpietri wrote: | One way this can work is pair programming. Especially if you | also practice frequent pair rotation, you can get plenty of | eyeballs on code in a timely fashion. That's my preference. | | Another way is that you next work on something different | enough that it doesn't need to stack. E.g., reviewing pull | requests. | perrygeo wrote: | By pinging people on slack and interrupting them for a review | asap? Or context switching to an unrelated part of the code | in parallel while you wait? Or reducing the frequency of | reviews and make a mega-PR every couple weeks? | | I've seen no solutions, only tradeoffs but I'm curious if | anyone has a tried and true way to avoid this traffic jam | scenario. | wowokay wrote: | Yes, complete your story in a single PR, if the next story | is related and requires your changes your work wasn't split | up properly, plus in that scenario there is a good chance | other devs have to many dependencies on other devs work | which is a recipe for disaster! | BerislavLopac wrote: | My personal rule of thumb is to rebase the working branch as | soon as the main has been updated; or at least merge main if | the changes are too complex. | zmj wrote: | I stack PRs when I'm working on a piece of new code, and in the | process discover one or more refactors that simplify the diff | for the new code. I wouldn't start at the refactors and then | wait to proceed - there's a chance they are dead ends until I | know exactly what the new code needs. | arxanas wrote: | If you work at asynchronous/remote work company, i.e. your | coworkers are in different timezones and can't review | immediately, what else are you going to do? Put out exactly one | code review per day until your feature is fully merged? Some | things like refactoring changes can be reviewed and committed | individually, but lots of feature work is fundamentally | dependent on the previous work. | | Stacking PRs is like pipelining for CPUs. It's efficient under | the hypothesis that there aren't too many invalidations/stalls. | The linked tooling `git-branchless` (I'm the author) is aimed | at reducing the impact of such an invalidation by significantly | improving the conflict resolution workflows. | isoos wrote: | > what else are you going to do? | | Depends on the team and the product. My personal approach is | to have 2-3 larger things to work on, so while I wait for | reviews on one, I can switch and work on the other. This | usually means minimum 1-2 weeks of planned work, sometimes | even more, without being blocked on reviews. If everything is | blocked, then it is time for some code health cleanup, | refactoring and fixing those TODOs that are just lingering | around, and also nudging the reviewers... | dan-robertson wrote: | One advantage of 'stacking' is breaking up review into more | logical units, eg | | 1. Introduce new test exhibiting bug | | 2. Introduce bug fix and update the test | | If 1 and 2 are reviewed together you have less evidence that | the test actually shows the bug being fixed. | dtech wrote: | You can still have them in 2 commits, and configure your CI | to build both of them, and the first 1 should fail. | | We actually have a rule that there must be 1 commit just | introducing a test that fails on CI for bugfix PRs. | chrisweekly wrote: | That's interesting, explicitly to require that bugs be | reproduced in CI. It makes sense in theory, but in praxis | (IME) CI systems tend to be overtaxed / underprovisioned - | meaning this extra burden might be questionable. /$.02 | nemetroid wrote: | The same burden is present when splitting the two commits | into two PRs. | YZF wrote: | Ideally your CI workflow prevents merging something that | breaks the tests. Also now if the first review merges but the | other doesn't for some reason you've broken everyone else | which is bad. | | EDIT: at least in rebase workflows which is what I'm used to. | I guess in merge workflows this works. | cornel_io wrote: | But once you merge 1, your test suite is broken, and | many/most companies wouldn't allow that. | dan-robertson wrote: | Yeah there's two solutions: | | 1. Merge #2 into #1 then merge the result, but this can | obscure your history | | 2. Don't make the test fail. Eg expect the incorrect | behaviour and leave a comment explaining why it is | incorrect and what the correct thing should be. | mrkeen wrote: | > The fact that you have to stack in the first place typically | suggests that PRs aren't being merged fast enough | | Yes. Whenever you inspect a proposed solution, you should | hopefully find the problem that it solves. | wpietri wrote: | For sure. One of the things I learned from the Lean folks was | to look for inventory; it's one of the 7 Wastes. [1] In | physical manufacturing, it's pretty obvious, because it's | physical stuff sitting around on the journey to becoming | actually useful. | | With software it can be harder to notice because you don't have | to make room for it. But in essence it's the same deal; it's | anything we have paid to create that isn't yet delivering value | to the people we serve. Plans, design docs, and any unshipped | code. | | There are a lot of reasons to avoid inventory, but a big one is | that until something is in use, we haven't closed a feedback | loop. Software inventory embodies untested hypotheses. E.g., a | product manager thinks users will use X. A designer thinks Y | will improve an interface for new users. A developer thinks Z | will make for cleaner, faster code. | | Both large pull requests and stacked pull requests increase | inventory. In the case of incorrect hypotheses, they also | increase rework. I could believe that for a well-performing | team stacked PRs are better than equally-sized single big PRs, | in that they could reduce inventory and cycle time. But like | you, I think I'd rather just go for frequent, unstacked, small | PRs. | | [1] e.g. https://kanbanize.com/lean-management/value- | waste/7-wastes-o... | vlovich123 wrote: | I have stacked diffs sometimes when the rework is large. I | want to make sure that I know the full story sounds the | change I'm making because I'm forced to think about that | upfront. What refactoring was needed? Was it actually needed? | What new path do I carve out in the code or how do features | interplay? Broken tests with good coverage tell me if I made | a foundational mistake. Even if I decide to throw away the | work because it was a dead end (rare) the team will have | learned something by me explaining what didn't work out. More | often, I'll need to go back and clean up. But I save | significant reviewer time by doing that before putting up | random prs one at a time that are not well understood. With | the exception of very simple work, stacked reviews generally | save significant time. You get reviews of non objectionable | prs. Coworkers can see a bigger picture if that's helpful to | understand the context of the change that's still coming into | shape. It actually reduces merge conflicts because, for | example, you can enable a refactor that everyone agrees needs | to be done and land that. Then your conflict space is | smaller. | | Small prs don't need it of course but complex features | benefit from shaking out things earlier. Commit more than 100 | lines are really hard to review (lots of anecdotal and | empirical research). If you're not reviewing small commit by | small commit, the reviews are easily missing things. A single | PR that's 800 lines adds review time to go commit by commit. | If you can merge the non objectionable stuff, the reviewee | gets to feel a some of forward progress and fewer merge | conflicts (eg someone lands a refactor before some simple | change of yours vs your simple change handed before and you | made it the person refactoring their problem where it | belongs) | ramraj07 wrote: | It's unavoidable sometimes. I get inspiration and time together | rarely, I can't wait for small chunks of code to be merged | before I continue. A lot of times it's an extremely Productive | Sunday afternoon and I have 2500 new lines of code that builds | a full new prototype. What am I to do? | pizza234 wrote: | I understand that (experienced the same "problem" today), but | writing "2500 new lines of code" on a Sunday afternoon is | (hopefully) not representative of regular workplace | conditions. | zeroonetwothree wrote: | Some people enjoy their work. I think it's fine as long as | it's a choice. | NateEag wrote: | It may be fine. | | Keep in mind, though, that humans are not perfect and | some choices are unwise. | sodapopcan wrote: | Why would a prototype need a code review? | computronus wrote: | First, think about how difficult, and time-consuming, it will | be for others to digest and review 2500 new lines of code | that sprung from someone else's mind. So you will end up | waiting anyway, for even a small part of your work to be | merged. | | The work of breaking up a big, inspired chunk of work into | small pieces helps you learn more about it, and the | perspective can reveal improvements that weren't obvious in | the initial effort. You might notice those yourself, or | reviewers may. The final outcome will end up overall better | for it, so spending that time is worthwhile. | Supermancho wrote: | > First, think about how difficult, and time-consuming, it | will be for others to digest and review 2500 new lines of | code that sprung from someone else's mind. | | There's a tradeoff to be made. Have a feature sooner or | later. Review now quickly and more carefully later, or | review carefully now. Part of what development teams do, is | risk assessment. | | Put a feature flag on it, do a demo of the branch. If it | looks good, do a quick once-over to see if it's interactive | with any limited resources, merge it in, make a ticket for | a re-review later. | dreamdeath wrote: | > First, think about how difficult, and time-consuming, | it will be for others to digest and review 2500 new lines | of code that sprung from someone else's mind. | | I haven't ever worked at big corp so maybe this kind of | thinking is actually valuable there. But in most startups | in my experience this mindset is wrong. You literally | won't have a job tomorrow (because your company will | fold) if you don't ship value-generating product | yesterday. But you're going to worry about how | _inconvenient_ it will be for some other developer to | review your PR? | computronus wrote: | Well, I'm proceeding from the assumption that thoughtful | review, which takes time, is desirable. If the situation | is really that dire, then it's even more important that | you ship product that works. Code review happens to be | one of the, if not the most, effective ways to catch bugs | and prevent disasters. It's a good idea to make the | review process work for you, even and especially when the | pressure is on. | | It's not about humongous reviews being "inconvenient". A | drop of thousands of lines of new code takes a long time | to review thoroughly, whether the company is at risk of | folding tomorrow or a stodgy enterprise with decades | ahead of it. If you have to constrain review time - or | ditch reviews altogether, why not? - you can, but there | are consequences regardless. | | I haven't worked in early startups, but I haven't only | worked at large corporations either. I hope that most of | us, most of the time, aren't less than a business day | away from unemployment, and so there's usually time for | code reviews. (If not, there's a lot of useless material | about it!) | | Without sarcasm, and potentially getting off-topic, I | would like to hear stories about how a startup survived | impending doom with heroic, fast shipping of product that | set aside a lot of time-consuming processes. What were | the most crucial steps to keep? How was the technical | debt repaid? | [deleted] | duped wrote: | I have a couple anecdotes to cover your question. | | All of them have something in common: startup needs money | so you demo to potential customers or investors. Unlike | in a stable corporate environment where deadlines can | have flex, you really don't want to cancel or postpone a | meeting to sell to a client - so those demos dates are | set in stone, and if things aren't ready you will need to | pull some heroics. | | One memorable one was when three of us spent the hours | leading up to a demo disabling automation and deploying | to production by hand. What that meant was disabling a | bunch of tests and code that checks those tests succeed | in order to get the code out the door. We spent the next | week cleaning that up. Sometimes you need to test in | production. | | Another was actually a demo for the same client that set | up that meeting. This time we had heard from the initial | introductions they had a specific, very nasty problem and | we could ostensibly solve it (that was true, we _could_ , | but the product at that point had no facility to do it). | So I spent I think three days hacking together a solution | that would solve the problem for the contrived demos we | would show. That solution had atrocious performance | characteristics so we wound up spending a few story | points over the next two sprints to optimize and refactor | the guts. | | Yet another demo was an integration. We had scoped out | the general feature (which was magical when it worked) | but it required a large amount of effort to coordinate | with the original software vendors to get the data we | would need. But those vendors have a tool with a free | trial install which had a bunch of the data in XML, so I | spent a day reverse engineering the schema and a second | day parsing into our internal data model which we demoed | on the third day to show how our product could solve that | particular problem. We never wound up getting data from | the first party company, and the parser got rewritten in | a different language, and the backend that does the stuff | is planned to be replaced in the next few sprints once it | gets priority. | | So TL;DR you have a demo scheduled, you hack together a | thing that can be presented, then spend your time | reimplementing or refactoring the demo code into | something maintainable. | | It helps to have a stack you can really quickly iterate | on. And management that understands demos aren't suitable | for production. | wizofaus wrote: | Why are you doing your demos in a production environment | though? How many live customers did you have that could | have been seriously negatively affected by what you were | deploying (assuming it almost certainly contained bugs)? | majormajor wrote: | What am I gaining from having a stack of PRs there versus | just a series of commits that I'm gonna go back and | polish later, quite probably breaking into various PRs, | but with some additional time and under less pressure? | | When I've hacked together stuff like that I'm often | making it up on the fly, I rarely have a plan in mind | that lines up with how I'd want to present it for code | review later. Hell, a lot of times some of the later PRs | would simply remove the entirety of a failed earlier | attempt! | Supermancho wrote: | This isn't going to get me internet points, but after a | few decades, I like to get my experience down. | | > Well, I'm proceeding from the assumption that | thoughtful review, which takes time, is desirable | | Ofc it's desirable. Nobody is arguing this. | | > If the situation is really that dire, then it's even | more important that you ship product that works. | | That is simply incorrect. Broken features (in innumerable | shades) are debuted all the time to secure future | investment in various ways which are not just financial. | Sometimes it's community confidence, sometimes it's | leadership clout, etc. Betas are a thing. This fear- | mongering about 2500 lines of code is pearl clutching | that hobbles large organizations that either fail to | deliver or fail to deliver stability, regardless of their | processes that drags on development for 4x or 10x, which | they have misplaced confidence in. | | > I hope that most of us, most of the time, aren't less | than a business day away from unemployment, and so | there's usually time for code reviews. (If not, there's a | lot of useless material about it!) | | There is lots of useless material about it. The number | one rule is "don't interrupt the flow of money" but that | rule doesn't extend to every project forever. Large | organizations get less and less efficient over time (see | rule 1) because perfect is the enemy of good. It's a good | tradeoff, when you have an organization that can't keep | up with how much money they are making to start piling on | additional process because you don't know where your | weaknesses are so anything that goes wrong gets an | additional check. Most orgs are not in this boat. | | If you don't look like you're making your money's worth, | even if you can explain how some side-process adds value, | someone starts looking for your replacement and | eventually they will find one and you're gone. That's | true, regardless if you work at some mom and pop shop or | Amazon. You're always one day away from unemployment, | even if you don't know what day the chain of events | started. So code reviews that block features can hurt you | and have put a lot of people out of work, I can attest. | | The gut-check is when a company has a merger/acquisition | deal. The team doesn't have a lot of time to vet the | other company's codebase. You do your best to have your | info meetings, try to run parts of the code with data, | make your recommendations, and the escrow eventually | closes. 2500? How do you think you'll do when looking at | millions of lines? At some point, you will be forced into | black box testing and realize that this is what matters | foremost. Look at the interface, look at the | expectations, look at the data. After that, the rest is | gravy that can be addressed later. | duped wrote: | Hence why you don't have massive PRs like that, code that | is easy to review is quick to merge and quick to ship. | | I wouldn't want to work at a startup that doesn't value | that in their engineering culture, at least not again. | More mature teams (in terms of the staff, not the | business) I've been on get this and ship quickly. | jcpst wrote: | To offer an alternative perspective: I haven't ever | worked at a startup. | | If someone wanted a PR review for 2500 lines, I would | tell them no. I absolutely expect a developer to think | twice when trying to make a change that large in one go. | | When your corporation's billion lines of code are the | engine that helps generate $30,000 a minute, you don't | just say "meh, looks good to me." | | Furthermore, this is multiplied on my team, which is the | framework team. A mistake in our auth middleware, http | client, etc, could easily turn into a mistake on 50+ | other teams. | baq wrote: | If you're the only developer for quite a while... | otherwise reviewability is a thing PRs must be optimized | for or your super-duper-important feature won't get in. | | Either way you should be looking for a new job, because | what you're describing is quite unsustainable in a team | of more than one person working on the same thing. | majormajor wrote: | If you're in a go-under-the-next-day scenario who is even | reviewing your code? How big is your team, realistically? | | Once you have significant runway and can hire, you need | to be able to start delivering faster and faster. One | person writing 2500 lines of code in bursts once or twice | a week isn't going to scale. You need a team, and you | need to be measuring total team throughput. | | Need a new service prototype? A 2500-line PR is | appropriate. But don't be surprised if it needs some big | revisions - that's the point of a prototype anyway. | | Need a feature? One person periodically "when inspiration | and time line up" dropping 2500 lines (this is a LOT of | lines in most languages used these days, even in newer, | more-concise Java versions) on top of what 10 other | people may be working on is _not_ going to help everyone | else move quickly at all. | | If you're the person who's so busy you rarely have time | to code, you need to figure out how to turn your | inspirations into ideas _others_ can execute and be the | code-level experts on. A team of 10 "1x" developers is | still more productive than a single "10x" developer who's | in meetings figuring out the company's plan half the day | anyway. | celtain wrote: | Isn't this exactly why you should use stacked PRs? That's | what it looks like when I break a big piece of work into | smaller pieces. | | What's the alternative anyway? If you don't want me writing | 2500 lines of code in one area, would you rather I write 10 | 250 line PRs in 10 different parts of the codebase instead? | Is that supposed to be easier to review? | | Or is the rule just "don't write a lot of code in any short | period of time"? | morelisp wrote: | > don't write a lot of code in any short period of time | | Depending on the team this may be a completely reasonable | policy. | tomasreimers wrote: | I am one of the authors of the tool Graphite | (https://graphite.dev). We built Graphite because we missed the | stack diff workflow we knew from previous job experiences at | larger companies, happy to answer any questions (and if you would | rather not ask in public, feel free to email me at tomas at | graphite.dev). | yosito wrote: | This article uses the term DAG everywhere, but I couldn't find a | definition of it. | scruple wrote: | Directed Acyclic Graph. | | [0]: https://en.wikipedia.org/wiki/Directed_acyclic_graph | compsciphd wrote: | One thing I wish git did (maybe it does and I don't know how?) is | to be able to say that a new branch is based off an old branch | (not a commit that used to be that branches head). so I can | branch a single pr in progress to start the next. Then if I | change the base pr in progress (say via rebase or via squashing | or the like), I can easily rebase my new commits in the new pr on | top of the current state of the branch. | | Currently, one can just do it by never modifying the underlying | "branch" (i.e. just adding new commits), but in practice that | doesn't always work, as many times you have to rebase against | one's master/main branch to pull in changes, which even if no | conflicts, will reflow your "base" branch" changing all the | commits. | | TLDR: Basically, want to be able to state that branch depends on | branch (which is currently commit id x) but if I rebase, use | whatever the current commit id is for that branch, not whatever | it was when I first made the branch. | | possible? stupid idea? thoughts? | 8K832d7tNmiQ wrote: | > I wish git did is to be able to say that a new branch is | based off an old branch (not a commit that used to be that | branches head). > Then if I change the base pr in progress (say | via rebase or via squashing or the like), I can easily rebase | my new commits in the new pr on top of the current state of the | branch. | | You'd still end up fixing all the conflicts your branch made | either way, and also breaking the flow of commits if you didn't | update the message. So why bother doing all of that instead of | stashing your current project, rebase, and force push it? I | believe that's supposed to be the standard approach to handle | conflict changes in PRs. | msbarnett wrote: | > TLDR: Basically, want to be able to state that branch depends | on branch (which is currently commit id x) but if I rebase, use | whatever the current commit id is for that branch, not whatever | it was when I first made the branch. | | As far as I can tell (the "problem" you're describing is a bit | vague) this is already how git works with the sole exception | being that git doesn't default to a particular branch for a | rebase? | | eg) all you seem to de describing here is a bog-standard: | (on feature-branch1)> git checkout -b feature-branch2 | | <do some work on feature-branch2, return to feature-branch1 and | make some more changes there, now you want to catch feature- | branch2 up with feature-branch1> (on | feature-branch2)> git rebase feature-branch1 | | <now we're branched off of the new tip of feature-branch1, not | where we originally branched> | | All it seems like you're asking for us to drop "feature- | branch1" from the rebase? | epage wrote: | git-stack [0] tries to do that. I also maintain a list of | related tools, some of which do similar [1]. | | [0] https://github.com/gitext-rs/git-stack | | [1] https://github.com/gitext-rs/git- | stack/blob/main/docs/compar... | bqmjjx0kac wrote: | It sounds like you're describing what `git branch --set- | upstream-to=$otherBranch` does? | zackmorris wrote: | Came here to say the same thing. I always rebase my own branch | onto the trunk and force-push before merging. But that's hard | to explain to other developers, and there's no way to enforce | it, so the repo inevitably becomes filled with overlapping | merges, which is an unforced error IMHO. Does anyone know if | there's a way to only allow rebase-and-merge on GitHub and | GitLab? | | https://docs.github.com/en/pull-requests/collaborating-with-... | | https://docs.gitlab.com/ee/topics/git/git_rebase.html#rebase... | regularjack wrote: | Isn't that how rebase already works? It will "apply" commits of | the current branch onto commits of the base branch, including | new commits that were created in the meantime. | theptip wrote: | This is one of the big features from git-branchless | (https://github.com/arxanas/git- | branchless/wiki/Command:-git-...) which is recommended in the | article; moving a stack (sub-tree) of commits instead of just | one branch. | | Might be useful for you if you find the rebase flow to be | painful. In particular this can be good for local prototyping | where you have a bunch of functional candidates on top of some | foundational refactors, and you may be rebasing frequently to | refine those foundational commits. | arxanas wrote: | Also worth pointing out these commands from git-branchless | (I'm the author): | | - git sync: rebase all commit stacks on top of the main | branch. - git restack: run after making a change to a | foundational commit to automatically restack dependent | commits. | dan-robertson wrote: | It feels like roughly the issue is that git thinks in terms of | snapshots whereas people often think in terms of patches. Darcs | and pijul are version control systems that try to have patches | as the fundamental object you operate on instead of snapshots. | In particular, there isn't a rerere operation to change the | base of a commit because patches don't have bases in the same | way. However if you're reviewing code you probably do care | about the base because changing the base may change the meaning | of the branch and if eg some library function is renamed | between when you write/approve a patch and when you merge it, | the patch may no-longer be valid. | avl999 wrote: | I do stacked PRs at work, they work great until someone suggests | an invasive change in a PR lower down in the stack. Does anyone | have ideas on how to deal with merge conflicts in this type of | flow? For example let's say I have the following stack of PRs | | PR1 -> PR2 -> PR3 -> PR4 | | The reviewer reviews and suggests a change in PR1, this change | causes a merge conflict in PR2 and therefore in PR3 and PR4 as | well. And then you have to go in manually resolve the exact same | merge conflict all the way through you PR stack in each of the | PRs. This gets annoying and hard to work with. | | Does anyone have a better way of dealing with this pattern of | merge conflict? I've tried using git rerere which in theory | sounds helpful but doesn't seem to do anything when I strike this | issue. | fire wrote: | huh, shouldn't solving the conflict to pr2 create a merge | commit that then also solves the conflict in 3 and 4? | travisb wrote: | It sounds like the OP might be using a rebase workflow. Such | a workflow creates many repetitive conflicts because there is | no merge commit to record the resolution point. | | Using a rebase workflow with stacked/cascaded PRs is an anti- | pattern that trips up people used to other git workflows | where the history depth is effectively only one level deep | instead of arbitrarily deep as in stacked/cascaded PRs. | xerxes901 wrote: | I think this is something git rerere is supposed to help | with | anderskaseorg wrote: | You can tell git what the resolution point is using `git | rebase --onto`. This can help avoid situations where Git | gives extra conflicts form trying to reapply an old version | of your change on top of a new version of the same change. | You can also use `git rebase --skip` if you recognize that | you've ended up in this situation. | kqr wrote: | I wish I had a better answer for you but my go-to solution as | of late has been the pragmatic "I agree. Do you mind if I fix | that in a later PR to avoid spending too much time on it?" | | If you've built up some trust with your team, they shouldn't | have a problem with it. | arxanas wrote: | The linked tool git-branchless handles this pretty well | (https://github.com/arxanas/git-branchless, I'm the author). | You basically run `git checkout <branch>`, `git commit | --amend`, and then `git restack`. This will rebase all | dependent branches. As long as you're not using merge commits, | you won't have to resolve the same conflict more than once. (It | will also warn you up front whether or not merge conflicts will | need to be resolved; you can pass `--merge` to start merge | conflict resolution.) | | To rebase your commit stack on top of the main branch, use `git | sync` instead of `git merge`. Merge commits often make it so | that you have to resolve conflicts multiple times. | bvrmn wrote: | Mentioned tools seem highly underfeatured comparing with stacked | git[1]. | | [1] https://stacked-git.github.io/ | arxanas wrote: | Hi bvrmn, I've been meaning to write a comparison of git- | branchless with Stacked Git, as they occupy similar spaces. Can | you list some of the features which Stacked Git has which git- | branchless might not? | moffkalast wrote: | Well this would be impossible to explain and coordinate with the | team | __derek__ wrote: | I'm guilty of doing this in the past, but it seems like an anti- | pattern because it attempts to create a local optimum, a big no- | no in the Theory of Constraints[1]. Better to find ways to | sustainably ease the constraint (code reviewers' time/attention) | than to find ways to create more WIP at the constraint. | | [1]: https://en.wikipedia.org/wiki/Theory_of_constraints | morelisp wrote: | As someone coming down from a nearly 2 year fight with an | engineering manager whose response to every bug was enforcing | more code review rules, and every code review backlog was | demanding more time allocated for code review, thank you for | this comment. | d0mine wrote: | Could you suggest some specific alternatives? | baq wrote: | i got a major cognitive dissonance from your comment because | stacking PRs is for me the way to get more time and attention | from potential reviewers by making their units of work smaller; | hopefully small enough to be easily mergable. this is a case of | 'more is less' (within reason). | ramraj07 wrote: | Any UI suggestions to make stacked PRs easier? Other than | graphite.dev - that needs org access on GitHub. | stitched2gethr wrote: | I believe this goes a bit further and decouples the submission | from the review. My team reviews PRs very fast, but why should | I wait 15 minutes between submitting and continuing my work. Or | what about when I'm working late when no one else is online. ___________________________________________________________________ (page generated 2022-07-24 23:00 UTC)