[HN Gopher] GitHub Stacked PRs
       ___________________________________________________________________
        
       GitHub Stacked PRs
        
       Author : ezekg
       Score  : 864 points
       Date   : 2026-04-13 20:36 UTC (1 days ago)
        
 (HTM) web link (github.github.com)
 (TXT) w3m dump (github.github.com)
        
       | ZeWaka wrote:
       | Seems to mainly be useful for monorepos as currently designed.
       | Or, to replace a long-lived feature/refactor branch.
        
         | YesThatTom2 wrote:
         | Whatbmakes you say that? Devs use stacked PRs in small and
         | large repos today.
        
           | ZeWaka wrote:
           | Their examples show combined backend and frontend changes on
           | the same monorepo in different PRs.
           | 
           | As far as splitting work into different PRs that need
           | coordinated merging, I've only ever encountered that when
           | it's a long lived refactor / feature.
        
         | Hamuko wrote:
         | I think the only thing I miss from GitLab was being able to
         | make merge requests depend on other merge requests, even across
         | repositories. So I could make a backend repository MR depend on
         | a library repository MR, and even enable auto-merge that'd fire
         | when the backend MR was reviewed and the dependency was also
         | merged.
        
       | inetknght wrote:
       | Cool. Now let me do it across multiple repos. I often end up with
       | 10 or 20 PRs across a half dozen repos that need to be merged in
       | specific order.
        
         | throwaway9980 wrote:
         | Who hurt you?
        
           | dpcx wrote:
           | Their manager who suggested that everything be a
           | microservice, but everything depends on each other.
        
           | simplyluke wrote:
           | Microservices, by the sound of the original comment
        
             | Arbortheus wrote:
             | Microservices without a monorepo is hell
        
               | Yokohiii wrote:
               | They've opted for critical damage.
        
         | whalesalad wrote:
         | For sure. If you are in a monorepo this solution works but if
         | you have distinct microservice repositories it would help to
         | coordinate pr #827 on repo-A and pr #1092 on repo-B are related
         | and need to ship in a certain order.
        
           | ZeWaka wrote:
           | Exact problem we've run into at work. We've ended up having
           | to write external merge coordination in order to not break
           | our dev deployments.
        
         | ameliaquining wrote:
         | How would that work? Commits in different repos aren't ordered
         | relative to one another. I suppose you could have a "don't let
         | me merge this PR until after this other PR is merged" feature,
         | but you could do that with a GitHub Action; it doesn't really
         | need dedicated backend or UI support.
        
           | inetknght wrote:
           | > _How would that work?_
           | 
           | In practical terms: I manually write a list of PRs, and
           | maintain that list in the description of each of the PRs.
           | Massive duplication. But it clearly shows the merge train.
        
       | noident wrote:
       | If only there were some way to logically break up large pull
       | requests into smaller pieces... Some way of creating a checkpoint
       | with a diff including your changes, and some kind of message
       | explaining the context behind the change... some way to "commit"
       | a change to the record of the repository...
        
         | Hamuko wrote:
         | Yeah, I feel like just being able to review a PR commit-by-
         | commit with a nice interface would just suffice.
        
           | ezekg wrote:
           | Not really. Without seeing the entire changeset for a PR,
           | you'd have to mentally keep track of what the current state
           | of everything is unless you're a commit minimalist and
           | presquash.
        
             | aunderscored wrote:
             | How does that differ from this where you need to keep track
             | of state and the whole change in the stack?
        
               | ezekg wrote:
               | If we're speaking strictly code review, because you can
               | actually make sense of the changeset for the child PR by
               | not including its unmerged parent's changeset.
        
           | benatkin wrote:
           | For me that would mean avoiding tiny commits, and I wouldn't
           | want to do that
        
         | jaredsohn wrote:
         | There are tools that use LLMs to do this.
         | 
         | I've done this manually by building a big feature branch and
         | asking an LLM to extract out functionality for a portion of it.
         | 
         | For the former, it would seem to split based on
         | frontend/backend, etc. rather than what semantically makes the
         | most sense and for the latter it would include changes I don't
         | want and forget some I do want. But I haven't tried this a lot.
        
         | bombcar wrote:
         | So much effort has been spent beating _git_ until it 's just
         | CVS with bells on.
        
           | steveklabnik wrote:
           | The stacked diffs flow is much closer to the kernel flow for
           | git than the traditional GitHub PR flow is.
        
         | landr0id wrote:
         | Part of the idea behind stacked PRs is to keep your commits
         | focused and with isolated changes that are meaningful.
         | 
         | A stacked PR allows you to construct a sequence of PRs in a way
         | that allows you to iterate on and merge the isolated commits,
         | but blocks merging items higher in the stack until the
         | foundational changes are merged.
        
           | noident wrote:
           | What can stacked PRs do that a series of well-organized
           | commits in a single branch can't?
        
             | steveklabnik wrote:
             | Stacked PRs tend to encourage a series of well-organized
             | commits, because you review each commit separately, rather
             | than together.
             | 
             | What they do that the single branch cannot is things like
             | "have a disjoint set of reviewers where some people only
             | review some commits", and that property is exactly why it
             | encourages more well-organized commits, because you are
             | reviewing them individually, rather than as a massive
             | whole.
             | 
             | They also encourage amending existing commits rather than
             | throwing fixup commits onto the end of a branch, which
             | makes the original commit better rather than splitting it
             | into multiple that aren't semantically useful on their own.
        
               | a_e_k wrote:
               | I think the point the GP was trying to make is that the
               | GitHub UI ought to be able to allow you to submit a
               | branch with multiple well-organized commits and review
               | each commit separately with its own PR. The curation of
               | the commits that you'd do for stacked PRs could just as
               | easily be done with commits on a single branch; some of
               | us _don 't_ just toss random WIP and fixup commits on a
               | branch and leave it to GitHub to squash at the end. I.e.,
               | it's the GitHub UI rather than Git that has been lacking.
               | 
               | (FWIW, I'm dealing with this sort of thing at work right
               | now - working on a complex branch, rewriting history to
               | keep it as a sequence of clean testable and reviewable
               | commits, with a plan to split them out to individual PRs
               | when I finish.)
        
               | steveklabnik wrote:
               | > I think the point the GP was trying to make is that the
               | GitHub UI ought to be able to allow you to submit a
               | branch with multiple well-organized commits and review
               | each commit separately with its own PR.
               | 
               | That's what this feature is, conceptually. In practice,
               | it does seem slightly more cumbersome due to the fact
               | that they're building it on top of the existing, branch-
               | based PR system, but if you want to keep it to one
               | commit, you can (and that's how I've been working with
               | PRs for a while now regardless, honestly).
               | 
               | They confirmed in other comments here that you don't
               | _have_ to use the CLI, just like you don 't have to use
               | gh in general to make pull requests, it's just that they
               | think the experience is nicer with it. This is largely a
               | forge-side UI change.
        
               | dontlikeyoueith wrote:
               | > I think the point the GP was trying to make is that the
               | GitHub UI ought to be able to allow you to submit a
               | branch with multiple well-organized commits and review
               | each commit separately with its own PR
               | 
               | So the point he's trying to make is that Gituhub UI
               | should support Stacked PRs but call them something else
               | because he doesn't like the name?
        
         | pertymcpert wrote:
         | What might that be?
        
       | bsimpson wrote:
       | Finally!
       | 
       | I never understood the PR=branch model GitHub defaulted to.
       | Stacked commits (ala Phabricator/Gerrit) always jived more with
       | how my brain reasons about changes.
       | 
       | Glad to see this option. I guess I'll have to install their CLI
       | thing now.
        
         | ezekg wrote:
         | My only complaint off the bat is the reliance on the GH CLI,
         | which I don't use either. But maybe by the time it's GA they'll
         | have added UI support.
        
           | ZeWaka wrote:
           | It seems partially exposed in the UI with that dropdown.
           | There's an 'add' and 'unstack' button.
           | 
           | Probably relies on some internal metadata.
        
           | ameliaquining wrote:
           | You can in fact do this from the web UI:
           | https://github.github.com/gh-stack/guides/ui/#creating-a-
           | sta...
        
             | ezekg wrote:
             | I must have missed that. Amazing! From a reviewer's POV,
             | this will be so nice to at the very least remove diff noise
             | for PRs built on top of another PR. I usually refrain from
             | reviewing child PRs until the parent is merged and the
             | child can be rebased, for the sole reason that the diffs
             | are hard to review i.r.t. what came from where.
        
             | NooneAtAll3 wrote:
             | damn, I missed it as well
             | 
             | presenting only cli commands in announcement wasn't a good
             | choice
        
           | SamuelAdams wrote:
           | CLI is great because now I can tell my AI agent to do it.
           | "Fix all dependabot security issues (copy logs) and run tests
           | to validate functionality. Create each dependency as its own
           | stack (or commit) so that contributors may review each
           | library update easily."
           | 
           | Wait 10 minutes and you're done.
        
             | sameenkarim wrote:
             | We're shipping a skill file with the CLI:
             | https://skills.sh/github/gh-stack/gh-stack
             | 
             | Everyone will have their own way of structuring stacks, but
             | I've found it great for the agent to plan a stack structure
             | that mirrors the work to be done.
        
           | bmitc wrote:
           | Why don't you use the CLI?
        
             | ezekg wrote:
             | Because git is all I need.
        
               | bmitc wrote:
               | Then why are you using GitHub? :)
               | 
               | My point is that Git is just a component of the GitHub
               | tool, and the GitHub CLI is quite good and helps automate
               | many things in GitHub. For example, even just using `gh
               | browse` and `gh pr create --web` and `gh pr view --web`
               | are fantastic tools.
        
               | ezekg wrote:
               | I don't need to automate anything in GitHub, I have a web
               | browser for when I need to use GitHub. Installing and
               | learning another CLI seems like a waste of my time for
               | very, very little return.
        
               | bmitc wrote:
               | You would rather manually browse to the repo you're
               | working on in the web interface rather than typing `gh
               | browse`? I hate CLIs, in general, but the GitHub CLI has
               | some very useful commands.
        
           | sameenkarim wrote:
           | Stacked PRs can be created via the UI, API, or CLI.
           | 
           | You can also run a combination of these. For ex, use another
           | tool like jj to develop locally, push up the branches, and
           | use the gh CLI to batch create a stack of n PRs, without
           | touching local state.
        
             | ezekg wrote:
             | Amazing. Though this wasn't super obvious from the landing
             | page or docs I read.
        
         | contravariant wrote:
         | Huh interesting, my mental model is unable to see any
         | difference between them.
         | 
         | I mean a branch is just jamming a flag into a commit with a
         | polite note to move the flag along if you're working on it. You
         | make a long trail, leave several flags and merge the whole
         | thing back.
         | 
         | Of course leaving multiple waypoints only makes sense if
         | merging the earlier parts makes any sense, and if the way you
         | continue actually depends on the previous work.
         | 
         | If you can split it into several small changes made to a
         | central branch it's a lot easier to merge things. Otherwise you
         | risk making a new feature codependent on another _even if there
         | was no need to_.
        
       | pbrowne011 wrote:
       | Interesting to see how their CLI compares with GitLab's CLI
       | interface for stacked diffs (the only support they offer at the
       | moment):
       | https://docs.gitlab.com/user/project/merge_requests/stacked_....
       | Most things are the same (up/down/top/bottom vs.
       | next/prev/first/last, init vs. create), but both feel quite
       | limiting. I've heard of other systems such as Gerrit that offer
       | better native support, but have not tried out any for myself.
        
       | whalesalad wrote:
       | At first I thought this was a user submitted project due to the
       | subdomain of github.com but then realize the subdomain is also
       | github. Is this an official channel for this sort of thing?
       | Surprised this isn't on the official blog.
        
         | ZeWaka wrote:
         | It's their 'GitHub' org GitHub Pages domain - it's just .com
         | instead of .io (not to be confused with their gh.io link
         | shortener)
        
         | ameliaquining wrote:
         | It's in private preview. Probably they'll put it in the main
         | docs and such once it's open to everyone.
        
         | varun_ch wrote:
         | it's a GitHub Pages site in the @GitHub org from a repo called
         | gh-stack (i.e. the repo is at https://github.com/github/gh-
         | stack/).
         | 
         | There's a special case where certain official orgs can continue
         | to use github.com instead of github.io for their Pages domain,
         | and that's how you end up with:
         | 
         | https://github.github.com/gh-stack/
         | 
         | from the code:
         | 
         | Should Pages owned by this user be regarded as "Official GitHub
         | properties"?
         | 
         | def github_owned_pages?
         | GitHub.github_owned_pages.include?(login) end
         | 
         | # Orgs/users that are owned by GitHub and should be allowed to
         | use # `github.com` URLs. # # Returns an Array of String
         | User/Organization logins. ...
        
       | topaztee wrote:
       | how is this different than viewing a PR one commit at a time?
        
         | simplyluke wrote:
         | Split into individual PRs, which works better for how a lot of
         | companies do code review.
        
         | Macha wrote:
         | Each commit can be merged independently as they're reviewed.
        
           | Hamuko wrote:
           | One of the advertised features of this is being able to merge
           | all the PRs at once. Which would also be the case for
           | multiple commits in a single PR.
        
             | Arainach wrote:
             | That's possible but not mandatory. In the current UX you
             | can only approve/submit all or none.
        
           | CharlieDigital wrote:
           | I don't think this is it. The main driver is that several
           | operations in GH are scoped around a PR, not a commit. So the
           | reason you need stacked PRs is that the layer of tooling
           | above `git` is designed to work on logical groups of commits
           | called a PR.
        
             | 4b11b4 wrote:
             | Right, the argument against: "how is this any different
             | than splitting into single commits?" is simply: In general
             | you want just one level above a commit which is the PR
        
         | nickcw wrote:
         | I think it is conceptually the same but multiple PRs gives you
         | the tools to manage the commits properly which GitHub is
         | missing. You can't do the equivalent of `git rebase -i` in the
         | GitHub UI to squash a fixup into a previous commit. Having each
         | change in it's own PR enables that workflow using the existing
         | GitHub UI.
        
         | stephbook wrote:
         | Commits are immutable and you never know which feedback goes
         | stale when you add another commit.
         | 
         | I'm not a huge fan, since stacked PRs mean the underlying
         | issues don't get addressed (reviews clearly taking too long,
         | too much content in there), but it seems they want something
         | that works for their customers, right now, as they work in real
         | life.
        
           | normie3000 wrote:
           | > Commits are immutable
           | 
           | I guess this is why you're getting downvoted. Commits can be
           | edited.
        
             | steveklabnik wrote:
             | When you edit a commit, it creates a new commit. They are
             | immutable. You can still find the old commit via the
             | reflog, until it gets eventually gc'd.
             | 
             | If I had to guess a reason they were downvoted (and I
             | didn't downvote, to be clear), it's probably because people
             | see stacked diffs as specifically solving "reviews clearly
             | taking too long, too much content in there", and so it
             | feels contradictory. Then again, as I said, I didn't
             | downvote!
        
               | normie3000 wrote:
               | Thank you for the correction.
        
               | mortar wrote:
               | I agree with the sentiment but hash collisions can occur
               | with different content which doesn't really make them
               | immutable.
        
         | masklinn wrote:
         | Stacked PRs track changes through updates and can be integrated
         | progressively as they get validated.
         | 
         | They also allow reviewing commits individually, which is very
         | frustrating to do without dedicated support (unless you devolve
         | back to mailing list patch stacks).
        
         | IshKebab wrote:
         | CI runs on each PR, you get a whole PR message and
         | discussion/review interface for each PR. Each PR can itself
         | consist of multiple commits. You can have stacked PRs from
         | different authors (though from another comment it sounds like
         | they may not have implemented that).
         | 
         | It's a big improvement (assuming they've done it right).
        
         | dboreham wrote:
         | It would be the same if commits were meaningful things. But
         | typically they're not. The PR is the meaningful thing. A commit
         | is something like "fix the lint error".
        
       | chao- wrote:
       | Even though moments where I would reach for it are rare, this is
       | a very welcome feature. In times when I could have used it, it
       | was not difficult to emulate via more branches, consistent
       | naming, referencing the PRs, etc. Not difficult, but definitely
       | tedious, and always left me feeling less organized than I like to
       | feel.
        
       | adamwk wrote:
       | As someone who used phabricator and mercurial, using GitHub and
       | git again feels like going back to the stone ages. Hopefully this
       | and jujutsu can recreate stacked-diff flow of phabricator.
       | 
       | It's not just nice for monorepos. It makes both reviewing and
       | working on long-running feature projects so much nicer. It
       | encourages smaller PRs or diffs so that reviews are quick and
       | easy to do in between builds (whereas long pull requests take a
       | big chunk of time).
        
         | kardianos wrote:
         | I continue to use gerrit explicitly because I cannot stand
         | github reviews. Yes, in theory, make changes small. But if I'm
         | doing larger work (like updating a vendored dep, that I still
         | review), reviewing files is... not great... in github.
        
           | tcoff91 wrote:
           | Most editors have some kind of way to review github PRs in
           | your editor. VSCode has a great one. I use octo.nvim since I
           | use neovim.
        
             | nine_k wrote:
             | Can these tools e.g. do per-commit review? I mean, it's not
             | the UI what's the problem (though it's not ideal), it's the
             | whole idea of commenting the entire PR at once, partly
             | ignoring the fact that the code in it changes with more
             | commits pushed.
             | 
             | Phabricator and even Gerrit are significantly nicer.
        
               | dathanb82 wrote:
               | Unless you have a "every commit must build" rule, why
               | would you review commits independently? The entire PR is
               | the change set - what's problematic about reviewing it as
               | such?
        
               | steveklabnik wrote:
               | In stacked diffs system, each commit is expected to land
               | cleanly, yes.
        
               | verst wrote:
               | But isn't that why you would squash before merging your
               | PR? If you define a rule that PRs must be squashed you
               | would still have the per commit build.
        
               | steveklabnik wrote:
               | Squash merge is an artifact of PRs encouraging you to add
               | commits instead of amending them, due to GitHub not being
               | able to show you proper interdiffs, and making comments
               | disappear when you change a diff at that line. In that
               | context, when you add fixup commits, sure, squashing
               | makes sense, but the stacked diffs approach encourages
               | you to create commits that look like you want them to
               | look like directly, instead of requiring you to roll them
               | up at the end.
        
               | riffraff wrote:
               | There's a certain set of changes which are just easier to
               | review as stacked independent commits.
               | 
               | Like, you can do a change that introduced a new API and
               | one that updates all usages.
               | 
               | It's just easier to review those independently.
               | 
               | Or, you may have workflows where you have different
               | versions of schemas and you always keep the old ones.
               | Then you can do two commits (copy X to X+1; update X+1)
               | where the change is obvious, rather than seeing a single
               | diff which is just a huge new file.
               | 
               | I'm sure there's more cases. It's not super common but it
               | is convenient.
        
               | Sebb767 wrote:
               | > Unless you have a "every commit must build" rule, why
               | would you review commits independently?
               | 
               | Security. Imagine commit #1 introduces a security
               | vulnerability (backdoor) and the features. Then #2
               | introduces a non-obvious, harmless bug and closes the
               | vulnerability introduced in #1 [0]. At some point, the
               | bug will surface and rolling back commit #2 will be an
               | easy fix, re-introducing your bug.
               | 
               | Alternatively, one of the earlier commits might, for
               | example, contain credential dumping code. Once that
               | commit is mainlined, CI might either automatically run on
               | it or will be able to be run on it since it's no longer
               | marked as unsafe PR.
               | 
               | [0] Think something like #1 introduces array access and
               | #2 adds a bounds-check in a function a layer above - a
               | reviewer with the whole context will see the bounds check
               | and (possibly) consider it fine, but to someone rolling
               | back a commit the necessity will not be obvious.
        
           | adityaathalye wrote:
           | Same team, and a rare hill I'm willing to die on.
           | 
           | Rant incoming...
           | 
           | Boy do I hate Github/Lab/Bucket style code reviews with a
           | burning passion. Who the hell _loses_ code review history? A
           | record of the very thing that made my code better? The  "why"
           | of it all, that I am guaranteed to forget tomorrow morning.
           | 
           | Nobody would be using `--force` or `--force-with-lease` as a
           | _normal_ part of development workflow, of their own volition,
           | if they had read that part of the git-push manpage and been
           | _horrified_ (as one should be).
           | 
           | The magit key sequence for this abominable operation is `P
           | "f-u"`. And every single time I am forced to do it, I read
           | "f-u" as it ought to be read.
           | 
           | Rebase-push _is_ the way to do it (patch sets in Gerrit).
           | 
           | Rebase-force-push is _absolutely not_.
           | 
           | You see, _any_ development workflow inevitably has to
           | integrate changes from at least one other branch (typically
           | latest develop or master), without destroying change history,
           | nor review history. Gerrit makes this trivial.
           | 
           | It's a bit difficult to convey exactly why I'm so rah-rah
           | Gerrit, because it is a matter of day-to-day experience of
           | - Well, a single commit of a few lines to maybe a hundred
           | lines *is* the correct unit of code review, rebase, revert
           | etc. Manually "Sizing PRs" to that review context size is
           | utter BS. I have better things to do in life than to book-
           | keep PR sizes. Make a single well-contained, revertible
           | commit. Then keep making those. And now you have a commit
           | history that is clean, that you can merge, bisect, and bulk-
           | revert at will. Octopus merges are a good thing. `git-log` is
           | *designed* to let us view changes in any sequence we wish,
           | *including* the so-called "linear" history. `git log
           | --online`.            - Trivial for committer to send up
           | reviews-preserving rebase-push responses to commit reviews
           | (NO force-push, ever --- that's an "admin" action to *evict*
           | / permanently wipe out disaster scenarios such as when
           | someone accidentally commits and pushes out a plaintext
           | secret or a giant blob of the executable of the source code
           | etc.).            - Fast-for-the-reviewer, per-commit, diff-
           | based, inline-commenting code reviews.            - The
           | years-apart experience of being able to dig into any part of
           | one's (immutable) software change history to offer a teaching
           | moment to someone new to the team.
           | 
           | ... to name a few key ones.
           | 
           | (edit: add point about review size)
        
             | adityaathalye wrote:
             | Slapping this "stacked diff" business _on top of_ something
             | so broken as Github /lab/bucket is a concrete example of...
             | https://en.wikipedia.org/wiki/Lipstick_on_a_pig
        
         | smallmancontrov wrote:
         | I'm so glad git won the dvcs war. There was a solid decade
         | where mercurial kept promoting itself as "faster than git*+++"
         | and every time I tried it wound up being dog slow (always) or
         | broken (some of the time). Git is fugly but it's fast,
         | reliable, and fugly, and I can work with that.
        
           | Leynos wrote:
           | I just used it because I preferred the UX.
        
           | forrestthewoods wrote:
           | Mercurial has a strictly superior API. The issue is solely
           | that OG Mercurial was written in Python.
           | 
           | Git is super mid. It's a shame that Git and GitHub are so
           | dominant that VCS tooling has stagnated. It could be so so so
           | much better!
        
             | awesome_dude wrote:
             | Whatever your opinion on one tool or another might be - it
             | does seem weird that the "market" has been captured by what
             | you are saying is a lesser product.
             | 
             | IOW, what do you know that nobody else does?
        
               | jrochkind1 wrote:
               | Welcome to VHS and Betamax. the superior product does not
               | always win the market.
        
               | Per_Bothner wrote:
               | Not always, but in this case the superior product (i.e.
               | VHS) won. At initial release, Beta could only record an
               | hour of content, while VHS could record 2 hours. Huge
               | difference in functionality. The quality difference was
               | there, but pretty modest.
        
               | jrochkind1 wrote:
               | I suppose one lesson could be that there are different
               | dimensions of superiority, different products may be
               | superior in different ways.
               | 
               | Of course, products also can win market dominance for
               | reasons external to the product's quality itself
               | (marketing, monopoly lock-in, other network effects,
               | consumer preferences on something other than product
               | quality itself, etc).
        
               | esafak wrote:
               | That worse is better, and some people don't know better
               | or care.
        
               | dwattttt wrote:
               | "better" in that sentence is very specific. Worse is also
               | worse, and if you're one of the people for whom the
               | "better" side of a solution doesn't apply, you're left
               | with a mess that people celebrate.
        
               | guelo wrote:
               | Network effects and marketing can easily prevent better
               | tools from winning.
        
               | awesome_dude wrote:
               | I mean, in the fickle world that is TECH, I am struggling
               | to believe that that's what's happened.
               | 
               | I personally went from .latest.latest.latest.use.this
               | (naming versions as latest) to tortoise SVN (which I
               | struggled with) to Git (which I also was one of those
               | "walk around with a few memorised commands" people that
               | don't actually know how to use it) to reading the fine
               | manual (well 2.5 chapters of it) to being an evangalist.
               | 
               | I've tried Mercurial, and, frankly, it was just as black
               | magic as Git was to me.
               | 
               | That's network effects.
               | 
               | But my counter is - I've not found Mercurial to be any
               | better, not at all.
               | 
               | I have made multiple attempts to use it, but it's just
               | not doing what I want.
               | 
               | And that's why I'm asking, is it any better, or not.
        
               | WolfeReader wrote:
               | Mercurial has a more consistent CLI, a really good
               | default GUI (TortoiseHg), and the ability to remember
               | what branch a commit was made on. It's a much easier tool
               | to teach to new developers.
        
               | awesome_dude wrote:
               | Hmm, that feels a bit subjective - I'm not going to say X
               | is easier than Y when I've just finished saying that I
               | found both tools to have a lot of black magic happening.
               | 
               | But what I will point out, for better or worse, people
               | are now looking at LLMs as Git masters, which is
               | effectively making the LLM the UI which is going to have
               | the effect of removing any assumed advantage of whichever
               | is the "superior" UX
               | 
               | I do wish to make absolutely clear that I personally am
               | not yet ready to completely delegate VCS work to LLMs -
               | as I have pointed out I have what I like to think of as
               | an advanced understanding of the tools, which affords me
               | the luxury of not having an LLM shoot me in the foot,
               | that is soley reserved as my own doing :)
        
               | arw0n wrote:
               | Networking effects are significantly strengthened by
               | necessary user buy in. VC is hard, and every tool demands
               | its users to spend a non-significant amount of time
               | learning it. I would guess the time to move from black
               | magic to understanding most of git is ~100h for most
               | people.
               | 
               | The thing is, to understand which one is actually better,
               | you would have to give the same amount of investment in
               | the second tool, which is not something most people are
               | willing to do if the first tool is "good enough". That's
               | how Python became the default programming language;
               | people don't miss features they do not understand.
        
               | Izkata wrote:
               | A little over a decade ago, with only svn experience, I
               | tried both mercurial and git. There was something about
               | how mercurial handled branches that I found extremely
               | confusing (don't remember what), while git clicked
               | immediately - even without reading the manual.
               | 
               | So at least for me, git was clearly better.
        
               | ptx wrote:
               | Mercurial later added bookmarks which work like Git
               | branches. These make more sense to me as well.
        
               | qsera wrote:
               | Did bookmarks moved as you made commits, like a branch
               | pointer in git does?
        
               | ptx wrote:
               | Yup: https://mercurial-scm.org/help/commands/bookmarks
        
               | forrestthewoods wrote:
               | Worse products win all the time. Inertia is almost
               | impossible to overcome. VHS vs Betamax is a classic. iPod
               | wasn't the best mp3 player but being a better mp3 player
               | wasn't enough to claw market share.
               | 
               | Google and Meta don't use Git and GitHub. Sapling and
               | Phabricator much much better (when supported by a massive
               | internal team)
        
               | aaronbrethorst wrote:
               | What was the better mp3 player than the iPod?
        
               | corndoge wrote:
               | sansa clip+
        
               | mi_lk wrote:
               | unironically Zune is goated in its own way
        
               | CrimsonRain wrote:
               | anything from Cowon. Always has been
        
               | codethief wrote:
               | Anything from iriver.
        
               | jorams wrote:
               | So far you've only gotten responses to "how can a worse
               | product win?", and they are valid, but honestly the
               | problem here is that Mercurial is not a better product in
               | at least one very important way: branches.
               | 
               | You can visit any resource about git and branches will
               | have a prominent role. Git is very good at branches.
               | Mercurial fans will counter by explaining one of the
               | several different branching options it has available and
               | how it is better than the one git has. They may very well
               | be right. It also doesn't matter, because the fact that
               | there's a discussion about what branching method to use
               | really just means Mercurial doesn't solve branches. For
               | close to 20 years the Mercurial website contained a guide
               | that explained only how to have "branches" by having
               | multiple copies of the repository on your system. It
               | looks like the website has now been updated: it doesn't
               | have any explanation about branches at all that I can
               | find. Instead it links to several different external
               | resources that don't focus on branches either. One of
               | them mentions "topic", introduced in 2015. Maybe that's
               | the answer to Git's branching model. I don't care enough
               | to look into it. By 2015 Git had long since won.
               | 
               | Mercurial is a cool toolbox of stuff. Some of them are
               | almost certainly better than git. It's not a better
               | product.
        
               | LordDragonfang wrote:
               | This is so strange, because, at a low level, a branch
               | isn't even a "thing" in git. There is no branch object
               | type in git, it's literally just a pointer to a commit,
               | functionally no different from a tag except for the
               | commands that interact with it.
        
               | fc417fc802 wrote:
               | Meanwhile mercurial has bookmarks. TBF I'm not sure when
               | it got those but they've been around forever at this
               | point. The purpose is served.
               | 
               | I think there are (or perhaps were) some product issues
               | regarding the specifics of various workflows. But at
               | least some of that is simply the inertia of entrenched
               | workflows and where there are actual downsides the (IMO
               | substantial) advantages need to be properly weighed
               | against them.
               | 
               | Personally I think it just comes down to the status quo.
               | Git is popular because it's popular, not because it's
               | noticably superior.
        
               | ezst wrote:
               | > I think there are (or perhaps were) some product issues
               | regarding the specifics of various workflows.
               | 
               | I love jumping in discussions about git branching,
               | because that's a very objective and practical area where
               | git made the playing field worse. Less and less people
               | feel it, because people old-enough to have used branch-
               | powered VCSes have long forgotten about them, and those
               | who didn't forget are under-represented in comparison to
               | the newcomers who never have experienced anything else
               | since git became a monopoly.
               | 
               | Anyhow, let's pick django as a project that was using a
               | VCS with branches before moving to git/github, and have a
               | look at the repo history:
               | https://github.com/django/django/commits/stable/6.0.x
               | 
               | Yes, every commit is prefixed with the branch name.
               | Because, unlike mercurial, git is incapable of storing
               | this in its commit metadata. That's ridiculous, that's
               | obscene, but that's the easiest way to do it with git.
        
               | Tarq0n wrote:
               | That's the definition of a tree though. Everything has a
               | parent, no cycles allowed.
        
               | xmcqdpt2 wrote:
               | It's interesting that branches, which is a marquee
               | feature of git, became less important at the same time as
               | git ate all the other vcs. Outside of OS projects, almost
               | all development is trunk based with continuous releases.
               | 
               | Maybe branching was an important reason to adopt git but
               | now we'd probably be ok with a vcs that doesn't even
               | support them.
        
               | krick wrote:
               | Not sure if it's true. I mean, I do agree with the core
               | of it, but how do you even do PRs and resolve conflicts,
               | if there are no branches and a developer cannot
               | efficiently update his code against the last (remote)
               | version of master branch?
        
               | qsera wrote:
               | To me mercurials branching is closer to the development
               | process and preserves more information, because it
               | records the original branch a commit was made.
               | 
               | Git does not have such concept. That is a trade off and
               | that trade off works great for projects managed like
               | Linux kernel. But for smaller projects where there is a
               | limited number of people working, the information
               | preserved by mercurial could be very valuable.
               | 
               | It also had some really interesting ideas like change set
               | evolution, which enabled history re-writing after a
               | branch has been published. Don't know its current status
               | and how well it turned out to be..
        
               | dugmartin wrote:
               | JWZ is still blocking traffic from HN so you can't click
               | to read this but you can copy/paste it into a new tab or
               | open it in a incognito window:
               | 
               | https://www.jwz.org/doc/worse-is-better.html
        
               | kasey_junk wrote:
               | GitHub had a business model where public repos were free.
               | BitBucket didn't.
               | 
               | That's it. That's why git won, you could put up open
               | source libs with one for free and not the other.
               | 
               | Which is extra funny as the centralized service was the
               | most important part of decentralized version control.
        
               | seniorThrowaway wrote:
               | >the centralized service was the most important part of
               | decentralized version control.
               | 
               | I've often thought this about github
        
             | worldsayshi wrote:
             | Maybe forgejo has a shot?
        
               | PeterStuer wrote:
               | Unfortunatly out-of-the-box llm agents only focus on
               | github support, creating friction.
        
               | worldsayshi wrote:
               | So pi.dev + forgejo?
        
               | ptx wrote:
               | It doesn't seem to support Mercurial though (not to imply
               | that you were implying that it did). All I can find in
               | this proxy/mirror thing to integrate it by presenting the
               | Mercurial repo as a Git server:
               | https://peterlavalle.github.io/post/forgejo-actions/
        
             | outworlder wrote:
             | > The issue is solely that OG Mercurial was written in
             | Python.
             | 
             | Are we back to "programming language X is slow" assertions?
             | I thought those had died long ago.
             | 
             | Better algorithms win over 'better' programming languages
             | every single time. Git is really simple and efficient. You
             | could reimplement it in Python and I doubt it would see any
             | significant slowness. Heck, git was originally implemented
             | as a handful of low level binaries stitched together with
             | shell scripts.
        
               | forrestthewoods wrote:
               | They died because everyone knows that Python is infact
               | very very slow. And that's just totally fine for a vast
               | number of glue operations.
               | 
               | It's amusing you call Git fast. It's notoriously
               | problematic for large repos such that virtually every
               | BigTech company has made a custom rewrite at some point
               | or another!
        
               | jstimpfle wrote:
               | Now that is interesting too, because git _is_ very fast
               | for all I have ever done. It may not scale to Google
               | monorepo size, it would ve the wrong tool for that. But
               | if you are talking Linux kernel source scale, it
               | asolutely, is fast enough even for that.
               | 
               | For everything I've ever done, git was practically
               | instant (except network IO of course). It's one of the
               | fastest and most reliable tools I know. If it isn't fast
               | for you, chances are you are on a slow Windows filesysrem
               | additionally impeded by a Virus scanner.
        
               | forrestthewoods wrote:
               | The fact that Git has an extremely strong preference for
               | storing full and complete history on every machine is a
               | major annoyance! "Except for network IO" is not a valid
               | excuse imho. Cloning the Linux kernel should take only a
               | few seconds. It does not. This is slow and bad.
               | 
               | The mere fact that Git is unable to handle large binary
               | files makes it an unusable tool for literally every
               | project I have ever worked on in my entire career.
        
               | pabs3 wrote:
               | Git handles large text files and large directories fairly
               | poorly too.
        
               | spockz wrote:
               | Git-lfs exists for a while now. Does that fix your issue?
               | Or do you mean that it doesn't support binary diffs?
        
               | forrestthewoods wrote:
               | Git LFS is a gross hack that results in pain and
               | suffering. Effectively all games use Perforce because Git
               | and GitLFS suck too much. It's a necessary evil.
        
               | jstimpfle wrote:
               | git clone --bare --depth=1
               | https://github.com/torvalds/linux
               | 
               | Takes 21 seconds on my work laptop, indeed a corporate
               | Windows laptop with antivirus installed. Majority of that
               | time is simply network I/O. The cloned repository is 276
               | MB large.
               | 
               | Actually checking the kernel out takes 90 seconds. This
               | amounts to creating 99195 individual files, totaling 2 GB
               | of data. Expect this to be ~10 times faster on a Linux
               | file system.
               | 
               | So what's your problem?
        
               | kuschku wrote:
               | I've rewritten a python tool in go, 1:1. And that turned
               | something that was so slow that it was basically a toy,
               | into something so fast that it became not just usable,
               | but an essential asset.
               | 
               | Later on I also changed some of the algorithms to faster
               | ones, but their impact was much lower than the language
               | change.
        
               | bonesss wrote:
               | I don't know if people think this way anymore, but Python
               | gained traction to some degree as a prototyping language.
               | Verify the logic and structures, then implement the
               | costly bits or performance sensitive bits in a more
               | expense-to-produce more performant language.
               | 
               | Which is only to say: that rewrite away from python story
               | can also work to show python doing its job. Risk
               | reduction, scaffolding, MVP validation.
        
               | Diggsey wrote:
               | > git was originally implemented as a handful of low
               | level binaries stitched together with shell scripts.
               | 
               | A bunch of low level binaries stitched together with
               | shell scripts is a lot faster than python, so not really
               | sure what the point of this comparison is.
               | 
               | Python is an extremely versatile language, but if what
               | you're doing is computing hashes and diffs, and generally
               | doing entirely CPU-bound work, then it's objectively the
               | wrong tool, unless you can delegate that to a fast,
               | native kernel, in which case you're not actually using
               | Python anymore.
        
               | eru wrote:
               | Well, you can and people do use Python to stitch together
               | low level C code. In that sense, you could go the early
               | git approach, but use Python instead of shell as the
               | glue.
        
               | saghm wrote:
               | Their point was that by offloading the bottlenecks to C,
               | you've essentially conceded that Python isn't fast enough
               | for them, which was the original point made above
        
               | eru wrote:
               | Fair point!
        
               | bmitc wrote:
               | You barely have to try to have Python be noticeably slow.
               | It's the only language I have ever used where I was even
               | aware that a programming language could be slow.
        
               | 20k wrote:
               | Python is by far the slowest programming language, an
               | order of magnitude slower than other languages
               | 
               | One of the reason mercurial lost the dvcs battle is
               | because of its performance - even the mercurial folks
               | admitted that was at least in part because of python
        
               | ragall wrote:
               | > I thought those had died long ago.
               | 
               | No, it's always been true. It's just that at some point
               | people got bored and tired of pointing it out.
        
               | jmalicki wrote:
               | Every time I've rewritten something from Python into
               | Java, Scala, or Rust it has gotten around ~30x faster.
               | Plus, now I can multithread too for even more speedups.
               | 
               | Python is absurdly slow - every method call is a string
               | dict lookup (slots are way underused), everything is all
               | dicts all the time, the bytecode doesn't specialize at
               | all to observed types, it is a uniquely horrible slow
               | language.
               | 
               | I love it, but python is almost _uniquely_ a slow
               | language.
               | 
               | Algorithms matter, but if you have good algorithms, or
               | you're already linear time and just have a ton of data,
               | rewriting something from a single-threaded Python program
               | to a multithreaded rust program I've seen 500x speedups,
               | where the algorithms were not improved at all.
               | 
               | It's the difference between a program running overnight
               | vs. in 30 seconds. And if there are problems, the
               | iteration speed from that is huge.
        
               | byroot wrote:
               | > every method call is a string dict lookup
               | 
               | Doesn't the Python VM have inline caches? [0]
               | 
               | https://en.wikipedia.org/wiki/Inline_caching
        
               | jmalicki wrote:
               | I think that's a new thing from like python 3.12+ or
               | something after I stopped using Python as much.
               | 
               | It didn't used to.
               | 
               | EDIT: python 3.11+: https://peps.python.org/pep-0659/
        
               | eru wrote:
               | > [...], it is a uniquely horrible slow language.
               | 
               | To be fair, Python as implement today is horribly slow.
               | You could leave the language the same but apply all the
               | tricks and heroic efforts they used to make JavaScript
               | fast. The language would be the same, but the
               | implementations would be faster.
               | 
               | Of course, in practice the available implementations are
               | very much part of the language and its ecosystems;
               | especially for a language like Python which is so defined
               | by its dominant implementation of CPython.
        
               | jmalicki wrote:
               | Fair! I guess I didn't mean language as such, but as
               | used.
               | 
               | But a lot of the monkey-patching kind of things and
               | dynamism of python also means a lot of those sorts of
               | things have to be re-checked often for correctness, so it
               | does take a ton of optimizations off the table. (Of
               | course, those are rare corner cases, so compilers like
               | pypy have been able to optimize for the "happy case" and
               | have a slow fall-back path - but pypy had a ton of
               | incompatibility issues and now seems to be dying).
        
               | dtech wrote:
               | Javascript has a lot of the same theoretical dynamism,
               | yet V8 and WebkitCore were able to make it fast
        
               | eru wrote:
               | Yes, with heroic effort. It's really a triumph of
               | compiler / vm engineers over language designers.
        
               | xmcqdpt2 wrote:
               | You don't even need to go all V8, you could just build
               | something like LuaJIT and get most of the way there.
               | LuaJIT is like 10k LOCs and V8 is 3M LOC.
               | 
               | The real reason is that it is a deliberate choice by the
               | CPython project to prefer extensibility and
               | maintainability to performance. The result is that python
               | is a much more hackable language, with much better C
               | interop than V8 or JVM.
        
               | mike_hearn wrote:
               | Python has a JIT compiling version in GraalPy. If you
               | have pure Python it works well. The problem is, a lot of
               | Python code is just callouts to C++ ML libs these days
               | and the Python/C interop boundary just assumes you're
               | using CPython and requires other runtimes to emulate it.
        
               | eru wrote:
               | > Better algorithms win over 'better' programming
               | languages every single time.
               | 
               | That's often true, but not "every single time".
        
               | surajrmal wrote:
               | You must belong to the club of folks who use hashmaps to
               | store 100 objects. It's amazing how much we've
               | brainwashed folks to focus on algorithms and lose sight
               | of how to actually properly optimize code. Being aware of
               | how your code interacts with cache is incredibly
               | important. There are many cases of using slower
               | algorithms to do work faster purely because it's more
               | hardware friendly.
               | 
               | The reason that some more modern tools, like jj, really
               | blow git out of the water in terms of performance is
               | because they make good choices, such as doing a lot of
               | transformations entirely in memory rather than via the
               | filesystem. It's also because it's written in a language
               | that can execute efficiently. Luckily, it's clear that
               | modern tools like jj are heavily inspired by mercurial so
               | we're not doomed to the ux and performance git binds us
               | with.
        
               | inejge wrote:
               | > You must belong to the club of folks who use hashmaps
               | to store 100 objects.
               | 
               | Apparently I belong to the same club -- when I'm writing
               | AWK scripts. (Arrays are hashmaps in a trenchcoat there.)
               | Using hashmaps is not necessarily an indictment you
               | apparently think it is, if the access pattern fits the
               | problem and other constraints are not in play.
               | 
               | > It's amazing how much we've brainwashed folks to focus
               | on algorithms and lose sight of how to actually properly
               | optimize code. Being aware of how your code interacts
               | with cache is incredibly important.
               | 
               | By the time you start worrying about cache locality you
               | have left general algorithmic concerns far behind. Yes,
               | it's important to recognize the problem, but for most
               | programs, most of the time, that kind of problem simply
               | doesn't appear.
               | 
               | It also doesn't pay to be dogmatic about rules, which is
               | probably the core of your complaint, although unstated.
               | You need to know them, and then you need to know when to
               | break them.
        
               | saghm wrote:
               | > You could reimplement it in Python and I doubt it would
               | see any significant slowness
               | 
               | I doubt it _wouldn 't_ be significantly slower. I can't
               | disprove it's possible to do this but it's totally
               | possible for you to prove your claim, so I'd argue that
               | the ball is in your court.
        
               | ezst wrote:
               | > Are we back to "programming language X is slow"
               | assertions? thought those had died long ago.
               | 
               | Yes we are? The slow paths of mercurial have been
               | rewritten in C (and more recently in Rust) and improved
               | the perf story substantially, without taking away from
               | the wild modularity and extensibility hg always had.
        
             | windward wrote:
             | Mercurial can't rebase without an extension, or force push.
             | Are you using a definition of strictly superior that means
             | it has fewer features?
        
               | saagarjha wrote:
               | When I ask for this people like to explain that these are
               | bad features nobody should want.
        
               | qsera wrote:
               | And they would be right,
               | https://news.ycombinator.com/item?id=47766632
        
               | qsera wrote:
               | Mercurial's model is different from Git that these things
               | you list does not make sense there.
               | 
               | Rebase does not make sense in Mercurial because it has
               | the concept of fixed branches. A commit is permanently
               | linked to the branch on which it was made. So you are
               | supposed to use merges.
               | 
               | Same with force-pushing.
        
               | windward wrote:
               | I know. It's an opinion about how to develop that a lot
               | of people hold - a declining proportion, mind you, like
               | Mecurial's declining market share - and it's one that
               | they're able to represent in Git's model, with Git's
               | features. They're even able to do it without exposing me
               | to it. But the same isn't true in reverse. Strictly
               | superior?
               | 
               | Believe me, I tried to have an open mind about it. Then
               | one day I was getting ready to go on a work trip with a
               | half-finished feature on my work laptop, and realised
               | there was simply no in-model way for backing that wip up
               | to the repo. If I lost my laptop, I lost the progress.
               | mercurial-scm fails at SCM.
        
               | qsera wrote:
               | >in-model way for backing that wip up to the repo.
               | 
               | That is because you have this notion of a "clean
               | history", (which IIUC prevented you from making this
               | permanent wip commit) which in reality does not have a
               | lot of use. For most project, "useful history" or "real
               | history" is better than a "clean" history.
               | 
               | That is what mercurial caters to.
        
               | ezst wrote:
               | > one that they're able to represent in Git's model, with
               | Git's features. They're even able to do it without
               | exposing me to it. But the same isn't true in reverse.
               | Strictly superior?
               | 
               | not sure what you mean to say, but for thoroughness'
               | sake, no: git and mercurial concepts are not
               | interchangeable, with git having mostly an inferior
               | model.
               | 
               | To give examples: git has no concept of branching (in the
               | way every VCS but Git uses the term). A branch in git is
               | merely a tag on the tip of a series meant to signify that
               | all ancestors belong to the same lineage. This comes with
               | the implication that this lineage information is totally
               | lost when two branches merge (you can't tell which side
               | of the merge corresponded to which lineage). The ugly and
               | generalised workaround is to abuse commit message (e.g.
               | "merge feat-ABC into main") to store an essential piece
               | of the repository history that the VCS cannot take.
               | 
               | Another example is phasing: mercurial records at commit
               | level whether it was exchanged with others or not. That
               | draws a clean line between the history that's always safe
               | to rewrite, and which that is subject to conflicting
               | merges if the person you shared those commits with also
               | happened to rewrite them on their end.
               | 
               | > Then one day I was getting ready to go on a work trip
               | with a half-finished feature on my work laptop, and
               | realised there was simply no in-model way for backing
               | that wip up to the repo. If I lost my laptop, I lost the
               | progress. mercurial-scm fails at SCM.
               | 
               | Sorry to be blunt, but that's a skill issue: hg is no
               | different than every other VCS in that regard. If you
               | want your WIP changes to leave your laptop, you've got to
               | push them somewhere, just like you would in git.
        
               | ezst wrote:
               | I'd like to fill up some inaccuracies in your response:
               | 
               | - rebasing in Mercurial simply means chopping a subtree
               | off of the history and re-attaching it to a different
               | parent commit. In that sense, rebasing is a very useful
               | and common history-rewriting operation. In fact, it's
               | even simpler and more powerful/versatile than in git,
               | because mercurial couldn't care less if the sub-tree you
               | are rebasing belongs to a branch or not: it's just a DAG.
               | It gets transplanted from A to B. A may or may not be
               | your checked commit, or be the tip of a branch, doesn't
               | matter.
               | 
               | - that mercurial requires a configuration toggle before
               | rebasing can be used (i.e. that the user need to enable
               | the extension explicitly) is a way to encourage
               | interested users to learn their tool, and grow its
               | capabilities together with their knowledge. It's
               | opinionated, it may be too much hand-holding for some,
               | but there is an elegant simplicity in keeping the help
               | pages and autocomplete commands just as complex as the
               | user can take it.
        
           | raincole wrote:
           | This matches my experience 100%. I was about to write a
           | similar comment before I see yours.
        
           | steveklabnik wrote:
           | What is kind of funny here is that you're right locally. At
           | the same time, the larger tech companies (Meta and Google,
           | specifically) ended up building off of hg and not git because
           | (at the time, especially) git cannot scale up to their use
           | cases. So while the git CLI was super fast, and the hg CLI
           | was slow, "performance" means more than just CLI speed.
           | 
           | I was never a fan of hg either, but now I can use jj, and get
           | some of those benefits without actually using it directly.
        
             | smallmancontrov wrote:
             | Right, and I'm glad there are projects serving The
             | Cathedral, but I live in The Bazaar so I'm glad The Bazaar
             | won.
             | 
             | The efforts to sell priest robes to fruit vendors were a
             | little silly, but I'm glad they didn't catch on because if
             | they had caught on they no longer would have been silly.
        
               | dwattttt wrote:
               | GNU Bazaar thoroughly lost, last release was 2016,
               | Canonical retired it last year:
               | https://en.wikipedia.org/wiki/GNU_Bazaar
        
               | hypeatei wrote:
               | GP is taking about this[0] but it's quite hilarious that
               | a VCS exists with that name.
               | 
               | 0: https://en.wikipedia.org/wiki/The_Cathedral_and_the_Ba
               | zaar
        
               | bonzini wrote:
               | It's not a coincidence, it was called like that as a
               | reference to facilitating distributed development.
        
             | landr0id wrote:
             | >At the same time, the larger tech companies (Meta and
             | Google, specifically) ended up building off of hg and not
             | git because (at the time, especially) git cannot scale up
             | to their use cases.
             | 
             | Fun story: I don't really know what Microsoft's server-side
             | infra looked like when they migrated the OS repo to git
             | (which, contrary to the name, contains more than just stuff
             | related to the Windows OS), but after a few years they
             | started to hit some object scaling limitations where the
             | easiest solution was to just freeze the "os" repo and roll
             | everyone over to "os2".
        
               | w0m wrote:
               | didn't msft write an ~entire new file system specifically
               | to scale git to the windows code base?
               | 
               | I have fuzzy memories on reading about it.
        
               | landr0id wrote:
               | They wrote something that allowed them to virtualize Git
               | -- can't remember the name of that. But it basically
               | hydrated files on-demand when accessed in the filesystem.
               | 
               | The problem was I think something to do with like the
               | number of git objects that it was scaling to causing
               | crazy server load or something. I don't remember the
               | technical details, but definitely something involving the
               | scale of git objects.
        
               | jamesfinlayson wrote:
               | I thought Microsoft made a number of improvements to git
               | to allow it work with all of their internal repos.
        
               | kqr wrote:
               | I have heard that the Google monorepo is called google3
               | but I don't know why. Maybe those things are common...
        
               | roca wrote:
               | It's not that.
        
               | vasco wrote:
               | Thanks for explaining!
        
               | ongy wrote:
               | It's the third attempt of building the mono repo.
               | 
               | But not the 3rd mono repo on the same technology to avoid
               | some scaling limit.
        
               | mike_hearn wrote:
               | Probably a lot of Googlers don't know. It's ancient
               | history, was called google3 even in 2006 when I first
               | joined.
               | 
               | google1 = code written by Larry, Sergey and employee
               | number 1 (Craig). A hacky pile of Python scripts, dumped
               | fairly quickly.
               | 
               | google2 = the first properly engineered C++ codebase.
               | Protobufs etc were in google2. But the build system was
               | some jungle of custom Makefiles, or something like that.
               | I never saw it directly.
               | 
               | google3 = the same code as google2 but with a new custom
               | build system that used Python scripts to generate
               | Makefiles. I suppose it required a new repository so they
               | could port everything over in parallel with code being
               | worked on in google2. P4 was apparently not that great at
               | branches and google3 didn't use them. Later the same
               | syntax for the build files was kept but turned into a new
               | languages called Starlark and the Makefile generator went
               | away in favor of Blaze, which directly interpreted them.
               | 
               | At least, that's the story I vaguely recall.
        
               | MASNeo wrote:
               | "roll everyone over to os2"
               | 
               | The IBM crowd may feel vindicated at last.
        
               | miki123211 wrote:
               | So 30 odd years later, MS went from working on OS/2 to
               | working on OS2?
               | 
               | I guess what's old is new again.
        
             | dijit wrote:
             | Small nit: Googles monorepo is based on Perforce.
             | 
             | I think what happened is Google bought a license for source
             | code and customised it.
        
               | steveklabnik wrote:
               | Yes, the server is based on Perforce, called Piper, but
               | the CLI is based on mercurial. So locally you're doing hg
               | and then when you create a CL, it translates it into what
               | p4 needs.
        
               | surajrmal wrote:
               | Depends on what frontend tool you use. You can use
               | either. These days you can also use jj. I'm not sure the
               | backend resembles peforce any longer.
        
               | unmole wrote:
               | > Google bought a license for source code and customised
               | it.
               | 
               | That makes sense because vanilla Perforce is unbearably
               | slow and impossible to scale.
               | 
               | Last I checked, it was bought by Private Equity firms and
               | actual product development had more or less stopped.
        
           | eqvinox wrote:
           | I remember using darcs, but the repos I was using it with
           | were so small as to performance really not mattering...
        
             | riffraff wrote:
             | I remember darcs fondly but even with tiny repos (maybe 5-6
             | people working on it) we hit the "exponential merge"
             | issues.
             | 
             | It worked just fine 99% of the time and then 1% it became
             | completely unusable.
        
             | dented42 wrote:
             | I definitely miss Darcs. I still use it very occasionally,
             | but only with very small repos.
        
           | bmitc wrote:
           | Git is not remotely fast for large projects.
        
             | Cthulhu_ wrote:
             | Define "large"; I've never ran into serious performance
             | issues during the ~15 years I've used Git, which either
             | means the projects I've worked in aren't actually _large_
             | large, or Git is fast enough for most use cases.
        
               | ezst wrote:
               | not OP, and indeed git is fast-enough in many cases, but
               | git not cutting it at Google and Facebook scale, combined
               | with the versatility of mercurial (monkeypatching and
               | extensions system) was the reason why they both invested
               | heavily in mercurial instead of git.
               | 
               | Among the tricks being used was remotefilelogs, which is
               | a way to "hydrate" content locally on-demand, which was
               | mimicked in git many years later with Microsoft's git-
               | vfs. Same goes with binary/large files that git
               | eventually got as git-lfs.
               | 
               | It's funny to think that a big reason for git to be
               | "fast" today is by playing catch-up with mercurial, which
               | carries this "forever stigma" of being slow.
        
           | alwillis wrote:
           | > I'm so glad git won the dvcs war. There was a solid decade
           | where mercurial kept promoting itself as "faster than git".
           | 
           | It wasn't the Mercurial team saying it was faster than Git;
           | that was Facebook after contributing a bunch of patches after
           | testing Mercurial on their very large mono-repo in 2014 [1]:
           | 
           |  _For our repository, enabling Watchman integration has made
           | Mercurial's status command more than 5x faster than Git's
           | status command. Other commands that look for changed files-
           | like diff, update, and commit--also became faster._
           | 
           | In fact they liked Mercurial so much they essentially cloned
           | it to create their own dvcs, Sapling [2]. (An aside: Facebook
           | did all of this because it was taking too long getting new
           | engineers up to speed with Git. Shocker.)
           | 
           | Today, most of the core of Mercurial has been rewritten in
           | Rust; when Facebook did their testing, Mercurial was nearly
           | 100% Python. That's where the "Mercurial is slow" thing came
           | from; launching a large Python 2.x app took a while back in
           | the day.
           | 
           | I was messing with an old Mercurial repo recently... it was
           | like a breath of fresh air. If I can push to GitHub using
           | Mercurial... sign me up.
           | 
           | [1]: https://engineering.fb.com/2014/01/07/core-
           | infra/scaling-mer...
           | 
           | [2]: https://sapling-scm.com/
        
             | Gabrys1 wrote:
             | You can push to GitHub using Sapling. I wish Sapling open
             | source was given more love, as the experience for non-
             | Facebookers is subpar. No bash completion outside the box,
             | no distro packages, no good help pages, random issues
             | interacting with a Git repo...
        
               | withinboredom wrote:
               | Sounds like what my teachers used to say: "a personal
               | problem". Literally nobody outside FB knows what they're
               | missing and until they fix that, literally nobody cares.
        
               | itsdesmond wrote:
               | > Sounds like what my teachers used to say: "a personal
               | problem".
               | 
               | They don't sound like a very good teacher.
        
               | withinboredom wrote:
               | Judging by the amount of adults wandering around thinking
               | their personal problems are everyone else's problem...
               | they were pretty good teachers.
        
               | Ericson2314 wrote:
               | Sapling and JJ can sort it out, the outside world will
               | only care for one of them.
        
               | alwillis wrote:
               | > Sapling and JJ can sort it out, the outside world will
               | only care for one of them.
               | 
               | I was immediately intrigued when I learned that JJ has
               | revsets [1], just like Mercurial.
               | 
               | [1]: https://docs.jj-vcs.dev/latest/revsets/
        
             | smallmancontrov wrote:
             | No, the "hg is fast" marketing claim that retreated to "hg
             | is Big-O fast and you are dumb for caring about constant
             | terms and factors even if they clearly dominate your use
             | case" predates 2014 and the Facebook patches. These talking
             | points were old in 2010. Mercurial was always dog slow and
             | always gaslighting about it.
             | 
             | I'm glad BigCo made tools to serve their needs, but their
             | needs aren't my needs or most peoples' needs.
             | 
             | > Mercurial has been rewritten in Rust
             | 
             | I'm glad they saw the light eventually! Ditto for the rest
             | of the Rust Tooling Renaissance.
        
           | littlecranky67 wrote:
           | I might be the outlier, but am I the only one who doesn't
           | care much about the speed of git? I've been using git since
           | 2011 as my main vcs for personal and professional work as a
           | freelancer contractor. Whenever I "wait" for git, it is
           | either limited by the bandwidth (git clone) or by the amount
           | of commit hooks that I implemented for linting, verification
           | etc. The percentage of time actually spent in git internal
           | execution must be a tiny fraction of my day to day usage.
           | What IS affecting me (and my the teams I work in) is
           | usability and UX experience. I.e. if people would screw up
           | stuff (no matter if in git or mercurial) we spent far more
           | time fixing this - I don't think the impmentation speed would
           | matter here.
           | 
           | The only case I can imagine is when doing a full checkout of
           | a big repo, but even there, there is --depth which is quite
           | practical.
        
             | windward wrote:
             | Isn't it kind of like how you don't care much about the
             | oxygen content of the air around you, but you'd miss it if
             | it was gone? I've done development with Mercurial, simple
             | processes were irritatingly slow, particularly if you stray
             | from the better-supported opinionated path.
        
             | ak217 wrote:
             | I spent a long time educating teams of developers about
             | git's usability quirks. I don't do that as much anymore -
             | partly because the quirks have been worked out, partly
             | because the developers have better guardrails and resources
             | to learn from.
             | 
             | This whole time (the past 15 years) git has been getting
             | faster without most of us noticing, because big companies
             | have been investing in speeding it up. The reason you don't
             | notice or care is that they work on a very different scale.
             | Thousands of users, thousands of PRs per day, millions of
             | CI/CD jobs all hitting the repo.
             | 
             | Now the cycle is repeating again because these numbers are
             | shooting through the roof because of agentic coding.
        
         | calebio wrote:
         | I miss the Phabricator review UI so much.
        
           | montag wrote:
           | Me too. And I'm speaking from using it at Rdio 15 years ago.
           | 
           | Nothing since (Gerrit, Reviewboard, Github, Critique) has
           | measured up...
        
             | Rodeoclash wrote:
             | Thanks for your work on Rdio. I miss it. Were you around
             | when that guy managed to spam plays to get fake albums to
             | the top of the charts?
        
           | sam_bristow wrote:
           | What does Facebook use internally these days. I'm amazed that
           | the state of review tools is still at or behind what we had a
           | decade ago for the most part.
        
             | ivantop wrote:
             | It's still phabricator
        
               | sam_bristow wrote:
               | Any idea if their internal version has improved
               | dramatically since they stopped maintaining the public
               | version?
        
               | kqr wrote:
               | I don't think they ever maintained the public project.
               | Priestly spun off a company to do that.
        
               | xixixao wrote:
               | It has improved massively by 2023 when I left.
        
           | treefry wrote:
           | Same here. Don't understand why Github hasn't supported this
           | until now. I'm tired of reviewing PRs with thousands of lines
           | of changes, which are getting worse nowadays with vibe
           | coding.
        
           | surajrmal wrote:
           | Why not use gerrit? It's pretty similar.
        
             | Redoubts wrote:
             | is it? it's insanely ugly and interactions seem bizarre
        
         | eru wrote:
         | Oh, phabricator. I hated that tool with a passion. It always
         | destroyed my carefully curated PR branch history.
         | 
         | See https://stackoverflow.com/questions/20756320/how-to-
         | prevent-...
        
           | illamint wrote:
           | Good. That's the point.
        
             | eru wrote:
             | The point of what?
             | 
             | I hope they fixed phabricator in the meantime.
        
               | dbetteridge wrote:
               | The point is the main branch reflects the "units" of
               | change, not the individual commits to get there.
               | 
               | One merged pr is a unit of change, at the end of the day
               | the steps you took to produce it aren't relevant to
               | others.
               | 
               | My opinion of course, I'm open to understanding why
               | preserving individual commits is beneficial
        
               | eru wrote:
               | You can get what you want from `git log --first-parent`
               | without having to toss out information.
               | 
               | See how the Linux kernel handles git history to see a
               | good example of non-linear history and where it helps.
               | They use merge commits, ie commits with more than one
               | ancestor, all the time.
        
               | saagarjha wrote:
               | A unit of change is a commit. I have no idea why you'd
               | think a PR is a unit of change.
        
               | zip1234 wrote:
               | Does your org approve specific commits or PRs overall?
        
               | saagarjha wrote:
               | PRs. This is largely why we don't do stacked PRs: they
               | can just be a chain of commits in one PR
        
           | KwanEsq wrote:
           | My understanding was that that was more a function of how arc
           | submitted stuff to Phabricator, rather than solely
           | Phabricator itself. arc at submission time submitted a bunch
           | of different commits as a single Phabricator DREV or whatever
           | the terminology is/was (basically a DREV is the {domain}/D123
           | webpage you'd do a review on). But other tools that submitted
           | commits to Phabricator instances (and maybe even arc itself
           | with the right flag?) submitted each commit as its own
           | separate DREV, so each commit got its own separate /D{N} page
           | and its own review, but all linked together in a stack. And
           | then still landed as separate commits in the actual repo.
           | This is how code submission works with Mozilla's use of
           | Phabricator.
        
             | eru wrote:
             | Well, I didn't care whether it was phabricator or whatever
             | it was using. It was bad.
        
         | nerdypepper wrote:
         | tangled.org supports native stacking with jujutsu, unlike
         | github's implementation, you don't need to create a new branch
         | per change: https://blog.tangled.org/stacking/
        
         | choi0330 wrote:
         | You should definitely try out
         | https://github.com/hokwangchoi/pilegit. It's platform-agnostic
         | and I use for my workflow with Phabricator, Github, Gitlab and
         | Gitea. No learning curves for cross-platform operations!
        
       | siva7 wrote:
       | What a time to be alive. Stacked PRs are now a native feature of
       | Github, even with first-class support for your ai agents.
       | Vibeslop your whole Jira Backlog. Don't fear the merge anymore.
       | Just make any feature branch a long-lived branch by stacking one
       | upon another like bricks.
       | 
       | I'm old enough to have worked with SVN and young enough to have
       | taught engineers to avoid stacking PR in Git. All wisdom has been
       | lost and will probably be rediscovered in another time by another
       | generation.
        
         | jollyllama wrote:
         | Yeah, not sure what this solves that doing multiple PRs from
         | one feature branch into another doesn't solve. But building
         | behavior that into AI agents wouldn't be cool enough, I guess.
        
       | cleverdash wrote:
       | As a solo dev I rarely need stacked PRs, but the underlying
       | problem, keeping PRs small and reviewable, is real even when
       | you're your own reviewer. I've found that forcing myself to break
       | work into small branches before I start (rather than
       | retroactively splitting a giant branch) is the actual discipline.
       | The tooling just makes it less painful when you don't.
       | 
       | Curious whether this changes anything for the AI-assisted
       | workflow. Right now I let Claude Code work on a feature branch
       | and it naturally produces one big diff. Stacked PRs could be
       | interesting if agents learned to split their own work into
       | logical chunks.
        
         | dbbk wrote:
         | If you visit the webpage it gives you integration instructions
         | for agents
        
         | ameliaquining wrote:
         | The tooling for that already exists, since a PR can consist of
         | multiple Git commits and you can look at them separately in the
         | UI. I don't know whether agents are any good at navigating
         | that, but if not, they won't do any better with stacked PRs.
         | Stacked PRs do create some new affordances for the review
         | process, but that seems different from what you're looking for.
        
           | Arainach wrote:
           | Looking at multiple commits is not a good workflow:
           | 
           | * It amounts to doing N code reviews at once rather than a
           | few small reviews which can be done individually
           | 
           | * Github doesn't have any good UI to move between commits or
           | to look at multiple at once. I have to find them, open them
           | in separate tabs, etc.
           | 
           | * Github's overall UX for reviewing changes, quickly seeing a
           | list of all comments, etc. is just awful. Gerrit is miles
           | ahead. Microsoft's internal tooling was better 16 years ago.
           | 
           | * The more commits you have to read through at once the
           | harder it is to keep track of the state of things.
        
             | Hamuko wrote:
             | > _It amounts to doing N code reviews at once rather than a
             | few small reviews which can be done individually_
             | 
             | I truly do not comprehend this view. How is reviewing N
             | commits different from/having to do less reviews reviewing
             | N separate pull requests? It's the same constant.
        
               | Arainach wrote:
               | Small reviews allow moving faster for both the author and
               | reviewer.
               | 
               | A chain of commits:
               | 
               | * Does not go out for review until the author has written
               | all of them
               | 
               | * Cannot be submitted even in partial form until the
               | reviewer has read all of them
               | 
               | Reviewing a chain of commits, as the reviewer I have to
               | review them all. For 10 commits, this means setting aside
               | an hour or whatever - something I will put off until
               | there's a gap in my schedule.
               | 
               | For stacked commits, they can go out for review when each
               | commit is ready. I can review a small CL very quick and
               | will generally do so almost as soon as I get the
               | notification. The author is immediately unblocked. Any
               | feedback I have can be addressed immediately before the
               | author keeps building on top of it.
        
               | tcoff91 wrote:
               | Let's compare 2 approaches to delivering commits A, B, C.
               | 
               | Single PR with commits A, B, C: You must merge all
               | commits or no commits. If you don't approve of all the
               | commits, then none of the commits are approved.
               | 
               | 3 stacked PRs: I approve PR A and B, and request changes
               | on PR C. The developer of this stack is on vacation. We
               | can incrementally deliver value by merging PRs A and B
               | since those particular changes are blocking some other
               | engineer's work, and we can wait until dev is back to fix
               | PR C.
        
               | mike_hearn wrote:
               | _> You must merge all commits or no commits_
               | 
               | This seems to be the root of the problem. Nothing stops a
               | reviewer merging some commits of a PR, except a desire to
               | avoid the git CLI tooling (or your IDE's support,
               | or....). The central model used in a lot of companies
               | requires the reviewee to do the final merge, but this has
               | never been how git was meant to be used and it doesn't
               | have to be used that way. The reviewer can also do
               | merges. Merge (of whichever commits) = approval, in that
               | model.
        
               | tcoff91 wrote:
               | Yes, the root of the problem is the workflow of the
               | company being centered around GitHub instead of Git
               | itself.
               | 
               | This feature helps improve GitHub so it's useful for
               | companies that do this this way.
               | 
               | At our company, only admin users can actually directly
               | git push to main/master. Everything else HAS to be merged
               | via github and pass through the merge queue.
               | 
               | So this stacked PRs feature will be very helpful for us.
        
             | tcoff91 wrote:
             | It's crazy that you're getting downvoted for this take.
             | 
             | This isn't reddit people. You're not supposed to downvote
             | just because you disagree. Downvotes are for people who are
             | being assholes, spamming, etc...
             | 
             | If you disagree with a take, reply with a rebuttal. Don't
             | just click downvote.
        
               | steveklabnik wrote:
               | Historically, hn etiquette is that it's fine to downvote
               | for disagreement. This came from pg himself.
               | 
               | That said, while he hasn't posted here for a long time,
               | this is still in the guidelines:
               | 
               | > Please don't post comments saying that HN is turning
               | into Reddit. It's a semi-noob illusion, as old as the
               | hills.
               | 
               | https://news.ycombinator.com/newsguidelines.html
        
               | tcoff91 wrote:
               | Well, I stand corrected.
        
         | adamwk wrote:
         | Maybe there's a git trick I don't know, but I've found making
         | small branches off each other painful. I run into trouble when
         | I update an earlier branch and all the dependent branches get
         | out of sync with it. When those earlier branches get rebased
         | into master it becomes a pain to update my in-progress branches
         | as well
        
           | flyingcircus3 wrote:
           | Stacking branches for any extended period of time is
           | definitely a poor mixing of the concepts of branches and
           | commits. If you have a set of changes you need to keep in
           | order, but you also need to maintain multiple silos where you
           | can cleanly allow the code to diverge, that divergence
           | constitutes the failure of your efforts to keep the changes
           | in order.
           | 
           | Until you can make it effortless, maintaining a substantial
           | commit structure and constantly rebasing to add changes to
           | the proper commit quickly turns into more effort than just
           | waiting to the end and manually editing a monster diff into
           | multiple sensible commits. But we take the challenge and tell
           | ourselves we can do better if we're proactive.
        
             | adamwk wrote:
             | This is what I understood as well, but it sounded like GP
             | had success doing it; so I was curious if there was a trick
             | I didn't know about
        
               | flyingcircus3 wrote:
               | I take from GP that they try to make their branches
               | small, and keep the cycle of development->review->merging
               | small, so that the problem stacked PRs seeks to solve
               | doesn't materialize in the first place.
               | 
               | Stacked PRs in my experience has primarily been a request
               | to merge in a particular order. If you're the only
               | merger, as in GP's case, there's no need to request this
               | of yourself.
        
               | skydhash wrote:
               | Whenever I send a big diff. I spend some time annotating
               | with comment first to helps the reviewer. A good summary
               | of the changes in the description, the I annotate the
               | diff of the PR, explaining approaches, the design of a
               | specific changes, tricky part of the code,
               | boilerplate,... Trying to guess the context is where the
               | review bottleneck is, so I present it alongside the code.
        
           | leleat wrote:
           | If I understood you correctly, you want to propagate changes
           | in a branch to other branches that depend on it? Then
           | --update-refs is for you[1]. That way, you only need to
           | update the "latest" branch.
           | 
           | [1] https://andrewlock.net/working-with-stacked-branches-in-
           | git-...
        
           | KptMarchewa wrote:
           | I understand that's what the feature is trying to solve.
        
         | steveklabnik wrote:
         | I have had a lot of success with Claude and jj, telling it to
         | take the stack of work it's done and build me a new stack on
         | top of trunk that's centered around ease of reviewing.
        
           | 4b11b4 wrote:
           | I once threatened Claude have to learn JJ after doing some
           | crazy git rebase gymnastics. The problem is clearly that I
           | don't know jj
        
             | steveklabnik wrote:
             | It sometimes will hallucinate older CLI options, because jj
             | has changed at various times, but it's pretty decent with
             | it at this point. The harder part is that a lot of plugins
             | hardcode git into them.
        
         | jillesvangurp wrote:
         | It's easier to pile on a lot of changes with AI assisted
         | workflows. And reviewing all that is definitely a challenge
         | just because of the volume of changes. I've actually stopped
         | pretending I can review everything in detail because it makes
         | me a bottleneck in the process. Anything that makes reviewing
         | easier is welcome.
         | 
         | To me, stacked PRs seems overly complicated. It seems to boil
         | down to propagating git rebases through stacks of
         | interdependent branches.
         | 
         | I'm fine with that as long as I don't have to deal with people
         | force pushing changes and routinely rewriting upstream history.
         | It's something you probably should do in your own private fork
         | of a repository that you aren't sharing with anyone. Or if you
         | are, you need to communicate clearly. But if the goal is to
         | produce a stack of PRs that in the end merge cleanly, stacked
         | PRs might be a good thing.
         | 
         | As soon as you have multiple collaborators working on a feature
         | branch force pushing can become a problem and you need to
         | impose some rules. Because otherwise you might end up breaking
         | people's local branches and create work for them. The core
         | issue here is that in many teams, people don't actually fork
         | the main repository and have push access to the main
         | repository. Which emulates the central repository model that
         | people were used to twenty years ago. Having push access is not
         | normal in most OSS projects. I've actually gotten the request
         | from some rookie developers that apparently don't get forking
         | to "please give me access to your repository" on some of my OSS
         | projects.
         | 
         | A proper pull request (whether stacked or not) to an OSS
         | project needs to be clean. If you want to work on some feature
         | for weeks you of course need mechanisms to stay on top of up
         | stream changes. OSS maintainers will probably reject anything
         | that looks overly messy to merge. That's their job.
        
           | recursivegirth wrote:
           | I spend more time in planning and steering the AI
           | implementation than I do on reviewing it's outputs.
           | 
           | I do the obvious checks like tests and spin up a dev instance
           | to make sure the feature works like I want it too, but very
           | rarely am I reviewing every line of code these days.
        
       | jamietanna wrote:
       | Very much looking forward to getting this on Renovate - we
       | require squash-merge via Merge Queue (with no per-PR override
       | available in GitHub, despite asking) and so when I've got
       | multiple changes, it's a lot of wrangling and rebasing
       | 
       | If this works as smoothly as it sounds, that'll significantly
       | reduce the overhead!
        
       | sailorganymede wrote:
       | Thank goodness. It was a pain to do this manually
        
       | fweimer wrote:
       | I find this puzzling. It does not seem to allow to stack PRs on
       | top of other people's PRs?
       | 
       | There is already an option to enable review comments on
       | individual commits (see the API endpoint here:
       | https://docs.github.com/en/rest/guides/working-with-comments...).
       | Self-stacking PRs seem redundant.
        
         | CharlieDigital wrote:
         | This API leaves a comment, on the commit; not quite the same
         | thing since in GH, several operations are tied to PRs and not
         | to commits.
        
         | jannes wrote:
         | Still feels like an alpha version right now. I'm sure they will
         | add it later.
         | 
         | Graphite (which they seem to be inspired by) has frozen
         | branches exactly for that use case:
         | 
         | https://graphite.com/blog/introducing-frozen-branches
        
       | bob1029 wrote:
       | I feel like we already have enough abstractions in this space.
       | Having _any constraints at all_ in your tools is actually a good
       | thing. PRs on top of ordinary git was a good step. This seems
       | like one too many.
        
         | Yokohiii wrote:
         | I honestly don't even get the PR addiction. Github has shaped
         | devs workflows way too much. My best experience with git was
         | when I realized that I can just have an blatantly simple
         | workflow and explain it even to the junior-est dev in a few
         | minutes. The reliance on github is somehow telling me that
         | people stopped thinking about things they can actually control.
        
       | TZubiri wrote:
       | github.github.com? Not the first time github does something
       | highly weird with their domains (like publishing docs from a
       | subdomain of their public github pages service)
       | 
       | I think they have a culture of circumventing 'official' channels
       | and whoever is in charge of a thing is whoever publishes the
       | thing.
       | 
       | I think it's a great way to train users to get phished by github
       | impostors, if tomorrow we see an official download from
       | official.github.com or even official-downloads.github.io, sure
       | it's phishy, but it's also something that github does.
       | 
       | It's also 100% the kind of issues that, if it happens, the user
       | will be blamed.
       | 
       | I would recommend github to stop doing this stuff and have a
       | centralized domain to publish official communications and
       | downloads from. Github.github.com? Come on, get serious.
       | 
       | TL;DR: DO NOT DOWNLOAD ANYTHING from this site, (especially not
       | npm/npx/pnpm/bun/npjndsa) stuff. It's a Github Pages site, just
       | on a subdomain that looks official, theoretically it might be no
       | different from an attacker to obtain access to
       | dksabdkshab.github.com than github.github.com. Even if it is
       | official, would you trust the intern or whoever managed to get a
       | subdomain to not get supply chained? github.github.com just think
       | about it.
        
         | varun_ch wrote:
         | https://news.ycombinator.com/item?id=47614038
        
           | TZubiri wrote:
           | in github's defense. This is a bit more nuanced, less
           | objectively wrong domain posture issue. It will only matter
           | if one security mechanism (subdomain control) fails.
           | 
           | The quoted microsoft examples are way worse. I see this with
           | outbound email systems a lot, which is especially dangerous
           | because email is a major surface of attack.
        
       | baq wrote:
       | Just when I've gotten used to having 3 or more PRs in parallel
       | with a local octopus working tree with jj. Maybe my colleagues
       | will see the light at least.
        
       | enraged_camel wrote:
       | The biggest challenge for us are PRs that need to be coordinated
       | across multiple repos. API + client for example. It doesn't sound
       | like stacked PRs solve that problem, right? Description
       | specifically states single repo.
        
         | masklinn wrote:
         | They do not no. Afaik GitHub has little to nothing that is
         | cross repository.
        
       | jenadine wrote:
       | I might be missing something, but what I need is not "stacked PR"
       | but a proper UI and interface to manage single commit:
       | 
       | - merge some commits independently when partial work is ready.
       | 
       | - mark some commit as reviewed.
       | 
       | - UI to do interactive rebase and and squash and edit individual
       | commits. (I can do that well from the command line, but not when
       | using the GitHub interface, and somehow not everyone from my team
       | is familiar with that)
       | 
       | - ability to attach a comment to a specific commit, or to the
       | commit message.
       | 
       | - better way to visualize what change over time in each forced
       | push/revision (diff of diff)
       | 
       | Git itself already has the concept of commit. Why put this
       | "stacked PR" abstraction on top of it?
       | 
       | Or is there a difference I don't see?
        
         | tcoff91 wrote:
         | It's basically trying to bring the stacked diff workflow
         | pioneered by Phabricator to GitHub.
         | 
         | The idea is that it allows you to better handle working on top
         | of stuff that's not merged yet, and makes it easier for
         | reviewers to review pieces of a larger stack of work
         | independently.
         | 
         | It's really useful in larger corporate environments.
         | 
         | I've used stacked PRs when doing things like upgrading react-
         | native in a monorepo. It required a massive amount of changes,
         | and would be really hard to review as a single pull request. It
         | has to be landed all at once, it's all or nothing. But being
         | able to review it as smaller independent PRs is helpful.
         | 
         | Stacking PRs is also useful even when you don't need to merge
         | the entire stack at once.
        
           | js2 wrote:
           | > stacked diff workflow pioneered by Phabricator
           | 
           | Ahem, pioneered by gerrit. But actually, I'm almost certain
           | even that wasn't original art. I think gerrit just brought it
           | to git.
           | 
           | https://www.gerritcodereview.com/about.html
        
             | sunshowers wrote:
             | To my knowledge, stacked diffs were first done in the Linux
             | kernel as stacks of patches sent over email. From there
             | they spread to Google and Facebook. (Source: I worked on
             | Facebook's source control team from 2012-2018 and did a lot
             | of work to enable stacked diffs there.)
        
               | js2 wrote:
               | Right, I was thinking from a web-based UI. The "pull
               | request" term is from git (AFAIK), but git itself was
               | built to accommodate the earlier concept of mailing
               | patches around. (Source: I've been using version control
               | since RCS/SCCS days and contributed here and there to git
               | in its infancy. Also an early user/contributor to
               | Gerrit.)
        
               | Izkata wrote:
               | > The "pull request" term is from git (AFAIK)
               | 
               | Possibly from github. It got popularized there at least,
               | encouraging forking code, and is why so many people say
               | "pull request" when they mean "merge request".
        
               | js2 wrote:
               | GitHub took the "pull request" terminology from Git. A
               | kernel developer (say) would have a bunch of changes
               | ready in their local Git server and would request a pull
               | from Linus, hence a pull request. There's literally a
               | command for it:
               | 
               | https://git-scm.com/docs/git-request-pull
               | 
               | The command is so old it's still written in shell:
               | 
               | https://github.com/git/git/blob/master/git-request-
               | pull.sh
               | 
               | It was first added July 27, 2005:
               | 
               | https://github.com/git/git/commit/ab421d2c7886341c246544b
               | c8d...
               | 
               | https://lore.kernel.org/git/20050726073036.GJ6098@mythrya
               | n2....
               | 
               | But even then, it simply codified existing terminology.
               | 
               | Ah, someone else did the research, so minimally BitKeeper
               | had the "pull" command first and the term "pull request"
               | falls naturally from that:
               | 
               | https://rdnlsmith.com/posts/2023/004/pull-request-
               | origins/
        
               | p-e-w wrote:
               | At some point, a derivative idea becomes so different
               | from the original one that it's a novel idea in essence.
               | Just like SMS is ultimately a derivative of cuneiform
               | tablets, and yet it isn't in any meaningful sense.
        
               | monster_truck wrote:
               | Imagine gettting a cuneiform tablet by courier telling
               | you that you have unpaid parking tickets in a state
               | you've never driven in
        
               | sunshowers wrote:
               | I don't think mailing stacks of patches is that
               | different? As someone who built this stuff it was pretty
               | obvious to me that web-based patch stack management was a
               | relatively small evolution over mailing lists. Tools like
               | patchwork bridged the gap initially, and we were quite
               | familiar with them.
        
               | hokumguru wrote:
               | Congrats and thank you. You helped build one of the best
               | devex experiences I've ever had the pleasure of working
               | with :)
        
             | pabs3 wrote:
             | Gerrit was forked from Rietveld. Not sure if Rietveld or
             | Gerrit are better though.
             | 
             | https://github.com/rietveld-codereview/rietveld
             | https://en.wikipedia.org/wiki/Rietveld_(software)
             | https://codereview.appspot.com/
        
           | eptcyka wrote:
           | What if main/master moves in between reviews?
        
             | tcoff91 wrote:
             | Rebase the stack onto main.
        
             | jrochkind1 wrote:
             | Before this feature when you were doing it manually, it was
             | a huge problem. One of the points of this feature, is it
             | automates rebasing the whole stack.
        
             | mh2266 wrote:
             | you just rebase it? what's the big deal?
             | 
             | I don't use Github but I do work at one of the companies
             | that popularized this workflows and it is extremely not a
             | big deal. Pull, rebase, resolve conflicts if necessary,
             | resubmit.
        
             | adregan wrote:
             | You head to the farthest branch in the chain, fetch the
             | latest main, and run `git rebase --update-refs main` (I
             | prefer interactive mode myself) and then force push all of
             | the branches from start to the end.
             | 
             | 1: https://git-scm.com/docs/git-rebase#Documentation/git-
             | rebase...
        
           | jrochkind1 wrote:
           | I'm not in a large corporate environment, but that also means
           | we're not always a well oiled machine, and sometimes i am
           | writing faster than the reviewer can review for a period of
           | time -- and i really need the stacking then too.
        
           | ttoinou wrote:
           | Even with one developer on a repo this sounds like useful
        
         | xixixao wrote:
         | Workflows can vary, but what I like:
         | 
         | PR/MR is an "atomic" change (ideally the smallest change that
         | can be landed separately - smallest makes it easier to review,
         | bisect and revert)
         | 
         | Individual commits (or what "versions" are in Phabricator) are
         | used for the evolution of the PR/MR to achieve that change.
         | 
         | But really I have 2 use cases for the commits:
         | 
         | 1. the PR/MR is still too big, so I split it into individual
         | commits (I know they will land together)
         | 
         | 2. I keep the history of the evolution of the PR/MR in the
         | commits ("changed foo to bar cause its a better approach")
        
         | mikeocool wrote:
         | Constantly rewriting git history with squashes, rebases, manual
         | changes, and force pushes has always seemed like leaving a
         | loaded gun pointed at your foot to me.
         | 
         | Especially since you get all of the same advantages with plain
         | old stream on consciousness commits and merges using:
         | 
         | git merge --no-ff
         | 
         | git log --first-parent
         | 
         | git bisect --first-parent
        
           | OJFord wrote:
           | Until someone merges master into their feature branch rather
           | than rebasing it. (And then that branch later gets merged.)
        
             | sheept wrote:
             | This shouldn't be a problem if you stick to commits and
             | merges. --first-parent will skip past commits, including
             | merge commits, in merged branches.
        
               | OJFord wrote:
               | Fair - but not if it's not their feature branch but their
               | local master; they pull & merge the remote changes and
               | then push the result.
        
           | OptionOfT wrote:
           | I agree. PR merges for me are bisect points. That's when
           | changes are introduced. Individual commits don't even always
           | build.
           | 
           | And I don't rebase or squash because I need provenance in my
           | job.
        
           | MrJohz wrote:
           | I find rebases are only a footgun because the standard git
           | cli is so bad at representing them - things like --force
           | being easier to write than --force-with-lease, there being no
           | way to easily absorb quick fixes into existing commits,
           | interdiffs not really being possible without guesswork,
           | rebases halting the entire workflow if they don't succeed,
           | etc.
           | 
           | I've switched over pretty much entirely to Jujutsu (or JJ),
           | which is an alternative VCS that can use Git as its backend
           | so it's still compatible with Github and other git repos. My
           | colleagues can all use git, and I can use JJ without them
           | noticing or needing to care. JJ has merges, and I still use
           | them when I merge a set of changes into the main branch once
           | I've finished working on it, but it also makes rebases really
           | simple and eliminates most of the footguns. So while I'm
           | working on my branch, I can iteratively make a change, and
           | then squash it into the commit I'm working on. If I refactor
           | something, I can split the refactor out so it's in a separate
           | commit and therefore easiest to review and test. When I get
           | review feedback, I can squash it directly into the relevant
           | commit rather than create a new commit for it, which means
           | git blame tends to be much more accurate and helpful - the
           | commit I see in the git blame readout is always the commit
           | that did the change I'm interested in, rather than maybe the
           | commit that was fixing some minor review details, or the
           | commit that had some typo in it that was fixed in a later
           | commit after review but that relationship isn't clear any
           | more.
           | 
           | And while I'm working on a branch, I still have access to the
           | full history of each commit and how it's changed over time,
           | so I can easily make a change and then undo it, or see how a
           | particular commit has evolved and maybe restore a previous
           | state. It's just that the end result that gets merged doesn't
           | contain all those details once they're no longer relevant.
        
             | muti wrote:
             | +1 on this, I also switched to jj when working with any git
             | repo.
             | 
             | What's funny is how much better I understand git now, and
             | despite using jj full time, I have been explaining concepts
             | like rebasing, squashing, and stacked PRs to colleagues who
             | exclusively use git tooling
        
             | skydhash wrote:
             | The magic of the git cli is that it gives you control.
             | Meaning whatever you want to do can be done. But it only
             | gives you the raw tools. You'll need to craft your own
             | workflow on top of that. Everyone's workflow is different.
             | 
             | > So while I'm working on my branch, I can iteratively make
             | a[...]which means git blame tends to be much more accurate
             | and helpful
             | 
             | Everything here I can do easily with Magit with a few
             | keystroke. And magit sits directly on top of git, just with
             | interactivity. Which means if I wanted to I could write a
             | few scripts with fzf (to helps with selection) and they
             | would be quite short.
             | 
             | > And while I'm working on a branch, I still have access to
             | the full history of each commit...
             | 
             | Not sure why I would want the history for a specific
             | commit. But there's the reflog in git which is the ultimate
             | undo tool. My transient workspace is only a few branches (a
             | single one in most cases). And that's the few commits I
             | worry about. Rebase and Revert has always been all I needed
             | to alter them.
        
               | rstuart4133 wrote:
               | > But there's the reflog in git which is the ultimate
               | undo tool.
               | 
               | That one sentence outs you as someone who isn't familiar
               | with JJ.
               | 
               | Here is something to ponder. Despite claims to the
               | contrary, there are many git commands that can destroy
               | work, like `git reset --hard`. The reflog won't save you.
               | However there is literally no JJ command that can't be
               | undone. So no JJ command will destroy your work
               | irretrievably.
        
               | skydhash wrote:
               | I've just tested that exact command and the reflog is
               | storing the changes. It's different from the log command
               | which displays the commit tree for the specified branch.
               | The reflog stores information about operations that
               | updates branches and other references (rebase, reset,
               | amend, commit,...). So I can revert the reset, or a pull.
        
               | rstuart4133 wrote:
               | `git reset --hard` destroys uncommitted changes. There is
               | no git command to recover those files. JJ has a similar
               | command of course, but it saves the files to a hidden
               | commit before changing them.
        
             | saagarjha wrote:
             | --force-with-lease is useless if you ever use tools that
             | refresh git status.
        
         | d0mine wrote:
         | You are describing gerrit.
         | 
         | https://www.gerritcodereview.com/
        
         | ahmadyan wrote:
         | the best implementation i've worked with was SuperSmartLog
         | (SSL) at Meta, which was open-sourced at interactive smartlog
         | (https://sapling-scm.com/docs/addons/isl/). There are also
         | extension for it in VSCode, etc.
         | 
         | Surprisingly it never gained the adoption it deserved.
        
         | icy wrote:
         | We've got this over on Tangled. :) https://tangled.org
        
         | rtpg wrote:
         | yeah interdiffing and being able to cherrypick in a review just
         | there and getting it done is nice.
         | 
         | Perhaps a future iteration of this feature will at least allow
         | us to do something like merge just steps of it if they can be
         | reordered.
        
         | trashburger wrote:
         | You want something like Gerrit.
        
       | robertwt7 wrote:
       | There's a startup callled Graphite dedicated to stacked PRs. I
       | have been using them for a while now I always wonder why github
       | doesn't implement something similar to this. I probaly will try
       | and switch to GitHub to see if it works flawlessly
        
         | ghthor wrote:
         | Yep, very happy with graphite at work.
        
           | heeton wrote:
           | Same, our team has been on it for a year and it's very good.
        
         | acjohnson55 wrote:
         | They recently got bought by Cursor.
        
       | K0IN wrote:
       | Wow i really need this, we had a refactor our monorepo (dotnet 8
       | -> 10 and angular 19 -> 21) which resulted in many small changes
       | (like refactoring to signals, moving components to standalone)
       | and we try to group changes into commits by what was fixed, but
       | this had the downside of some commits beeing huge while others
       | small, this would have helped us alot grouping commits together
       | and having cleaner commit messages.
        
       | DesiLurker wrote:
       | what happened to the old gerrit reviews, I loved its handling on
       | incremental patchsets. github is primitive by comparison.
        
       | ghighi7878 wrote:
       | What's difference between stacked PRs and merge trains in gitlab?
        
         | masklinn wrote:
         | Merge trains are an integration method. In GitHub that's called
         | merge queues.
         | 
         | Stacked PRs are a development method, for managing changes
         | which are separate but dependent on one another (stacked).
         | 
         | The two are orthogonal they can be used together or
         | independently (or not at all).
        
           | ghighi7878 wrote:
           | Ahh so stacked diffs? https://docs.gitlab.com/user/project/me
           | rge_requests/stacked_...
        
             | IshKebab wrote:
             | Yes, except with a proper UI. Also while you could do this
             | on GitHub before in the same way that that Gitlab feature
             | works, it didn't work cross-repo so in practice it wasn't
             | an option for most open source code.
             | 
             | I can't remember if Gitlab has the same limitations but I
             | do remember trying to use Gitlab's stacked diffs and
             | finding them to not work very well. Can't remember why tbh.
        
       | inerte wrote:
       | Looks interesting, but it seems you need to know the final shape
       | of the stack before you start creating Pull Requests. So it's
       | useful if you create Pull Request A, then immediately start
       | working on something that builds on top of A, create a Pull
       | Request for that (while A is still a PR), then you can do A->B->C
       | 
       | Here's something that would be useful: To break down an already
       | big PR into multiples that make up a stack. So people can create
       | a stack and add layers, but somehow re-order them (including
       | adding something new at the first position).
        
         | tcoff91 wrote:
         | It looks like in the UI if you base a PR on another branch you
         | can just check a box to make it a stack. So I don't think you
         | have to know the full shape of the stack in advance unless
         | you're using the cli.
         | 
         | I use jj to stack branches so i'll just be using the UI to do
         | github pr stacks.
        
         | mattstir wrote:
         | It appears the CLI is only half-baked so far. Given how many
         | things they've borrowed from Graphite (a tool which adds this
         | type of workflow), it should only be a matter of time until
         | they add a `split` command. Graphite lets you split a large set
         | of changes by commit or by hunk which is very handy.
        
       | akersten wrote:
       | Does it fix the current UX issue with Squash & Merge?
       | 
       | Right now I manually do "stacked PRs" like this:
       | 
       | main <- PR A <- PR B (PR B's merge target branch is PR A) <- PR
       | C, etc.
       | 
       | If PR B merges first, PR A can merge to main no problems. If PR A
       | merges to main first, fixing PR B is a nightmare. The GitHub UI
       | automatically changes the "target" branch of the PR to main, but
       | instantly conflicts spawn from nowhere. Try to rebase it and
       | you're going to be manually looking at every non-conflicting
       | change that ever happened on that branch, for no apparent reason
       | (yes, the reason is that PR A merging to main created a new merge
       | commit at the head of main, and git just can't handle that or
       | whatever).
       | 
       | So I don't really need a new UI for this, I need the tool to Just
       | Work in a way that makes sense to anyone who wasn't Linus in 1998
       | when the gospel of rebase was delivered from On High to us
       | unwashed Gentry through his fingertips..
        
         | xixixao wrote:
         | Conflicts spawn most likely because PR A was squashed, and once
         | you squash Git doesn't know that PR B's ancestors commits are
         | the same thing as the squashed commit on main.
         | 
         | No idea if this feature fixes this.
         | 
         | Edit: Hopefully `gh stack sync` does the rebasing correctly
         | (rebase --onto with the PR A's last commit as base)
        
           | akersten wrote:
           | > Conflicts spawn most likely because PR A was squashed, and
           | once you squash Git doesn't know that PR B's ancestors
           | commits are the same thing as the squashed commit on main.
           | 
           | Yeah, and I _kind of_ see how git gets confused because the
           | squashed commits essentially disappear. But I don 't know why
           | the rebase can't be smart when it sees that file content
           | between the eventual destination commit (the squash) is the
           | same as the tip of the branch (instead of rebasing one commit
           | at a time).
        
             | skydhash wrote:
             | Because at first your have this                 main <- PR
             | A <- PR B
             | 
             | Then you'll have                 main, squashed A
             | \            \-> PR A -> PR B
             | 
             | The tip of B is the list of changes of both A and B, while
             | the tip of main is now the squashed version of the changes
             | of A. Unless a branch tracks the end of A in the PR B, It
             | looks like more you want to apply A and B on top of A
             | again.
             | 
             | A quick analogy to math                 main is X       A
             | is 3       B is 5
             | 
             | Before you have X + 3 + 5 which was equivalent to X + 8,
             | but then when you squash A on on X, it looks like (X + 3) +
             | (3 + 5) from `main`'s point of view, while from B, it
             | should be X + (3 + 5). So you need to rebase B to remove
             | its 3 so that it can be (X + 3) + 5.
             | 
             | Branches only store the commits at the top. The rest is
             | found using the parent metadata in each commits (a linked
             | list. Squashing A does not remove its commits. It creates a
             | new one, and the tip of `main` as its parent and set the
             | new commit as the tip of `main`. But the list of commits in
             | B still refer to the old tip of `main` as their ancestor
             | and still includes the old commits of A. Which is why you
             | can't merge the PR because it would have applies the
             | commits of A twice.
        
         | gregoryl wrote:
         | If I'm following correctly, the conflicts arise from other
         | commits made to main already - you've implicitly caught branch
         | A up to main, and now you need catch branch B up to main, for a
         | clean merge.
         | 
         | I don't see how there is any other way to achieve this cleanly,
         | it's not a git thing, it's a logic thing right?
        
           | Smaug123 wrote:
           | No, it's a Git thing arising from squash commits. There are
           | workflows to make it work (I've linked the cleanest one I
           | know that works without force pushing), but ultimately
           | they're basically all hacks.
           | https://www.patrickstevens.co.uk/posts/2023-10-18-squash-
           | sta...
        
             | heldrida wrote:
             | This is actually a reasonable workflow. Although requires
             | some preparation. I'll try it out!
        
               | mckn1ght wrote:
               | Yep that's how I do it if I have to deal with stacked
               | PRs. I also just never use rebase once anything has
               | happened in a PR review that incurs historical state,
               | like reviews or other people checking out the branch
               | (that I know of, anyways). I'll rebase while it's local
               | to keep my branch histories tidy, but I'll merge from
               | upstream once shared things are happening. There are a
               | bunch of tools out there for merging/rebasing entire
               | branch stacks, I use https://github.com/dashed/git-chain.
        
           | akersten wrote:
           | I've no issue with the logic of needing to update feature
           | branches before merging, that's pretty bread and butter. The
           | specific issue with this workflow is that the "update branch"
           | button for PR B is grayed out because there are these
           | hallucinated conflicts due to the new squash commit.
           | 
           | The update branch button works normally when I don't stack
           | the PRs, so I don't know. It just feels like a half baked
           | feature that GitHub automatically changes the PR target
           | branch in this scenario but doesn't automatically do whatever
           | it takes for a 'git merge origin/main' to work.
        
             | skydhash wrote:
             | > the "update branch" button for PR B is grayed out because
             | there are these hallucinated conflicts due to the new
             | squash commit
             | 
             | Those are not hallucinated. PR B still contains all the old
             | commits of A which means merging would apply them twice.
             | The changes in PR B are computed according to the oldest
             | commits belonging to PR B and main which is the parent of
             | squashed A. That would essentially means applying A twice
             | which is not good.
             | 
             | As for updating PR B, PR B doesn't know where PR A (that
             | are also in PR B) ends because PR A is not in main.
             | Squashed A is a new commit and its diff corresponds to the
             | diff of a range of commits in PR B (the old commits of PR
             | A), not the whole B. There's a lot of metadata you'd need
             | to store to be able to update PR B.
        
               | akersten wrote:
               | I guess to me, I'm looking at it from the perspective of
               | diffing the repo between the squashed commit on main and
               | the tip of the incoming PR. If there are merge conflicts
               | during the rebase in files that _don 't appear in that
               | diff_, I consider that a hallucination, because those
               | changes _must_ already in the target branch and no matter
               | what happened to those files along the way to get there,
               | it will always be a waste of my time to see them during
               | an interactive rebase.
               | 
               | I don't think we need to store any additional metadata to
               | make the rebase just slightly more smarter and able to
               | skip over the "obvious" commits in this way, but I'm also
               | just a code monkey, so I'm sure there are Reasons.
        
               | skydhash wrote:
               | You're looking at it from the perspective of a human
               | reasoning. But a computer is a simple machine (what it
               | can do, not how it does it). What seems obvious to you
               | could be a complicated algorithm.
               | 
               | Git store all its information as a directed acyclic graph
               | (a tree) of commits. The leaves of that tree have names,
               | and are what we called branches. Each commit points to a
               | tree (also a tree data structure) where the nodes are
               | blobs (files) and sub trees. But that tree only stores
               | the files that has been changed since the last commit.
               | Git does not store diffs. Diffs are computed as needed.
               | 
               | This why the common ancestor commit is important. From
               | there, a version of the working directory is computed for
               | each branch (main-with-squashed-A and PR B). Files that
               | have not been changed since PR A are ok, but everything
               | else will be different, especially if you've modified the
               | same lines.
               | 
               | Squashed A is a brand new commit with a new tree that PR
               | B does not know about. You need to recompute PR B on top
               | of Squashed A, (which will create new commits for PR B).
        
         | pastel8739 wrote:
         | I agree that this is annoying and unintuitive. But I don't see
         | the simplest solution here, so:
         | 
         | All you need to do is pull main, then do an interactive rebase
         | with the next branch in your stack with 'git rebase -i main',
         | then drop all the commits that are from the branch you just
         | merged.
        
           | adregan wrote:
           | I typically prefix my commit messages with the ticket number
           | to make it easier to spot the commits to drop.
        
           | claytonjy wrote:
           | This is what i often do, but i have never been able to get
           | many coworkers onboard. In my experience I'd say less than 5%
           | of all software folk i've worked with are willing to do an
           | interactive rebase; everyone else finds it too scary
        
         | contravariant wrote:
         | Oh that's annoying, seems to me there wouldn't have been an
         | issue if you just merged B into A after merging A into main, or
         | the other way around but that already works fine as you pointed
         | out.
         | 
         | I mean if you've got a feature set to merge into dev, and it
         | suddenly merges into main after someone merged dev into main
         | then that's very annoying.
        
         | sameenkarim wrote:
         | Yes, we handle this both in the CLI and server using git rebase
         | --onto                 git rebase --onto
         | <new_commit_sha_generated_by_squash>
         | <original_commit_sha_from_tip_of_merged_branch> <branch_name>
         | 
         | So for ex in this scenario:                 PR1: main <- A, B
         | (branch1)       PR2: main <- A, B, C, D        (branch2)
         | PR3: main <- A, B, C, D, E, F  (branch3)
         | 
         | When PR 1 and 2 are squash merged, main now looks like:
         | S1 (squash of A+B), S2 (squash of C+D)
         | 
         | Then we run the following:                 git rebase --onto S2
         | D branch3
         | 
         | Which rewrites branch3 to:                 S1, S2, E, F
         | 
         | This operation moves the unique commits from the unmerged
         | branch and replays them on top of the newly squashed commits on
         | the base branch, avoiding any merge conflicts.
        
           | puelocesar wrote:
           | That's how I've been working for years now. Does anyone know
           | how this gh stacks work internally? Does it do the same thing
           | under the hood?
           | 
           | I'm conflicted about it, seems like a good convenience, but I
           | wouldn't want my team to get dependent on an exclusive
           | feature of a single provider
        
             | steveklabnik wrote:
             | (You're replying to someone from product at GitHub, they're
             | explaining that's how it works there)
        
           | jd3 wrote:
           | We dealt with this headache for 7+ years at my former
           | employer. Thanks so much for this.
        
         | patrickthebold wrote:
         | I'm not sure I follow your workflow exactly. If PR B is merged,
         | then I'd expect PR A to already be merged (I'd normally branch
         | off of A to make B.)
         | 
         | That said, after the squash merge of A and git fetch origin,
         | you want something like git rebase --update-refs --onto
         | origin/main A C (or whatever the tip of the chain of branches
         | is)
         | 
         | The --update-refs will make sure pr B is in the right spot. Of
         | course, you need to (force) push the updated branches. AFAICT
         | the gh command line tool makes this a bit smoother.
        
         | jiveturkey wrote:
         | You "just" need to know the original merge-base of PR B to fix
         | this. github support is not really required for that. To me
         | that's the least valuable part of support for stacked PRs since
         | that is already doable yourself.
         | 
         | The github UI may change the target to main but your local
         | working branch doesn't, and that's where you `rebase --onto` to
         | fix it, before push to origin.
         | 
         | It's appropriate for github to automatically change the target
         | branch, because you want the diff in the ui to be
         | representative. IIRC gitlab does a much better job of this but
         | this is already achievable.
         | 
         | What is actually useful with natively supported stacks is if
         | you can land the entire stack together and only do 1 CI/actions
         | run. I didn't read the announcement to see if it does that. You
         | typically can't do that even if you merge PR B,C,D first
         | because each merge would normally trigger CI.
         | 
         | EDIT: i see from another comment (apparently from a github
         | person) that the feature does in fact let you land the entire
         | stack and only needs 1 CI run. wunderbar!
        
         | Phlogistique wrote:
         | I made a tool that adresses this precise problem:
         | https://github.com/scortexio/autorestack-action/
         | 
         | It does some merge magic so that PR B shows the correct diff;
         | and does so without needing to force push, so on your side you
         | can just "git pull" and continue working.
         | 
         | Of course I expect this repo to become obsolete when GitHub
         | makes their native stacking public.
        
       | teaearlgraycold wrote:
       | Wondering how all of those startups that implement this for
       | GitHub feel right now.
        
         | zaps wrote:
         | sherlocked
        
       | mc-serious wrote:
       | great, I'll directly compare it to graphite.com - the main point
       | really is the user interface in my opinion. Still a bit sceptical
       | whether github can out-deliver here, but happy to be proven
       | wrong!
       | 
       | Has anyone already tried that was a graphite user before?
        
       | atq2119 wrote:
       | People have been building stacked PR workflows on top of GitHub
       | for a while now. It's great to see that the message seems to have
       | finally landed at GitHub, but what is actually new here in GitHub
       | itself (i.e., not counting the gh CLI tool)?
       | 
       | There seems to be a native stack navigation widget on the PR
       | page, which is certainly a welcome addition.
       | 
       | The most important question though is whether they finally fixed
       | or are going to fix the issues that prevent submitting stacked
       | PRs from forks. I don't see any indication about that on the
       | linked page.
        
         | Liskni_si wrote:
         | They haven't fixed the fork issue, the FAQ clarifies this. I
         | suspect the target audience is squash merging corpos. Everyone
         | else can just do normal PRs with atomic commits reviewed
         | individually...
        
       | scottfits wrote:
       | cherry picking is so fragile, this is at least a step in the
       | right direction
        
       | jrochkind1 wrote:
       | Well, I have been waiting for this for YEARS.
       | 
       | Every time I try to do it manually, I wind up screwing everthing
       | up.
       | 
       | Very interested ot check it out.
        
       | ninkendo wrote:
       | > a chain of small, focused pull requests that build on each
       | other -- each one independently reviewable.
       | 
       | I have never understood what this even means.
       | 
       | Either changes are orthogonal (and can be merged independently),
       | or they're not. If they are, they can each be their own PR. If
       | they're not, why do you want to _review_ them independently?
       | 
       | If you reject change A and approve change B, nothing can merge,
       | because B needs A to proceed. If you approve change A and reject
       | change B, then the feature is only half done.
       | 
       | Is it just about people wanting to _separate_ logical chunks of a
       | change so they can avoid get distracted by other changes? Because
       | that seems like something you can already do by just breaking a
       | PR into commits and letting people look at one of those at a
       | time.
       | 
       | I've tried my best to give stacked-diff proponents the benefit of
       | the doubt but _none_ of it actually makes sense to me.
        
         | steveklabnik wrote:
         | The canonical example here is a feature for a website that
         | requires both backend and frontend work. The frontend depends
         | on the backend, but the backend does not depend on the
         | frontend. This means that the first commit is "independent" in
         | the sense that it can land without the second, but the second
         | is not, hence, a stack. The root of the stack can always be
         | landed independently of what is on top of it, while the rest of
         | the stack is dependent.
         | 
         | > If they're not, why do you want to review them independently?
         | 
         | For this example, you may want review from both a backend
         | engineer and a frontend engineer. That said, see this too
         | though:
         | 
         | > that seems like something you can already do by just breaking
         | a PR into commits and letting people look at one of those at a
         | time.
         | 
         | If you do this in a PR, both get assigned to review the whole
         | thing. Each person sees the code that they don't care about,
         | because they're grouped together. Notifications go to all
         | parties instead of the parties who care about each section.
         | Both reviews can proceed independently in a stack, whereas they
         | happen concurrently in a PR.
         | 
         | > If you approve change A and reject change B, then the feature
         | is only half done.
         | 
         | It depends on what you mean by "the feature." Seen as one huge
         | feature, then yes, it's true that it's not finished until both
         | land. But seen as two separate but related features, it's fine
         | to land the independent change before the dependent one: one
         | feature is finished, but the other is not.
        
           | Phelinofist wrote:
           | If the layers of a stack have a disjoint set of reviewers
           | things are viewed in separation which might lead to issues if
           | there is no one reviewing the full picture.
        
             | steveklabnik wrote:
             | That is why your forge will show that these two things are
             | related to each other, and you may have the same person
             | assigned to review both. It can show you this particular
             | change in the context of the rest of them. But not every
             | reviewer will always want to see all of the full context at
             | all times.
        
           | ninkendo wrote:
           | > If you do this in a PR, both get assigned to review the
           | whole thing. Each person sees the code that they don't care
           | about, because they're grouped together.
           | 
           | There are two separate issues you're bringing up:
           | 
           | - Both groups being "assigned" the PR: fixable with code
           | owners files. It's more elegant than assigning diffs to
           | people: groups of people have ownership over segments of the
           | codebase and are responsible for approving changes to it.
           | Solves the problem way better IMO.
           | 
           | - Both groups "seeing" all the changes: I already said GitHub
           | lets you view single commits during PR review. That is
           | already a solved problem.
           | 
           | And I didn't even bring up the fact that you can just open a
           | second PR for the frontend change that has the backend commit
           | as the parent. Yes, the second PR is a superset of the first,
           | but we've already established that (1) the second change
           | isn't orthogonal to the first one and can't be merged
           | independently anyway, and (2) reviewers can select only the
           | commits that are in the frontend range. Generally you just
           | mark the second PR as draft until the first one merges (or do
           | what Gitlab does and mark it as "depends on" the first, which
           | prevents it from merging until the first one is done.) The
           | first PR being merged will instantly make the second PR's
           | diff collapse to just the unique changes once you
           | rebase/merge in the latest main, too.
           | 
           | All of this is to explain how we can already do pretty much
           | all of this. But in reality, it's silly to have people review
           | change B if change A hasn't landed yet. A reviewer from A may
           | completely throw the whole thing out and tell you to start
           | over, or everything could otherwise go back to the drawing
           | board. Making reviewers look at change B before this is done,
           | is a potential for a huge waste of time. But then you may
           | think reviewers from change B may opt to make the whole plan
           | go back to the drawing board too, so what makes A so special?
           | And the answer is it's both a bad approach: just make the
           | whole thing in one PR, and discuss it holistically. Code
           | owners files are for assigning ownership, and breaking things
           | into separate commits is to help people look at a subset of
           | the changes. (Or just, like, have them click on the folder in
           | the source tree they care about. This is not a problem that
           | needs a whole new code review paradigm.)
        
             | steveklabnik wrote:
             | > fixable with code owners files.
             | 
             | Code owners automatically assigns reviewers. You still end
             | up in the state where many groups are assigned to the same
             | PR, rather than having independent reviews.
             | 
             | > I already said GitHub lets you view single commits during
             | PR review.
             | 
             | Yes, you can look at them, but your review is still in the
             | context of the full PR.
             | 
             | > And I didn't even bring up the fact that you can just
             | open a second PR for the frontend change that has the
             | backend commit as the parent.
             | 
             | The feature being discussed here is making this a first-
             | class feature of the platform, much nicer to use. The
             | second PR is "stacked" on top of the first.
        
               | ninkendo wrote:
               | > You still end up in the state where many groups are
               | assigned to the same PR
               | 
               | > Yes, you can look at them, but your review is still in
               | the context of the full PR.
               | 
               | Why is this a bad thing? I don't get it. This has
               | literally never been a problem once in my career. Is the
               | issue that people can't possibly scroll past another
               | discussion? Or... I seriously am racking my brain trying
               | to imagine why it's a bad thing to have more than one
               | stakeholder in a discussion.
               | 
               | I can think of a _lot_ of reasons why doing the opposite,
               | and siloing off discussions, leads to disaster. _That_ is
               | something I've encountered constantly in my career. We
               | start out running an idea past group A, they iterate,
               | then once we reach a consensus we bring the conclusion to
               | group B and they have concerns. But oh, group A already
               | agreed to this so you need to get on board. So group B
               | feels railroaded. Then more meetings are called and we
               | finally bring all the stakeholders together to discuss,
               | and suddenly hey, group A and B both only had a partial
               | view of the big picture, and why didn't we all discuss
               | this together in the first place? That's happened more
               | times in my career than I can count. The number of times
               | group B is mad that they have to move their finger to
               | scroll past what group A is talking about? Exactly zero.
        
               | steveklabnik wrote:
               | It's totally possible that you aren't the target audience
               | for this sort of feature. It tends to be more useful in
               | very large team and/or monorepo contexts.
               | 
               | This isn't about siloing discussions: it's about focus.
               | You can always see the full stack if you want to go look
               | at the other parts, the key is that you don't _have_ to.
               | 
               | The goal is to get thoroughly reviewed changes. It's much
               | easier to review five 100 line changes than one 500 line
               | one, and it's easier to review five 500 line changes than
               | it is a 2500 line one. Keeping commits small and tightly
               | reviewed leads to better outcomes in the end. Massive PRs
               | lead to rubber stamps of +1.
               | 
               | I agree that that scenario sounds like a nightmare. But I
               | don't think that a PR is the right place to solve that
               | problem: it sounds like something that should have been
               | sorted before any of the code was written in the first
               | place.
        
               | ninkendo wrote:
               | > It's much easier to review five 100 line changes than
               | one 500 line one, and it's easier to review five 500 line
               | changes than it is a 2500 line one.
               | 
               | This is true if the changes are orthogonal and are truly
               | independent. One should always favor small independent
               | changes if one can.
               | 
               | But when changes are all actually part of the same unit,
               | and aren't separable (apart from maybe the first of N of
               | them which may be mergeable independently), proponents
               | always seem to advocate that stacked diffs can somehow
               | change this fact. "Oh if only we had stacked diffs we
               | could break this into smaller changes", ignoring the fact
               | that no, they'd still be ordered and dependent on one
               | another.
               | 
               | Stacked diffs seem like a UI convenience for reviewers...
               | that's fine I guess. GitHub is basically what you get
               | when you ask the question "how can we make code review as
               | tedious and unhelpful as possible", and literally
               | anything would be better than what we have (seriously I
               | could fill a _book_ with how bad GitHub is. I don't think
               | I could design a worse experience if I tried.) So, maybe
               | I should just be happy they're trying anything.
        
               | steveklabnik wrote:
               | In stacked diffs systems, the idea is that the base of
               | the stack (once reviewed) can always be merged
               | independently, so you're totally right that like, if you
               | just purely think you can split things up when they
               | shouldn't be split up, that would be bad.
               | 
               | This is the model that the kernel uses, as well as tons
               | of other projects (any Gerrit user, for example), and so
               | it has gotten real-world use and at scale. That said,
               | everyone is also entitled to their preferences :)
        
               | ninkendo wrote:
               | > This is the model that the kernel uses
               | 
               | Nah.
               | 
               | The kernel uses a mailing list, and a "review" means a
               | mailing list thread. With some nice CLI tools to
               | integrate with git when you want to actually apply the
               | patch (or start a review thread.)
               | 
               | In that world, "[PATCH 2/5]" (or whatever) in the subject
               | title, and a different CC list for each patch, is a nice
               | way to be able to ensure different subsets of the patch
               | series have different discussions. That's great.
               | 
               | But if you're going to compare this to a GitHub UI, you
               | have to choose the basis for comparison, because the two
               | are so utterly different. Choosing one aspect (can we
               | make sure discussions are kept separate), and saying
               | "therefore the kernel uses stacked diffs" is a huge
               | misrepresentation of how different GitHub's approach is.
               | 
               | Because the kernel approach is the platonic ideal of a
               | code review: it's a simple threaded discussion between
               | stakeholders, centered around a topic (the patch, which
               | is inlined right in the email.) I would wager close zero
               | kernel maintainer actually look at the diffs exclusively
               | via their email client. They probably just check out the
               | changes locally and look at them, and the purpose of the
               | mailing list is to facilitate focused discussion on parts
               | of the change (which is all we really want, in the end.)
               | 
               | GitHub has so thoroughly shit the bed on actually
               | developing a good model of "threaded discussion about a
               | change", that you have to _change the way you think about
               | git's model_ to fix how awful GitHub is at allowing
               | review discussion to stay focused. You shouldn't need to
               | think about stacked diffs and multiple PR's. You should
               | use git branches as intended, multiple commits
               | representing changes, and a merge meaning "this branch
               | makes it or not." That GitHub's UI for discussing subsets
               | of a change is so abysmal, does not mean the model is
               | wrong. It means their discussion system is so abysmal
               | that a mailing list TUI can run circles around it. Fixing
               | this is GitHub's problem, and doesn't require _any_
               | changes to how PR's should be split up.
               | 
               | If you have a 2500-line PR with 5 500-line commits,
               | GitHub should not require you to split things up further
               | in any way, just to unfuck their discussion system.
               | 
               | Random idea I spent 10 seconds thinking about: let me
               | start a "here's a thread discussing the UI changes" and
               | add folks to it, and "here's a thread discussing the
               | backend changes", and add folks to that. I can then say
               | "let's not merge this until both threads are green". You
               | still see the whole change in the UI. (You can click
               | directories to drill into the changes, that solves the
               | "but the diff is too big" issue.) Discussion on a chunk
               | of the diff is scoped to a _discussion thread_ , which
               | you select when sending the message. Thus, all discussion
               | on any part of the diff is still scoped to a "discussion
               | thread" of arbitrary subsets of stakeholders.
               | 
               | None of this needs me to change how I split up my git
               | branches, an entire logical change is still either
               | "merged" or "not-merged" (seriously who cares about the
               | Pyrrhic victory of merging only change 1/N), and if we
               | want to limit scopes of discussion to subsets of a
               | change, we can just... _do that._
        
               | steveklabnik wrote:
               | Sorry, I am talking about stacked diffs in general, not
               | this specific implementation on GitHub. That "Patch 2/5"
               | is five stacked diffs, on top of each other. Forges that
               | are stacked-diff native do that same kernel flow, just on
               | the web instead of over email. You can also see this
               | corroborated over here:
               | https://news.ycombinator.com/item?id=47758251
               | 
               | All of the advantages, like "it's a simple threaded
               | discussion between stakeholders, centered around a
               | topic", is exactly why people like stacked diffs over
               | PRs.
               | 
               | GitHub is doing "stacked PRs", which is like stacked
               | diffs but more like PRs in the sense that they're stacked
               | _branches_ rather than stacked _diffs_. I agree that this
               | seems less ideal, but they also are putting it into an
               | existing project, rather than rebuilding everything
               | around it. There 's pros and cons to both approaches, but
               | I agree that I'd prefer a native system built for this,
               | personally. I'm still glad they're going to be
               | popularizing the general concept.
        
               | ninkendo wrote:
               | > Sorry, I am talking about stacked diffs in general, not
               | this specific implementation on GitHub
               | 
               | My point is that the LKML and what GitHub do is so
               | different that the definition of "stacked diffs in
               | general" can only describe a tiny aspect of each, if you
               | want to call both of their approaches by the same name.
               | From where I sit, the only common element between them is
               | "they offer a way to keep discussion separated."
               | 
               | If that's all people are actually complaining about,
               | there are a thousand better ways to "keep discussion
               | separated" that don't require me to pretend that it's ok
               | that only a subset of my branch is ok to merge.
               | 
               | In git, a branch is the thing you either merge or don't.
               | You merge multiple commits at once, or you don't. It's a
               | great model. Breaking up the branch into smaller pieces,
               | and giving people the impression it's ok to merge the
               | first commit but not the rest, _just to unfuck the
               | discussion UX_ , is putting the cart before the horse. I
               | make a branch strictly _because_ I want it to either all
               | merge or none of it merge. It's the only sensible
               | approach in my book. If a discussion system is so bad
               | that this is unworkable, it means the discussion system
               | is bad, it doesn't mean the conceptual model of a merge
               | is bad.
        
               | steveklabnik wrote:
               | > My point is that the LKML and what GitHub do is so
               | different that the definition of "stacked diffs in
               | general" can only describe a tiny aspect of each
               | 
               | That's fine, what I mean is, when we started this convo,
               | I thought you were asking about the general concept of
               | stacked diffs, not the specifics of what GitHub is
               | releasing here. That's my mistake for misunderstanding,
               | sorry about that.
               | 
               | This is also (assumedly, anyway) why they're calling this
               | "stacked PRs" and not "stacked diffs," because what
               | they're doing is slightly different than Gerrit,
               | Phabricator, Critique, etc.
        
               | ninkendo wrote:
               | Thanks for indulging me so far, by the way, I really
               | appreciate this discussion, it's very stimulating.
               | 
               | After thinking about the whole thing I think I can
               | summarize my opinion a lot better now:
               | 
               | Stacked diffs are a category error. Units of discussion,
               | and units of integration, should not be conflated.
               | 
               | A branch is my unit of intended integration: merge all of
               | it or none of it. The fact that reviewers need smaller
               | slices to discuss does not imply those slices should
               | become independently landable history objects. That's a
               | UX concern for the review tool, not something I should
               | have to encode into Git history.
               | 
               | The ideal system would let me seed discussion however I
               | want (by commit, by path, by subsystem, by semantic
               | region of the diff, etc) without forcing me to pretend
               | those are separate merge units.
               | 
               | Github nails the "merge unit" (CI runs against the whole
               | branch, the branch either merges or doesn't, etc), but
               | absolutely fumbles in the discussion part. I hate that
               | I'd have to change the merge unit just to fix their
               | discussion UX.
        
         | charcircuit wrote:
         | >If you reject change A and approve change B, nothing can merge
         | 
         | The feature is also half done in this case. The author can fix
         | up the concerns the reviewer had in A and then both can be
         | merged at the same time.
        
           | ninkendo wrote:
           | Couldn't they do that in one PR? Seriously, couldn't you just
           | say "hey Alice, could you review the A parts of this PR" and
           | "hey Bob, could you review the B parts", then only merge once
           | both of them approve? Even GitHub, for all its faults,
           | supports code owners files, such that this can even be
           | policy.
        
             | charcircuit wrote:
             | Technically yes, but the work for A and B may not be done
             | at the same time so you may want to get a head start on
             | getting A reviewed while B is still being worked on.
             | 
             | As a counter example. Why use multiple PRs when you can
             | always just merge them into a single one. It's possible to
             | make huge PRs with a bunch of different changes all
             | included, but then the GitHub tools with managing stuff
             | don't really work that well and you have to just do
             | everything as comments instead of being about to actually
             | accept a single accepted change for example.
        
         | esafak wrote:
         | Feature B depends on feature A, but you don't need B to
         | understand A. Why _wouldn 't_ you create separate PRs?? It is
         | faster to review and deploy.
        
           | fmbb wrote:
           | Of course you would create separate PRs.
           | 
           | Why would you waste time faffing about building B on top of a
           | fantasy version of A? Your time is probably better spent
           | reviewing your colleague's feature X so they can look at your
           | A.
        
         | mh2266 wrote:
         | you're upgrading the repository from language version 1 to 2,
         | version 2 adds new compiler errors that rejects some old code,
         | or the library has removed some old deprecated API the
         | repository was still using in some places--the key here being
         | that it can't be something that needs to be completely atomic.
         | 
         | you have hundreds or thousands of files to fix. that is
         | unreviewable as a single commit, but as a per-file, per-
         | library, per-oncall, etc. commit it is not that bad.
        
           | ninkendo wrote:
           | > you have hundreds or thousands of files to fix. that is
           | unreviewable as a single commit, but as a per-file, per-
           | library, per-oncall, etc. commit it is not that bad
           | 
           | Why is it _intrinsically_ unreviewable as a single commit?
           | Why can 't the discussion/review system allow scoping
           | discussions to a single folder of the change, or a single
           | library, or a particular code-owner's "slice" of the repo,
           | etc? The answer to this question is always unsatisfactory to
           | me. It always ends up being "because GitHub's UI makes it
           | hard to <foo>" and it's just taken as an immutable law of the
           | universe that we're stuck with that UI's limitations.
           | 
           | If a change is huge, find some basis by which to discuss it
           | in smaller chunks. That basis doesn't _have_ to be the PR
           | itself (such that you have to make smaller PR 's to make
           | discussion manageable.) It can be a subdirectory of the diff.
           | A wildcard-match over the source files. Whatever the case
           | needs to be, the idea is still that the discussion UX
           | shouldn't make reviewing large changes painful.
           | 
           | Why do we tolerate the fact that GitHub doesn't let you say
           | "approved for changes in `frontend/*`" or "approved for the
           | changes I'm a code-owner of", and have the PR check system
           | mark the PR as approved once all slices have been approved?
           | Why do we tolerate that a thousand-file change is
           | "unreviewable"? Instead we have to change our unit of
           | integration, allowing partially-complete work to be merged,
           | just because the review UX sucks.
        
             | dontlikeyoueith wrote:
             | Why do you insist on a different but functionally
             | equivalent solution to the problem?
             | 
             | It's weird.
             | 
             | > Why do we tolerate the fact that GitHub doesn't let you
             | say "approved for changes in `frontend/*`
             | 
             | That's literally what stacked PRs are adding.
        
         | nerdypepper wrote:
         | we have been stacking on tangled.org for a while now, you can
         | see a few examples of stacks we have made here:
         | https://tangled.org/tangled.org/core/pulls?state=merged&q=st...
         | 
         | for example, this stack adds a search bar:
         | https://tangled.org/tangled.org/core/pulls/1287
         | 
         | - the first PR in the stack creates a search index.
         | 
         | - the second one adds a search API handler.
         | 
         | - the last few do the UI.
         | 
         | these are all related. you are right that you can do this by
         | breaking a change into commits, and effectively that is what i
         | do with jujutsu. when i submit my commits to the UI, they form
         | a PR stack. the commits are individually reviewable and
         | updatable in this stacking model.
         | 
         | gh's model is inherently different in that they want you to
         | create a new branch for every new change, which can be quite a
         | nuisance.
         | 
         | have written more about the model here:
         | https://blog.tangled.org/stacking/
        
           | ninkendo wrote:
           | > - the first PR in the stack creates a search index.
           | 
           | > - the second one adds a search API handler.
           | 
           | > - the last few do the UI.
           | 
           | So you're saying you're going to merge (and continuously
           | integrate, perhaps to production) a dangling, unused search
           | index, consuming resources with no code using it, just to
           | make your review process easier?
           | 
           | It's very depressing that review UX is so abysmal that you
           | have to _merge features before they 're done_ just to un-fuck
           | it.
           | 
           | Why can't the change still be a big branch that is either all
           | merged or not... _and_ people can review it in chunks? Why do
           | we _require_ that the unit of integration equals the unit of
           | review?
           | 
           | The perverse logic always goes something like this:
           | 
           | "This PR is too big, break it up into several"
           | 
           | Why?
           | 
           | "It's easier to review small, focused changes"
           | 
           | Why can't we do that in one PR?
           | 
           | "Because... well, you see GitHub's UI makes it really hard to
           | ..."
           | 
           | And that ends up being the root-cause answer. I should be
           | able to make a 10,000 line change in a single commit if I
           | want, and reviewers should be able to view subsets of it
           | however they want: A thread of discussion for the diffs
           | within the `backend` folder. A thread of discussion for the
           | diffs within the `frontend` folder, etc etc. Or at the very
           | least I should be able to make a single branch with multiple
           | commits based on topic (and under no obligation for any of
           | them to even compile, let alone be merge-able) and it should
           | feel natural to review each commit independently. _None_ of
           | this should require me to contort the change into allowing
           | integration partially-completed work, just to allow the
           | review UX to be manageable.
        
             | matharmin wrote:
             | This is not just about the UI, it's about the mental model
             | and management of the changes.
             | 
             | Just covering the review process:
             | 
             | Yes, you can structure your PR into 3 commits to be
             | reviewed separately. I occasionally structure my PRs like
             | this - it does help in some cases. But if those separate
             | parts are large, you really want more structure around it
             | than just a commit.
             | 
             | For example, let's say you have parts A, B and C, with B
             | depending on A, and C depending on B.
             | 
             | 1. I may want to open a PR for A while still working on B.
             | Someone may review A soon, in which case I can merge
             | immediately. Or perhaps it will only be reviewed after I
             | finished C, in which case I'll use a stacked PR. 2. The
             | PR(s) may need follow up changes after initial review. By
             | using stacked PRs instead of just separate commits, I can
             | add more commits to the individual PRs. That makes it clear
             | what parts those commits are relevant to, and makes it easy
             | to re-review the individual parts with updated changes.
             | Separate commits don't give you that.
             | 
             | Stacked PRs is not a workflow I'd use often, but there are
             | cases where it's a valuable tool.
             | 
             | Then apart from the review process, there are lots of
             | advantages to keeping changes small. Typically, the larger
             | a change, the longer it lives in a separate branch. That
             | gives more time for merge conflicts to build up. That gives
             | more time for underlying assumptions to change. That makes
             | it more difficult to keep a mental map of all the changes
             | that will be merged.
             | 
             | There are also advantages to deploying small changes at a
             | time, that I won't go into here. But the parent's process
             | of potentially merging and deploying the search index first
             | makes a lot of sense. The extra overhead of managing the
             | index while it's "unused" for a couple of days is not going
             | to hurt you. It allows early testing of the index
             | maintenance in production, seeing the performance overhead
             | and other effects. If there's an issue, it's easy to revert
             | without affecting users.
             | 
             | The overall point is that as features become large, the
             | entire lifecycle becomes easier to manage if you can split
             | it into smaller parts. Sometimes the smaller parts may be
             | user-visible, sometimes not. For features developed in a
             | day or two, there's no need to split it further. But if it
             | will span multiple weeks, in a project with many other
             | developers working on, then splitting into smaller changes
             | helps a lot.
             | 
             | Stacked PRs is not some magical solution here, but it is
             | one tool that helps manage this.
        
               | ninkendo wrote:
               | > But if those separate parts are large, you really want
               | more structure around it than just a commit.
               | 
               | Why? I reject the notion that large commits should be
               | intrinsically hard to review.
               | 
               | GitHub already has the concept of "code owners", which
               | are people who have ownership/review responsibility over
               | slices of the codebase, based on globs/pattern matching.
               | But they don't implement the other half of that, which is
               | that a reviewer should be able to see a _projection_ of a
               | given PR, which matches the part of the repo they 're the
               | owner of.
               | 
               | There. That solves the entire problem of "this is too
               | big, I can't look at all of it" (because your code
               | ownership says this is the chunk of codebase you say you
               | care about), and if that still isn't sufficient, there's
               | a zillion UI features GitHub _could_ add that they simply
               | don 't. Why can't I "focus" on a subset of the changes
               | during review, in a way that helps me ignore unrelated
               | discussions/changes? That is, even if I'm not code owner
               | of the `frontend/` folder, why isn't there a UI
               | affordance that says "let me focus on changes inside
               | `frontend/` and ignore discussions/etc for the rest"?
               | 
               | > By using stacked PRs instead of just separate commits,
               | I can add more commits to the individual PRs
               | 
               | Or you could just add commits to _the_ PR, and if GitHub
               | got the damned UI right, it would be natural to see the
               | "slice" you care about, for all the new commits. Having
               | to rearrange commits into separate PR's and slice-and-
               | dice followup changes to file them into the right PR
               | unit, is (to me) a workaround for how shitty GitHub's
               | review UX is. It really shouldn't be this way.
               | 
               | > Then apart from the review process, there are lots of
               | advantages to keeping changes small [...]
               | 
               | I agree with you on most of these points, but the
               | decision to land smaller changes earlier should be made
               | based on things like "let's get early feedback behind a
               | feature flag" or "let's see how this chunk behaves in
               | production so we can validate assumptions", or "let's
               | merge what we have now so to cut back on conflicts", etc.
               | That's all fine. But I'm vehemently opposed to being
               | _required_ to slice up my changes this way, _just to work
               | around a terrible review UI._
               | 
               | Personally, I review code in my development environment
               | GitHub's UI is nonsensically terrible to read code. I
               | could go on for hours about this[0], but when looking in
               | my IDE I can drill into a subfolder and look at the diffs
               | there. I can click and follow symbols. I can look at the
               | individual diff history for any wildcarded subset of the
               | repo, and see how the change was broken into commits. If
               | I'm typing up some feedback to say "try doing it this way
               | instead", I can actually try it myself first to make sure
               | I'm not suggesting that someone do something that doesn't
               | even compile.
               | 
               | And GH's discussion UX is by _far_ the worst part of all
               | of it. If you have a thread of discussions around a line
               | of code, then wake up the next morning and want to see
               | what new comments have been added? Good luck. Your best
               | bet is to check your email inbox, because the comments
               | are actually shown to you there. Using GitHub 's "inbox"
               | feature? All that is is a link to PR's you have to look
               | at, with no hints at "why" (it could be a CI run finished
               | for all you know.) Good luck figuring out "why" a PR is
               | on your list. Did someone @-mention you? Who knows. So,
               | find the blue dot next to the PR, click it, and then
               | figure out for yourself what changed since the last time
               | you looked. No, you can't just scroll and find it because
               | GitHub hides half the discussions by default. So you have
               | to go and expand all the collapsed sections to hopefully
               | find that conversation you were having yesterday. But oh,
               | you can only find it in the diff tab. So you click that,
               | but the relevant file is collapsed by default ("Large
               | diffs are not rendered blah blah"), so then click that.
               | _Then_ you may find that discussion.
               | 
               | Contrast this to a mailing list. The discussions are...
               | discussion threads. You pick up where you left off.
               | People's comments are right there in your inbox, newest
               | one on top (or whatever your preference is.) You get
               | notified when there's a new message, and when you tap the
               | notification, _it 's the actual message_, not some link
               | to the PR that makes you click 6 more things to maybe
               | find the message that just happened.
               | 
               | [0] like how the first thing you have to do when opening
               | up the changes tab is ctrl+f search for "Large diffs are
               | not rendered by default" to find the actually-important
               | diffs that are not shown to you because GitHub's backend
               | can't scale to rendering large diffs without friction.
               | Countless times I've been burned by approving a PR
               | because I _don 't_ see it making a change to some
               | functionality, only to find out it actually _did_ make
               | said change, but GitHub just decided not to show me it.
               | Seriously, the  "large diffs" are the most important
               | ones, and those are the ones _you don 't see without
               | extra clicks._ The mind boggles.)
        
           | whereistejas wrote:
           | Each of your stacked PRs only has one commit. Do you have any
           | examples with multiple commits per PR in a stack?
           | 
           | PS: I love the concept of tangled. I currently use
           | `sourcehut` but may soon move to tangled.
        
             | whereistejas wrote:
             | nevermind, I see what's happening in the UI. Each `jj`
             | change is preserved in the UI and we can see multiple
             | versions of the same change. The stack then is not really a
             | stack of PRs but a stack of changes (where each change has
             | its own history, i.e., the interdiff view). Did I get it
             | mostly right?
        
               | nerdypepper wrote:
               | yes, thats right! when you submit a branch, you can
               | choose to "stack" it, so the individual commits in the
               | branch turn into separate PRs. these PRs evolve
               | individually, can be merged individually, and be reviewed
               | individually. you can also set different reviewers/labels
               | for different PRs in the stack.
        
       | ChrisArchitect wrote:
       | Aside:
       | 
       | > _This is a docs site that was made to share the spec and CLI
       | for private preview customers that ended up getting picked up.
       | This will move to GitHub docs once it's in public preview._
       | 
       | (https://x.com/matthewisabel)
        
       | WhyNotHugo wrote:
       | I really don't get the point of stacked PRs.
       | 
       | Just using git, you'd send a set of patches, which can be
       | reviewed, tested and applied individually.
       | 
       | The PR workflow makes a patch series an undivisible set of
       | changes, which must be reviewed, tested and applied in unison.
       | 
       | And stacked PRs tries to work around this issue, but the issue is
       | how PRs are implemented in the first place.
       | 
       | What you really want is the ability to review individual
       | commits/patches again, rather than work on entire bundles at
       | once. Stacked PRs seems like a second layer of abstraction to
       | work around issues with the first layer of abstractions.
        
         | pierrekin wrote:
         | The teams that I have worked with still apply the philosophy
         | you're describing, but they consider PRs to be the "commit",
         | i.e. the smallest thing that is sane to apoly individually.
         | 
         | Then the commits in the PR are not held to the standard of
         | being acceptable to apply, and they are squashed together when
         | the PR is merged.
         | 
         | This allows for a work flow in which up until the PR is merged
         | the "history of developing the PR" is preserved but once it is
         | merged, the entire PR is applied as one change to the main
         | branch.
         | 
         | This workflow combined with stacked PRs allows developers to
         | think in terms of the "smallest reviewable and applicable
         | change" without needing to ensure that during development their
         | intermediate states are safe to apply to main.
        
           | philwelch wrote:
           | Squashing is fine if you're just making a mess of temporary
           | commits as you work and you don't want to keep any of those
           | changes separate in master, but that's not a useful review
           | workflow. A lot of times I've built a feature in a way that
           | decomposed naturally into e.g. two commits: one to do a
           | preparatory refactor (which might have a lot of noisy and
           | repetitive changes, like changing a function signature) and
           | another to actually change the behavior. You want those
           | changes to be separate because it makes the changes easier to
           | review; the reviewer quickly skims the first commit, observes
           | that it's a mechanical refactor, and the change in behavior
           | has its own, smaller commit without all the noise.
           | 
           | "What if there's feedback and you need to make changes after
           | the code review?" Then I do the same thing I did before I
           | posted the code review: make separate "fixup" commits and do
           | an interactive rebase to squash them into my commits. (And
           | yes, I do validate that the intermediate commits build
           | cleanly.)
           | 
           | There's nothing you get from stacked PR's that you don't also
           | get from saying "please review my feature branch commit by
           | commit".
        
             | pierrekin wrote:
             | Yes what you're describing is literally the thing GitHub
             | has built but instead of having to make a bunch of
             | compromises, there is dedicated UI and product metaphor for
             | it.
             | 
             | Some examples of compromises:
             | 
             | You can't merge partially merge a large "review commit by
             | commit" PR so you are forced to wait until it is all ready
             | to merge.
        
           | WhyNotHugo wrote:
           | Doesn't this mean that a first review might request that a
           | specific change be reverted, and then a later reviewer
           | reviews that reversion? That's essentially reviewing a noop,
           | but understanding the it's a noop requires carefully checking
           | all previous now-invalidated changes.
        
             | pierrekin wrote:
             | No, each PR is based on the previous one, so the reviewer
             | only needs to consider the ideas that are new in each PR
             | one at a time.
        
         | jiveturkey wrote:
         | Right, a PR is "just" a set of commits (all must be in the same
         | branch) that are intended to land atomically.
         | 
         | Stacked PRs are not breaking up a set of commits into divisible
         | units. Like you said, you can already do that yourself. They
         | let you continue to work off of a PR as your new base. This
         | lets you continue to iterate asynchronously to a review of the
         | earlier PRs, and build on top of them.
         | 
         | You often, very often, need to stage your work into reviewer-
         | consumable units. Those units are the stack.
        
         | mh2266 wrote:
         | this works much better in Phabricator because commits to diffs
         | are a 1:1 relationship, diffs are updated by amending the
         | commit, etc., the Github implementation does seem a bit like
         | gluing on an additional feature.
        
         | cush wrote:
         | It's useful for large PRs in large repos with many
         | contributors. It reduces the burden for reviewers.
        
           | Gigachad wrote:
           | Still not sure this is the right solution. My problem is if
           | one of your first stages gets rejected in review or requires
           | significant changes, it invalidates so much work that comes
           | after it. I've always when possible preferred to get small
           | stuff merged in to production as it happens rather than build
           | an entire feature and put it up for review.
        
             | thamer wrote:
             | > it invalidates so much work that comes after it.
             | 
             | No, not necessarily.
             | 
             | I work on a large repo and new features often involve
             | changes to 3 different services: 2 from the backend, and
             | the frontend UI. Sending a single PR with changes to all 3
             | services is really not ideal: the total diff size in a
             | feature I added recently was maybe 600+ lines, and the
             | reviewers for frontend and backend changes are different
             | people. The changes in the 2 backend services can be
             | thought of as business logic on one side and interactions
             | with external platforms on the other. The business logic
             | can't work without integrating calls to external APIs, and
             | the UI can't work without the business logic.
             | 
             | These days I open 3 separate PRs and the software only
             | works once all 3 are merged and built. It would be great to
             | have all of them as a single package that's still testable
             | and reviewable as 3 distinct parts. The UI reviewer can
             | check out the whole stacked PR and see it running locally
             | with a functional backend, something that's not possible
             | without a lot of manual work when we have 3 PRs.
        
             | pertymcpert wrote:
             | The LLVM community used this model for years with
             | Phabricator before it was EOL'd and moving to GH and PRs
             | was forced. It's a proven model and works very well in
             | complex code bases, multiple components and dependencies
             | that can have very different reviewer groups. E.g: 1) A
             | foundational change to the IR is the baseline commit 2)
             | Then some tweaks on top to lay the groundwork for uses of
             | that change 3) Some implementation of a new feature that
             | uses the new IR change 4) A final change that flips the
             | feature flag on to enable by default.
             | 
             | Each of these changes are dependent on the last. Without
             | stacked PRs you have o only one PR and reviewing this is
             | huge. Maybe thousands of lines of complex code. Worse, some
             | reviewers only need to see some parts of it and not the
             | rest.
             | 
             | Stacked diffs were a godsend and the LLVM community's
             | number one complaint about moving to GitHub was losing this
             | feature.
        
         | gorgoiler wrote:
         | Exactly! A stack of PRs is really the same beast as a branch of
         | commits.
         | 
         | The traditional tools (mailing-lists, git branches,
         | Phabricator) represented each change as a difference between an
         | old version of the code and the proposed new version. I believe
         | Phabricator literally stored the diff. They were called "diffs"
         | and you could make a new one by copying and pasting into a
         | <textarea> before pressing save*.
         | 
         | The new fangled stuff (GitHub and its clones) recorded your
         | change as being between branches A and B, showed you the
         | difference on the fly, and let you modify branch B. After
         | fifteen years of this we are now seeing the option for branch A
         | to be something other than main, or at least for this to be a
         | well supported workflow.
         | 
         | In traditional git land, having your change as a first class
         | object -- an email or printout or ph/D1234 with the patch
         | included -- was the _default workflow_!
         | 
         | *Or some other verb meaning save.
        
       | eqvinox wrote:
       | > How It Works
       | 
       | > The gh stack CLI handles the local workflow [...]
       | 
       | That's not "how it works", that's "how you['re supposed to] use
       | it"... for "how it works" I would've expected something like "the
       | git branches are named foo1 foo2 and foo3 and we recognize that
       | lorem ipsum dolor sit amet..."
       | 
       | ...which, if you click the overview link, it says "The CLI is not
       | required to use Stacked PRs -- the underlying git operations are
       | standard. But it makes the workflow simpler, and you can create
       | Stacked PRs from the CLI instead of the UI." ... erm ... how
       | about actually explaining what the git ops are? A link, maybe? Is
       | it just the PRs having common history?
       | 
       | ...ffs...
       | 
       | (In case it's not obvious: I couldn't care less for using a GH
       | specific CLI tool.)
        
       | zzyzxd wrote:
       | One mistake I see across many organizations is that sometimes
       | they overthink how much order should matter.
       | 
       | Sure, your application has a dependency on that database, but it
       | doesn't necessarily mean you can't deploy the application before
       | having a database. If possible, make it acceptable for your
       | application to stay in a crashloop until your database is online.
        
         | devmor wrote:
         | I agree with you and further will add that modularity+atomicity
         | are the ideal state for the vast majority of software
         | applications... but in reality, most organizations can not
         | afford to rewrite their software to the extent required to
         | achieve this, if it wasn't planned from the start.
        
       | alkonaut wrote:
       | Let's say I have the canonical example of a stack from main via a
       | backend-pr and a frontend-pr. When my stack is done I send it for
       | review to one frontend reviewer and one backend reviewer.
       | 
       | Usually when you develop a "full stack" thing you continuously
       | massage the backend into place while developing frontend stuff.
       | If you have 10 commits for frontend and 10 for backend, they
       | might start with 5 for backend, then 5 commits to each branch to
       | iron out the interface and communication, and finally 5 commits
       | on the frontend. Let's call these commits B1 through B10 and F1
       | through F10. Initially I have a backend branch based on main wuth
       | commits B1 through B5.
       | 
       | Then I have a frontend branch based on B5 with commits F1 through
       | F5. But now I need to adjust the backend again and I make change
       | B6. Now I need to rebase my frontend branch to sit on B6? And
       | then I make F6 there (And so on)?
       | 
       | And wouldn't this separation normally be obvious e.g. by paths?
       | If I have a regular non-stack PR with 20 commits and 50 changed
       | files, then 25 files will be in /backend and 25 in /frontend.
       | 
       | Sure, the reviewers who only review /frontend/* might now see
       | half the commits being empty of relevant changes. But is that so
       | bad?
        
         | steveklabnik wrote:
         | > If you have 10 commits for frontend and 10 for backend
         | 
         | In this model, you tend to want to amend, rather than add more
         | commits. And so:
         | 
         | > they might start with 5 for backend, then 5 commits to each
         | branch to iron out the interface and communication,
         | 
         | You don't add more commits here, you modify the commits in your
         | stack instead.
         | 
         | > Now I need to rebase my frontend branch to sit on B6?
         | 
         | Yes, when you change something lower in the stack, the things
         | on top need to be rebased. Because your forge understands that
         | they're stacked, it can do this for you. And if there's
         | conflicts, let you know that you need to resolve them, of
         | course.
         | 
         | But in general, because you are amending the commits in the
         | stack rather than adding to it, you don't need to move anything
         | around.
         | 
         | > And wouldn't this separation normally be obvious e.g. by
         | paths?
         | 
         | In the simplest case, sure. But for more complex work, that
         | might not be the case. Furthermore, you said you have five
         | commits for each; within those sets of five, this separation
         | won't exist.
        
       | herpdyderp wrote:
       | I thrive on stacked PRs but this sure seems like a weird way to
       | implement support for it. Just have each branch point to their
       | parent in the chain, the end. Just native Git. I've been longing
       | for better GitHub support for this but the CLI is not where I
       | need that support: just the UI.
        
         | sroussey wrote:
         | Yes! Maybe that feature will come next.
        
         | sameenkarim wrote:
         | The CLI is completely optional, you can create stacked PRs
         | purely via the UI.
         | 
         | Also the rationale for having a chain of branches pointing to
         | each other was so the diff in a PR shows just the relevant
         | changes from the specific branch, not the entire set of changes
         | going back to the parent/trunk.
         | 
         | Curious how you're thinking about it?
        
           | herpdyderp wrote:
           | > so the diff in a PR shows just the relevant changes from
           | the specific branch
           | 
           | That's exactly right.
           | 
           | > you can create stacked PRs purely via the UI
           | 
           | How?
           | 
           | I see from the docs https://github.github.com/gh-
           | stack/introduction/overview:
           | 
           | > When a pull request is part of a stack
           | 
           | How does GitHub determine if a PR is part of a stack? Is it
           | automatically detected so that I don't need to adjust my
           | tooling that already creates chained PRs?
        
         | pastel8739 wrote:
         | Rebasing after merging a base branch becomes a pain though,
         | when you do this. IMO the CLI will be nice to automate the
         | process of rebasing each branch on its parent.
        
           | herpdyderp wrote:
           | Agreed. I do have tooling for a rebase + push flow, but it
           | simply calls native git commands.
        
         | godzillafarts wrote:
         | +1 this isn't something new, it's been possible all along in
         | native git if you're willing to do branch management and
         | rebasing yourself. Just without the fancy UI / stack map.
        
       | the_gipsy wrote:
       | Can we merge from GitHub UI without rewriting the commit already?
        
       | thcipriani wrote:
       | Very cool that GitHub actually put stacks in the UI vs. GitLab's
       | `glab stack`[0] (which looks just like the `gh stack` part of
       | GitHub's thing).
       | 
       | One part that seems like it's going to feel a little weird is how
       | merging is set up[1].
       | 
       | That is, if I merge the bottom of the stack, it'll rebase the
       | others in the stack, which will probably trigger a CI test run.
       | So, if I have three patches in the stack, and I want to merge the
       | bottom two, I'd merge one, wait for tests to run on the other,
       | merge the second vs. merge just those two in one step (though,
       | without having used it, can't be sure about how this'd work in
       | practice--maybe there's some way to work around this with
       | restacking?)
       | 
       | [0]: <https://docs.gitlab.com/cli/stack/>
       | 
       | [1]: <https://github.github.com/gh-stack/guides/stacked-
       | prs/#mergi...>
        
         | sameenkarim wrote:
         | > So, if I have three patches in the stack, and I want to merge
         | the bottom two, I'd merge one, wait for tests to run on the
         | other, merge the second vs. merge just those two in one step
         | 
         | As we have it designed currently, you would have to wait for CI
         | to pass on the bottom two and then you can merge the bottom two
         | in one step. The top of the stack would then get rebased, which
         | will likely trigger another CI run.
         | 
         | Thanks for the callout - we'll update those docs to make it
         | clear multiple PRs can be merged at once.
        
       | zeafoamrun wrote:
       | My main question about this is does it keep review history
       | properly after a rebase to restack PRs? Eg if I have reviewed PR
       | for branch A and now its been rebased onto B by this tool and
       | then more changes are made to A, does "review changes since" work
       | in A's PR? This has been the main thing stopping me from wanting
       | to use rebase to stack PRs and if they've fixed this somehow then
       | I'm interested.
        
       | dminik wrote:
       | Maybe this is just a skill issue, but even with several attempts
       | I just can't figure out why I would use stacked diffs/PRs. Though
       | maybe that's because of the way I work?
       | 
       | I notice a lot of examples just vaguely mention "oh, you can have
       | others review your previous changes while you continue working",
       | but this one doesnt make sense to me. Often times, the first set
       | of commits doesn't even make it to the end result. I'm working on
       | a feature using lexical, and at this point I had to rewrite the
       | damn thing 3 times. The time of other devs is quite valuable and
       | I can't imagine wasting it by having them review something that
       | doesn't even make it in.
       | 
       | Now, I have been in situations where I have some ready changes
       | and I need to build something on top. But it's not something just
       | making another branch on top + rebase once the original is merged
       | wouldn't solve.
       | 
       | Is this really worth so much hype?
        
         | pierrekin wrote:
         | We use this feature extensively at $dayjob.
         | 
         | Imagine you have some task you are working on, and you wish to
         | share your progress with people in bite sized chunks that they
         | can review one at a time, but you also don't want to wait for
         | their reviews before you continue working on your task.
         | 
         | Using a stacked set of PRs you can continue producing new work,
         | which depends on the work you've already completed, without
         | waiting for the work you've already completed to be merged, and
         | without putting all your work into one large PR.
        
           | Gigachad wrote:
           | I've always done this by just creating new PRs that are based
           | on the branch of the old one. Maybe this is a UI improvement?
        
             | steveklabnik wrote:
             | Yes, you can do that, but there's lots of things about it
             | that are awkward. This makes it a more first-class feature.
        
             | literallyroy wrote:
             | Yeah that is a "stacked" pr. The tooling is nice especially
             | when have a larger stack and make changes to the first
             | branch. Update refs + push all branches, same with merging
             | and rebasing onto main.
        
           | philwelch wrote:
           | You can review PR's commit by commit, and you can ask people
           | to review PR's commit by commit. Not a big deal.
        
             | pierrekin wrote:
             | Then you lose the ability to merge the portion of work
             | which has been agreed to, until the whole change overall
             | has been agreed to.
        
         | heldrida wrote:
         | I also branch out, and rebase. Also, keep updating and rebasing
         | until merged. It's tedious when PR take ages for approval, as I
         | keep creating new branches on top of each other.
         | 
         | So, when I saw this announcement seemed interesting but don't
         | see the point of it yet.
        
         | mh2266 wrote:
         | in Phabricator you either abandon the original diffs entirely,
         | or you amend them. you don't just stack more commits with
         | meaningless messages like "WIP", "lint fix", etc. on top.
         | 
         | > The time of other devs is quite valuable and I can't imagine
         | wasting it by having them review something that doesn't even
         | make it in.
         | 
         | this is now what stacked diffs are for. stacked diffs doesn't
         | mean putting up code that isn't ready. for example you are
         | updating some library that needs an API migration, or compiler
         | version that adds additional stricter errors. you need to touch
         | hundreds of files around the repository to do this. rather than
         | putting up one big diff (or PR) you stack up hundreds of them
         | that are trivial to review on their own, they land immediately
         | (mitigating the risk of merge conflicts as you keep going) then
         | one final one that completes the migration.
        
       | fmbb wrote:
       | > Large pull requests are hard to review, slow to merge, and
       | prone to conflicts. Reviewers lose context, feedback quality
       | drops, and the whole team slows down.
       | 
       | OK, yeah, I'm with you.
       | 
       | > Stacked PRs solve this by breaking big changes into a chain of
       | small, focused pull requests that build on each other -- each one
       | independently reviewable.
       | 
       | I don't get this part. It seems like you are just wasting your
       | own time building on top of unreviewed code in branches that have
       | not been integrated in trunk. If your reviews are slow, fix that
       | instead of running ahead faster than your team can actually work.
        
         | altano wrote:
         | This _is_ a solution to slow reviews. Smaller reviews are
         | faster to get in. And many small reviews take less time to
         | review than one large review.
         | 
         | Plus there's no review that's instant. Being able to continue
         | working is always better.
        
           | fmbb wrote:
           | I am not arguing against small PRs.
           | 
           | Stacking PRs are not a way to make changes smaller and
           | therefore not making reviews easier.
        
       | lopsotronic wrote:
       | Interesting to see how this integrates with any release flows
       | that use a lot of tags or feature flagging.
        
       | throwatdem12311 wrote:
       | Freaking finally.
       | 
       | I've been trying to convince my boss to buy Graphite for this,
       | seems like Github is getting their a* in gear after Cursor bought
       | them.
       | 
       | If Jetbrains ever implements support for them in IntelliJ I will
       | be in Heaven.
        
       | quibono wrote:
       | GitLab's UI around MRs (PRs) is IMO miles better than what GH's
       | been offering. Try creating a PR from branch A to main, and then
       | rebasing A. GitLab handles this fine and can show you changes
       | between the two revisions; GitHub is completely lost.
        
       | Pxtl wrote:
       | This feels like a workaround for git's contradictory ergonomics.
        
       | jwpapi wrote:
       | This is probably driven to be more usable with AI agents, but
       | smaller prs can create more code as they need to enforce more
       | backwards compability, this can also lead to more code or more
       | maintenance work.
       | 
       | Honestly I don't see the benefit of smaller prs, except driving
       | vanity scores?
       | 
       | Like I'm not saying you should
        
       | jen20 wrote:
       | I'm surprised no-one has commented on the "sign up for the
       | waitlist" button being a Microsoft Office form that wants your
       | email address and GitHub handle. This feels like an elaborate
       | phishing attack more than a serious feature announcement.
        
       | godzillafarts wrote:
       | "You cannot merge a PR in the middle of the stack before the PRs
       | below it are merged."
       | 
       | Huh? Some stacks need to land all at once and need to be reviewed
       | (and merged) from the top down. It's not uncommon, in my org at
       | least, to review an entire stack and merge 3 into 2 and then 2
       | into 1 and then 1 into main. If 2 merges before 3, you just
       | rebase 3 onto 1.
        
       | j3g6t wrote:
       | Super excited to give this a whirl - i've been messing with
       | graphite's `gt` command for stacking and it's been relatively
       | decent but I didn't love needing to bring in another
       | tool/service/account when I only care about the stacking
       | behaviour. Was a fun experiment but nice I can simplify back onto
       | `gh` and `git`
        
         | mattstir wrote:
         | I hope that GitHub continues copying Graphite's homework in
         | terms of functionality, because from what I can see they don't
         | have equivalents to `gt split`, absorb, and so on. Those can be
         | very useful in the right contexts.
        
       | silverwind wrote:
       | This needs to be supported on `git` level first imho, not by a
       | forge vendor.
        
         | steveklabnik wrote:
         | What would this being supported by git mean to you?
        
       | prakashn27 wrote:
       | Meta has something similar to this using mercurial. It was
       | awesome.
        
       | altano wrote:
       | The `gh stack` CLI sounds essential for people using git, but I
       | hope it doesn't become required, as people using things like
       | jj/sl should be able to work with stacks. `gs submit`/`gs push`
       | being the interface is fine, but `gs init` and `gs add` should be
       | optional.
        
         | steveklabnik wrote:
         | They confirmed below that you should be able to use this with
         | jj just fine, just like you can already use gh to create a PR
         | that you've authored with jj:
         | https://news.ycombinator.com/item?id=47759426
        
       | latentdream wrote:
       | the Website for the release statement look soooooo bad
        
       | solaire_oa wrote:
       | Pretty cool to see stacks being given due attention. Also check
       | out git-spice, which works with Gitlab (possibly others).
       | Personally I use git-spice in place of all the conventional git
       | commands.
        
       | meric_ wrote:
       | I loved using sapling / mercurial so much at work that I ended up
       | using the sapling SCM vsc extension at home all the time for
       | personal work.
       | 
       | Only downside is that Phabricator is not open source so viewing
       | it in most things sucks. Hoping now I can get a much better
       | experience
        
         | mhh__ wrote:
         | Phabricator is open source and has been for years. It has had a
         | bumpy ride over the last few years though. Although I guess
         | having written that I assume the internal meta one is much
         | better
        
           | meric_ wrote:
           | Huh, that's news to me. I had to do some googling and the
           | only one I could find was by Phalicity which seems to be from
           | a Meta employee who left and made it into a company (a la
           | Statsig, or to some extent Graphite)
           | 
           | Seems that company shutdown though a while ago and it got
           | forked into Phorge, but either way I assume there's some
           | divergence from what's internal at this point.
           | 
           | Still I'll look into it, it does look neat and might suit my
           | preferences still. Thanks for the headsup :)
        
       | mhh__ wrote:
       | 1. Finally. Pull requests are consanguine and bizarre.
       | 
       | 2. I'm not a huge fan of having to use a secondary tool that
       | isn't formally a layer around git / like jj as opposed to git
       | _hub_
        
       | mhh__ wrote:
       | I think the core conceptual difference between a stacked diff and
       | PRs as we use them in open source is the following:
       | 
       | A PR is basically a cyberspatial concept saying "I, as a dog on
       | the internet, am asking you to accept my patches" like a mailing
       | list - this encourages trying to see the truth in the whole. A
       | complete feature. More code in one go because you haven't pre-
       | agreed the work.
       | 
       | Stacks are for the opposite social model. You have already agreed
       | what you'll all be working on but you want to add a reviewer in a
       | harmonious way. This gives you the option to make many small
       | changes, and _merge from the bottom_
        
       | ruined wrote:
       | man, why is this waitlisted. this should have been a feature 10
       | years ago
        
       | sbinnee wrote:
       | Is this going to be a part of triage task? If so, it makes sense.
       | Whether a human developer or an AI made a big PR, AI goes review
       | it and if necessary makes stacked PRs. I don't see any human
       | contributors using this feature to be honest because it's an
       | extra work and they should have found a better way to suggest a
       | large PR.
        
       | zmmmmm wrote:
       | Curious how / how well it deals with conflicts in the different
       | branches that are part of the stack. Is there some support for
       | managing that, or what happens when two of the branches don't
       | rebase / merge cleanly?
        
         | mattstir wrote:
         | > If a rebase conflict occurs, the operation pauses and prints
         | the conflicted files with line numbers. Resolve the conflicts,
         | stage with git add, and continue with --continue. To undo the
         | entire rebase, use --abort to restore all branches to their
         | pre-rebase state.
         | 
         | So it tries to replay commits in the stack and will stop
         | halfway through that individual stack (layer?) to let you fix
         | it if there's a conflict.
        
       | conor_f wrote:
       | This just reeks to me of bad practice. Why use this as opposed to
       | breaking your change into smaller PRs and merging them
       | individually behind a feature flag or similar? With this, you
       | have a marginally better UX for reviewing through the Github
       | website, but the underlying issues are the same. The change being
       | introduced is not sufficiently testable by itself, or it's
       | (somehow) too tightly coupled to other parts of the UI/codebase
       | that it can't be split. You still need to test for integration
       | issues at every point of the stack, and some architecture issues
       | or points of code reuse can't be seen from stacked changes like
       | this.
       | 
       | Not for me, but I'm glad it fits other people's workflows. I just
       | hope it doesn't encourage people to try make poorly reasoned
       | changes!
        
         | gpm wrote:
         | When I've reached for stacked PRs (in the past, not using this
         | feature) it's precisely because I've split my change into
         | smaller PRs being merged individually.
         | 
         | I've just written those smaller PRs at once, or in quick enough
         | succession that the previous PRs weren't merged before the
         | later ones were ready. And the later ones relied on the
         | previous ones because that's how working on a feature works.
         | 
         | The earlier PRs are absolutely reviewable and testable without
         | relying on the later ones. The later ones are just treating the
         | earlier ones as part of the codebase. I.e. everything here
         | looks like two different PRs except the timing.
         | 
         | An obvious example would be "implement API for a feature" and
         | then "implement UI that uses that API". Two different PRs. The
         | second fundamentally relies on the first.
        
           | scaryclam wrote:
           | I do this as well, but there is a workflow problem to solve
           | and that is: getting PRs merged when they need to be to
           | continue working.
           | 
           | It's not a simple problem to solve, we can't all just jump
           | because someone finished some work after all. But if the PRs
           | are OK to rubber stamp, and merge, and they're safely behind
           | a feature flag, then it could just be as simple as letting
           | the submitter merge without the need for an extra review.
           | That can of course be contentious, but then we can ask "why
           | not?" and figure out what non-human gateways need to be added
           | to help make it possible etc.
           | 
           | I'm finding myself increasingly interested in understanding
           | what friction can be removed from the software review, merge
           | and release process, without sacrificing safe, well tested,
           | understandable code that follows good standards.
        
           | conor_f wrote:
           | This is a perfect example that I've often seen in practice.
           | There's nothing blocking in this workflow at all, and no
           | reason these changes cannot be made in independent changes.
           | e.g.
           | 
           | 1) API implementation - Including tests and docs this should
           | be perfectly acceptable to merge and review independently 2)
           | UX implementation - Feature flagged, dummy API responses,
           | easy to merge + review 3) One quick "glue" PR where the
           | feature can be integration tested etc
           | 
           | This prevents awful merge conflicts, multiple rounds of
           | increasingly complex stacked reviews, and a host of other
           | annoyances.
           | 
           | Is there any reason that the stacked PR workflow is better
           | that I'm ignoring or overlooking?
        
             | gpm wrote:
             | You're creating more work for no reason. There is
             | absolutely no reason to make dummy API responses, a feature
             | flag (well unless you want to delay public release of the
             | features - domain dependent here), or a glue PR.
             | 
             | Moreover you haven't even eliminated the dependency. The UI
             | PR requires knowing that the dummy API responses you've
             | created fit the right format - i.e. approval of the API PR
             | up to small nits.
             | 
             | Just test against the actual implementation from the start.
             | Even without stacked PRs just leave the second as a draft
             | with both sets of commits until the first is merged then
             | rebase and make it.
             | 
             | Stacked PRs are superior here because they eliminate that
             | extra work of the draft PR and parallelize the review
             | process slightly better.
        
       | cadamsdotcom wrote:
       | The vibecoded frontend makes the product look like a side
       | project.
       | 
       | Is it?
        
         | steveklabnik wrote:
         | It was announced in like November of last year, so it's
         | certainly taken some time. The announcement was by some senior
         | management at GitHub, so it has some degree of buy-in.
        
       | lpeancovschi wrote:
       | this was released about 7 years ago, no?
        
       | fphilipe wrote:
       | I've been doing stacked PRs for ~2 years now. Thus, I don't quite
       | see the need for this CLI. Git has had some additions in the last
       | few years that make this work natively - specifically the
       | --update-refs flag[1] or the rebase.updateRefs config. Combined
       | with `git commit --fixup`, rebase.autoStash, and
       | rebase.autoSquash rebasing stacks becomes a breeze (as long as
       | you work off from the tip of your stack). Add in git-absorb[2]
       | and the heavy-lifting is taken care of.
       | 
       | My biggest gripe with GitHub when working with stacks - and
       | something that's not clarified in these docs - is whether fast-
       | forward merges are possible. Its "Merge with rebase" button
       | _always_ rewrites the commit. They do mention that the stack
       | needs to be rebased in order to merge it. My workaround has been
       | `git merge --ff-only top-branch-of-stack` to merge the entire
       | stack locally into main (or anything in between actually) and
       | then push. GitHub neatly recognizes that each PR in the stack is
       | now in main and marks them all as merged. If there are subsequent
       | PRs that weren 't merged it updates the base branch.
       | 
       | Having said that, it's great to see GitHub getting a proper UI
       | for this. It's also great that it understands the intent that
       | branch B that goes on top of branch A is a stack and thus CI runs
       | against. I just hope that it's not mandatory to use their CLI in
       | order to create stacks. They do cover this briefly in the FAQ[3],
       | but it might be necessary to use `gh stack init --adopt branch-a
       | branch-b branch-c`. On the other hand, if that removes the need
       | to manually create the N PRs for my stack, that's nice.
       | 
       | [1]: https://git-scm.com/docs/git-rebase#Documentation/git-
       | rebase...
       | 
       | [2]: https://github.com/tummychow/git-absorb
       | 
       | [3]: https://github.github.com/gh-stack/faq/#will-this-work-
       | with-...
        
         | locknitpicker wrote:
         | > Git has had some additions in the last few years that make
         | this work natively - specifically the --update-refs flag[1] or
         | the rebase.updateRefs config. Combined with `git commit
         | --fixup`, rebase.autoStash, and rebase.autoSquash rebasing
         | stacks becomes a breeze (as long as you work off from the tip
         | of your stack). Add in git-absorb[2] and the heavy-lifting is
         | taken care of.
         | 
         | ...or you don't bother with all that and simply do:
         | 
         | - gh stack init
         | 
         | - gh stack push
         | 
         | - gh stack submit
        
           | fphilipe wrote:
           | Sure, that's possible. I can also use the GitHub app and use
           | a Git abstraction where I don't have to understand Git at
           | all.
           | 
           | The point is that I want to use Git, a tool and skill that is
           | portable to other platforms.
        
             | locknitpicker wrote:
             | > The point is that I want to use Git, a tool and skill
             | that is portable to other platforms.
             | 
             |  _You_ want to use git.
             | 
             | Most people around you want to get things done.
        
             | KptMarchewa wrote:
             | That's like, most AI obsoleteable skill you could pick.
        
               | philwelch wrote:
               | Not at all. One of the tricks of using AI is context
               | management and managing the Git history yourself can be a
               | big part of that. If the AI has a stupid idea and
               | implements it, even when you tell it, "that was a stupid
               | idea, don't do that, change it back", the history could
               | persist and the stupid idea will poison the context
               | window every time an agent reads the commit history. It's
               | even worse if _you_ had the stupid idea!
               | 
               | Also, my current workflow actually has hooks to block
               | agents from creating or changing commits. I know at some
               | point this will be a limit to scaling, but I think that
               | will result in me spending more rather than less time in
               | git.
        
         | pksunkara wrote:
         | I think the CLI is useful for pushing. What do you use to push
         | all the rebased child branches?
        
           | fphilipe wrote:
           | My git config for pushing is set to push.default=current. For
           | rebased stacks I have an alias that does this:
           | git --config push.default=matching push --force-with-lease
           | --force-if-includes
           | 
           | In other words, I force push all branches that have a
           | matching upstream by changing my config on the fly.
        
       | rs545837 wrote:
       | This is awesome honestly, Stacked PRs are one of those features
       | that feels obvious in hindsight. Breaking a n-line PR into 3
       | focused layers where each one is independently reviewable is a
       | huge win for both the author and reviewer. The native GitHub UI
       | with the stack navigator is the right call too, and there's no
       | reason this should require a third-party tool.
       | 
       | One thing I keep thinking about in this same direction: even
       | within a single layer of a stack, line-level diffs are still
       | noisy. You rename a function and update x call sites, the diff
       | shows y changed lines. A reviewer has to mentally reconstruct "oh
       | this is just a rename" from raw red/green text.
       | 
       | Semantic diffing (showing which functions, classes, methods were
       | added/modified/deleted/moved) would pair really well with stacks.
       | Each layer of the stack becomes even easier to review when the
       | diff tells you "modified function X, added function Y" instead of
       | just showing changed lines.
       | 
       | I've been researching something in this direction,
       | https://ataraxy-labs.github.io/sem/. It does entity-level diffs,
       | blame, and impact analysis. Would love to see forges like GitHub
       | move in this direction natively. Stacked PRs solve the too much
       | at once problem. Semantic diffs solve the "what actually changed"
       | problem. Together they'd make code review dramatically better.
        
       | MASNeo wrote:
       | Very curious about this as especially with more use of AI in the
       | development process I have seen PR size has increased. So looking
       | forward to general availability.
        
       | boomlinde wrote:
       | IME the github workflow promotes bad commit hygiene by making
       | squashing or rebasing as-is an either-or choice in the web GUI.
       | 
       | This will help some since you can more easily split PRs into
       | units that make sense to squash at the end, but it still seems
       | like not doing this on a per-commit basis is a disadvantage
       | compared to Gerrit. With Gerrit I can use all the built-in Git
       | rebase/squash/fixup tools to manage the commit stack and push
       | everything in one go. I don't think there's a nearly as
       | convenient a way to work with stacked branches in Git.
        
       | baalimago wrote:
       | Sounds like a merge-conflict nightmare
        
       | srvaroa wrote:
       | This feature is 10 years late
        
       | AJRF wrote:
       | I have never got a good answer to "can't you just make smaller
       | PRs". This is convoluted tooling (needs its own CLI) for
       | something you could achieve with just learning how git works.
        
         | hambes wrote:
         | I agree that a `gh stack` command is not needed, but this feels
         | to me like just a better UI feature for a good git workflow. It
         | literally is about making multiple smaller PRs that build on
         | top of each other.
        
           | scaryclam wrote:
           | The question is, why are you not just merging them into main
           | as you go? It's a bit of a smell when you "need" to merge
           | branches into branches. It shows a lack of safety and ease in
           | deployments, which is the real problem to solve IMO.
        
             | dontlikeyoueith wrote:
             | Because sometimes there are changes that need to land as
             | all or nothing.
        
         | gugagore wrote:
         | If there is a stack of size n and you make a modification at
         | the first change, closest to the trunk, is there a single git
         | command you can run to rebase the other n-1 branches and ensure
         | they remote branches are updated?
        
           | Liskni_si wrote:
           | Not a single one, but it can be done with 2.
           | 
           | Assuming you're currently on the most recent branch (furthest
           | from the trunk), `git rebase -i --update-refs trunk` will
           | rebase all the intermediate branches. If you need to make a
           | change to the first branch nearest the trunk, either use
           | `edit` in the interactive rebase, or make a fixup commit and
           | enable autosquash for the rebase. The `--update-refs` flag
           | makes sure that all the intermediate branches get updated
           | during the rebase.
           | 
           | Then, to push them all, something like `git push origin
           | 'refs/heads/yourname/*'` will push all branches prefixed with
           | `yourname/`. It's a bit stupid that one can't just do `git
           | push 'yourname/*'` though.
        
         | poszlem wrote:
         | Right, so 'just work the way the tool requires instead of
         | making the tool work the way you want'. I would prefer the tool
         | worked the way I want and the way I think of the changes
         | instead.
        
         | avita1 wrote:
         | IMO this tool is basically allowing you to do that, it just
         | takes care of the bookkeeping to associate the series of
         | smaller PRs with eachother which is possible today but requires
         | a lot of clicking.
        
       | nonoesp wrote:
       | First thing that came to mind was git butler.
        
       | metafeather wrote:
       | I've been using `git town`[1] for years to managed stacked PR's
       | alone with Github PR's[2] and juniors I have introduced it to
       | have really found it a helpful mental model when developing
       | features.
       | 
       | I hope the Gitub CLI will include syncing[3] 'stacks' locally
       | with upstream in a similar way.
       | 
       | [1]: https://www.git-town.com/stacked-changes.html
       | 
       | [2]: https://github.com/marketplace/actions/git-town-github-
       | actio...
       | 
       | [3]: https://www.git-town.com/commands/sync.html
        
       | netheril96 wrote:
       | Does this work from a fork? That is, can I file a stacked PR to a
       | project not owned by me, by creating branches in my forked
       | project? Previously I asked AI about how to contribute stacked
       | PR, it told me that I can only do it when I have push privileges
       | to the repo, not from a fork, and the doc here is ambiguous.
       | 
       | ----
       | 
       | OK, I found this from official docs, so this feature is now quite
       | useless to me:
       | 
       | > Can stacks be created across forks?
       | 
       | > No, Stacked PRs currently require all branches to be in the
       | same repository. Cross-fork stacks are not supported.
        
       | elAhmo wrote:
       | Hah, first time seeing github.github.com
        
       | vedant_awasthi wrote:
       | This is useful. Managing dependencies across PRs has always been
       | tricky -- nice to see better workflows evolving.
        
       | vedant_awasthi wrote:
       | Interesting direction. Curious how this compares with traditional
       | transformer-based approaches in real use cases.
        
       | sajithdilshan wrote:
       | I already do this using git branched. Whenever I have features
       | that depends on one another I create a feature branch and then
       | stack branches on top of each other for individual feature so
       | it's easy for the reviewer to go through the code and and also
       | keep the PR size quite small. Also this gives me freedom to push
       | more than one commit for each branch to fix things.
       | 
       | The only annoying part is that I have to keep on merging the base
       | branch to the feature branch constantly to keep it up-to date. If
       | Github can provide a feature to do that automatically, then that
       | would be perfect. Other than that, I don't see any advantage on
       | this stacked PR approach they are proposing.
        
       | jamesfisher wrote:
       | Reminder that if your agent can create PRs then it can merge them
       | too: https://github.com/orgs/community/discussions/182732
        
       | balamatom wrote:
       | Oh cool, soon people will stop being incapable of working with
       | me.
        
       | samsin wrote:
       | 'Large pull requests are hard to review' is a good reason to keep
       | PRs small, but small PRs also encourage continuous
       | integration/delivery/deployment. Stacked PRs sound like they
       | encourage long-lived feature branches instead.
        
         | dontlikeyoueith wrote:
         | Depends on what you consider long-lived.
         | 
         | I typically generate stacks of 3-5 PRs in 1-2 days now (in a
         | gen-AI world).
        
       | nathas wrote:
       | Meanwhile, you still can't do fast-forward merges in GitHub
       | :clown: https://github.com/orgs/community/discussions/4618
       | 
       | And it doesn't even rebase and merge correctly with fast-forward
       | if there it's a clean set of commits!
       | https://github.com/orgs/community/discussions/5524
        
         | charles_f wrote:
         | > :clown:
         | 
         | We're neither on reddit nor on twitter, avoid that please.
        
           | surajrmal wrote:
           | Right. Just use directly.
        
           | tele_ski wrote:
           | It is a table stakes missing feature.. for a long time. Clown
           | seems appropriate, every project I've worked on in github we
           | end up copying a github yml action to allow us to do this
           | with one comment '/fast-forward', just is silly at this point
           | that github doesn't natively support it.
        
       | sylware wrote:
       | microsoft broke nearly all classic web support (noscript/basic
       | (x)html).
       | 
       | Since I can still login, is there a web API (using CURL and some
       | identifying session token I could retrieve from my login) I could
       | use to actually do "something". For instance, be involved in the
       | issues of some project?
       | 
       | (for me, that would be mostly valve stuff on linux based OSes)
       | 
       | Any pointers?
        
       | Liskni_si wrote:
       | It's awesome that they're adding a UI for stacked branches1! The
       | UX of the CLI tool seems weird, though. Why do I need to
       | explicitly create and add branches to the stack if all I really
       | want is to open PRs from my commits? Here's the workflow that I
       | built for myself instead:
       | 
       | [?] `git checkout -b feature-branch-xyz`
       | 
       | [?] make a few commits, perhaps some fixups, rebase, whatever
       | 
       | [?] start tig, look at the history, decide at which points I want
       | to break the branch into stacked PRs, and mark those points using
       | shift-s (which calls my own `git gh-stack branch create $commit`
       | and creates a specially named branch there)
       | 
       | [?] `git gh-stack sync` -- collects all the specially named
       | branches, builds a graph of how they're stacked on one another,
       | pushes them, opens stacked PRs
       | 
       | GitHub has had some "support" for stacked PRs for a while, so
       | merging the first one to main will automatically change the
       | target branch of the second to main.
       | 
       | If I need to change anything, I can just `git rebase
       | --interactive --update-refs`, amend commits, split commits,
       | rearrange commits, and then running `git gh-stack sync` will
       | update the PRs for me. If I split a commit in the middle and
       | shift-s to mark it, it will open an extra PR and restack
       | everything to update the order.
       | 
       | Furthermore, the "PR stack" doesn't actually need to be a stack
       | (linear chain), it can be a tree. If I know that some commits are
       | independent of the rest, I don't need to create a separate stack,
       | I just create another local branch, mark PR-ready commits with
       | shift-s, and `git gh-stack sync` will do the right thing. If I
       | need to rebase the whole tree on top of current main, then `git
       | rebase -i --rebase-merges --update-refs` does the job.
       | 
       | I guess what I'm saying is that as someone who's been using git
       | since its inception, it feels much more natural to just do
       | everything in git, and then have a single command that pushes my
       | work to GitHub. And I think this might work even better with
       | jujutsu -- just point `git gh-stack sync` at the branches jj
       | makes and it'll make a stack/tree of PRs out of them. :-)
       | 
       | https://github.com/liskin/dotfiles/blob/home/bin/git-gh-stac...
       | if anyone's curious. It's just a few hundred lines of code.
       | Building the graph is done by `git log --simplify-by-decoration`.
       | Opening PRs is shelled out to `gh pr create`.
       | 
       | 1) I mean, I'd much rather they added a UI for reviewing PRs
       | commit-by-commit, with the option to approve/request-changes on
       | each, and the possibility to merge the first few approved ones
       | while continuing work on the rest... But in a world of almost
       | every $dayjob insisting on squash-merging, a UI for stacked PRs
       | is a total game changer, positively.
        
       | iknownthing wrote:
       | That page looks vaguely AI generated
        
       | choi0330 wrote:
       | Wait. I built pilegit, Stacked PR solution.
       | 
       | All in all, pilegit works with Github, Gitlab, Phabricator,
       | Gitea, and custom.
       | 
       | How about https://github.com/hokwangchoi/pilegit?
        
       | boisterousness wrote:
       | Stacked Git (StGit) [1] is a git CLI add-on for working with
       | stacked commits in your local repo.
       | 
       | Why are stacked commits useful? Multiple patches can be developed
       | concurrently and efficiently, with each patch focused on a single
       | concern, for a clean Git commit history and improved
       | productivity. The tutorial [2] says:
       | 
       | > One common use of StGit is to "polish" a Git branch before
       | publishing it to another public repository. The kinds of polish
       | that StGit can help with include:                   Complete and
       | correct commit messages.         Each patch limited to one
       | coherent topic.         Each patch standing on its own: passing
       | tests, etc.         Considerate patch (commit) order
       | 
       | > Careful curation of Git commit history, as enabled by StGit,
       | can be of high value to those reviewing pull requests or trying
       | to understand why or how code came to be the way it is. ...
       | 
       | > As a concrete example, consider a situation where several Git
       | commits have been made in a repository with commit messages such
       | as:                   "Improve the snarfle cache"         "Remove
       | debug printout"         "New snarfle cache test"         "Oops,
       | spell function name correctly"         "Fix documentation error"
       | "More snarfle cache"
       | 
       | > While the above may be the "true" history of commits to the
       | repository, it may not be the history that is most helpful to
       | code reviewers or the developer who needs to understand what
       | happened in this area of the code six months after the fact.
       | Using StGit, this history can be revised to be higher quality and
       | higher value.
       | 
       | Originally written in Python (2005, pre-GitHub) by Catalin
       | Marinas, the current version is in Rust. StGit is free and open
       | source [3]. It was inspired by Quilt [4], an earlier system
       | credited to Andrew Morton and Andreas Grunbacher.
       | 
       | [1] https://stacked-git.github.io/ [2] https://stacked-
       | git.github.io/guides/tutorial/#development-b... [3]
       | https://github.com/stacked-git/stgit/ [4]
       | https://en.wikipedia.org/wiki/Quilt_(software)
        
       ___________________________________________________________________
       (page generated 2026-04-14 23:01 UTC)