git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Triangular workflows

From
D. Ben Knoble <ben.knoble@gmail.com>
Date
Jan 5, 2026, 22:36 UTC
Message-ID
<CALnO6CAUSU-Pq_r-WYm3o0to6H8MdqiYOuoKaRfL1PTt30VaoQ@mail.gmail.com>
In-Reply-To
<CALnO6CB7-w0tNMiYn5=SCBow637vRRrKRj_9k1h1DS4crJaVtQ@mail.gmail.com>
On Mon, Jan 5, 2026 at 5:19 PM D. Ben Knoble <ben.knoble@gmail.com> wrote:
Show 50 quoted lines
>
> On Thu, Jan 1, 2026 at 2:43 PM Harald Nordgren <haraldnordgren@gmail.com> wrote:
> >
> > Hi Ben!
> >
> > Did you ever get to this? And does it match what I do in the tests for PATCH v10:
> >
> > ```
> > git config remote.pushDefault origin
> > git branch --set-upstream-to upstream/main
> > ```
> >
> >
> > Harald
>
> Yeah, that's definitely part of it for me. I've been meaning to write
> this down elsewhere for a while, but here's what my setup for
> triangular workflows looks like.
>
> First, there are typically 2 remotes (but not always!). In the
> examples, I'll use "origin" (the place I usually cloned from first,
> the most official version of the code, etc.; also the place I pull
> from) and "benknoble" (the place I push to). The setup works just fine
> with a single origin, though.
>
> Next, I globally configure
>
>     push.default = current
>     pull.rebase = true
>     branch.autoSetupRebase = always
>
> The first works with other settings to make the @{push} ref work (and
> to make "git push" work without arguments). I really like the @{push}
> ref, and I'm not aware of any other way to enable it.
>
> Then, when setting up a repository I configure remotes and make sure
> to configure
>
>     remote.pushDefault = benknoble
>
> (if there is such a remote).
>
> The next step is usually starting a branch:
>
>     git switch -c branch origin # or origin/main, or whatever
>
> With the above settings, I immediately have
> - branch@{upstream} (@{u}) -> origin/…
> - branch@{push} (@{push}) -> benknoble/branch (or origin/branch,
> depending on the case)
Premature send :/

Anyway, after working for a bit, I can use "git pull" to synchronize with upstream via rebasing (since it's WIP, I don't mind, though for Git I have to remember to --keep-base anytime I rebase). Ditto for "git rebase" without a fetch, or when squashing ("git rs" = "git rebase --autosquash"). When I want to send out a new version, I "git push" (or "pf", an alias for "push --force-with-lease"; additionally I've already configured push.useForceIfIncludes = true); I typically first take a range-diff as described in my other mail (alias: rdup does "git range-diff @{upstream} @{push} @" and rdupc does "git rdup | copy-range-diff").

The last piece of the puzzle for me are "interrogation commands": like "git status", where am I wrt to all these branches? I use 2

- "git sbup" is my alias for "git show-branch HEAD HEAD@{upstream} HEAD@{push}"
- "git div" is described at [1], but it draws a graph between my HEAD
and either upstream or push, depending on whether I've already pushed
out the current version (the newest version [2] is a bit smarter than
the original post describes). The graph uses cherry-mark and some
other options so I can decide how to handle divergence: do I need to
integrate someone else's changes? From which branch? How? I also use
this a lot to look between a new release candidate and a past release
at work to make sure we're not missing any patches that might have
gone in on the last release branch but not into the latest candidate.
And with repositories that commit accepted patches to the trunk, I
know I can delete my branch when "git div" shows all "=", even though
Git refuses without "--force" (for good and clear reasons, just a
note).

Anyway, my workflow for this all came about because I wanted to "git pull" and "git push" (and "git rebase") without arguments and still be able to sync from upstream while sending to another place for PR-style review.

The only downside so far is that "git div" in git.git can show too much information due to all the topic branch merges. Adding --first-parent helps, but the --boundary commits still make a mess for trying to view things. But in repositories that commit accepted patches directly to the main branch, it works great. (If anyone has a version of "show me the graph of divergence" that doesn't turn into a spider web when looking at git.git, LMK. A good test case is the recent je/doc-reset topic. I have a remote "broken-out" pointing at gitster/git on GitHub, and "git div broken-out/je/doc-reset origin/master" is difficult to read after the first few lines. But if you rebase it atop the latest master, it's very easy to see what's going on.)

[1]: https://benknoble.github.io/blog/2024/11/15/useful-utilities/#git [2]: https://github.com/benknoble/Dotfiles/blob/master/links/bin/git-div

-- 
D. Ben Knoble
Previous: D. Ben Knoble
Message 2 of 2 in “Re: Triangular workflows”
  1. D. Ben KnobleJan 5, 2026
  2. D. Ben KnobleJan 5, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.