All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alejandro Colomar <alx@kernel.org>
To: Nico Williams <nico@cryptonector.com>
Cc: git@vger.kernel.org
Subject: Re: git-rebase-walk
Date: Thu, 1 Oct 2026 18:50:08 +0200	[thread overview]
Message-ID: <ar6LUeH3AjxbiMgd@debian> (raw)
In-Reply-To: <ar6GExDLasWWFajm@ubby>

[-- Attachment #1: Type: text/plain, Size: 5039 bytes --]

Hi Nico,

> Date: 2026-10-01 11:10:59-0500
> From: Nico Williams <nico@cryptonector.com>
>
> On Thu, Oct 01, 2026 at 01:58:42PM +0200, Alejandro Colomar wrote:
> > I use this little command to apply iterative rebases, which are easier
> > to handle when there are large conflicts.  Are you interested in it?
> > 
> > 	$ cat $(which git-rebase-walk)
> > 	#!/bin/bash
> > 
> > 	set -Eeufo pipefail;
> > 
> > 	git merge-base HEAD "$1" \
> > 	| xargs -I{} git log --oneline {}.."$1" \
> > 	| cut -f1 -d' ' \
> > 	| tac \
> > 	| while read -r c; do
> > 		git rebase "$c";
> > 	done;
> 
> You could simplify this pipeline to:
> 
>     git log --reverse --format=%H $(git merge-base HEAD "$1").."$1" |
>     while read c; do git rebase "$c"; done

Actually, I've simplified it to:

	$ cat $(which git-rebase-walk)
	#!/bin/bash

	set -Eeufo pipefail;

	git merge-base HEAD "$1" \
	| xargs -I{} git rev-list {}.."$1" \
	| tac \
	| while read -r c; do
		git rebase "$c";
	done;

since git-rev-list(1) is the plumbing command (IIUC).

I prefer the explicit tac(1) instead of --reverse.  It's simpler
conceptually (we don't need to know/remember that there exists a
--reverse flag to git-rev-parse(1) nor to understand its exact meaning).
tac(1) is well known.  The performance doesn't change much, IME
(sometimes better; sometimes worse).

I also prefer to use a pipe with xargs(1), since it keeps each command
short and readable, without nested commands inside arguments to other
commands.

> 
> But:
> 
>  - you need to add conflict handling
>  - this is very slow

I have it running on the background while doing other stuff, and when
it stops at a conflict, I look at it.

> I've tried this before, so I know it's very slow if you're rebasing
> across thousands of upstream commits!

Yes, it is.  When I did this manually before writing the tool, I did
roughly a binary search of the conflicts.  That'd be faster, and if
implemented as part of git(1), it would make sense to implement it that
way.  For my use case, I could live with a slow thing in the background,
which is why I chose to keep it robust.

I expect it wouldn't be that hard to do a binary search within a script.

> Also, you need some extra handling of conflicts.

No, that's the nice part.  It works as is.  When I see a conflict, I get
stopped at the rebase that caused the issue.  I solve that conflict, and
then can --continue that one rebase.  Or I can --abort that one rebase.

Once I've --continue'd, it ends at that one rebase, and doesn't continue
the walk.  I must run git-rebase-walk again for resuming the
rebase-walk, which allows me to see the status before doing it.

> > The source code is trivial, so I guess I don't need to explain much.
> > It behaves quite nicely, IME.
> 
> It can be much too slow.  I've a better solution: bisect-rebase.sh:
> 
> https://gist.github.com/nicowilliams/ea2fa2b445c2db50d2ee6509c3526297

Hmmm, 93 LoC is certainly more interesting than the 4k+ python script.
I'll have a look.  I'll also attempt at writing a bisect-rebase from
scratch myself, to compare.

> (The first revision of that gist is slow-rebase.sh, which is a linear
> rebase like the one you posted.)
> 
> This script very efficiently finds the firts upstream commit that your
> branch conflicts with, asks the user to resolve conflicts, then resumes
> rebasing.

Indeed, this is what I did manually before writing my slow script, so it
seems you've had the same needs and line of thought that I had.  :)

> So let's say that your upstream has 1,000 commits you need to rebase
> across, and 10 of those introduce conflicts (assume there's no reverts
> of those for now), then this script will ask you to resolve conflicts 10
> times, and each time it's clear which pair of local and upstream commits
> conflict so you have the best possible context for conflict resolution.
> 
> It's like git-imerge, but better in that it's specifically geared to
> rebase workflows.
> 
> I've successfully used this bisect-rebase.sh script to rebase a
> postgresql fork across between 1,000 and 2,000 commits twice, each time
> with significant conflicts to resolve that were much too difficult to
> resolve with a plain rebase.  I.e., a plain `git rebase origin/master`
> produced large conflicts where I didn't have enough context, but
> bisect-rebase.sh let me resolve much smaller conflicts with a new base
> that immediately introduced those conflicts, so I always had the right
> context for resolving them.
> 
> PG is a perfect test case for this sort of thing because it's so large
> and moves so fast.

I'll certainly try your script; thanks!

Out of curiosity, did you offer this script to git(1)?
If not, why not?
If yes, what happened?

This is something that would clearly be helpful to people solving rebase
conflicts in many projects.


Have a lovely night!
Alex

> 
> Nico
> -- 

-- 
<https://www.alejandro-colomar.es>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2026-10-01 16:50 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-01 11:58 git-rebase-walk Alejandro Colomar
2026-10-01 13:22 ` git-rebase-walk Patrick Steinhardt
2026-10-01 15:51   ` git-rebase-walk Alejandro Colomar
2026-10-02  6:46     ` git-rebase-walk Patrick Steinhardt
2026-10-02  7:19       ` git-rebase-walk Alejandro Colomar
2026-10-03 19:37         ` git-rebase-walk Nico Williams
2026-10-04 10:03       ` git-rebase-walk Phillip Wood
2026-10-05 13:28         ` git-rebase-walk Alejandro Colomar
2026-10-05 13:37           ` git-rebase-walk Alejandro Colomar
2026-10-06 14:01             ` git-rebase-walk Phillip Wood
2026-10-06 14:58               ` git-rebase-walk Nico Williams
2026-10-06 16:45                 ` git-rebase-walk Alejandro Colomar
2026-10-08 22:05               ` git-rebase-walk Alejandro Colomar
2026-10-08 22:07                 ` git-rebase-walk Alejandro Colomar
2026-10-01 17:31   ` git-rebase-walk Junio C Hamano
2026-10-01 16:10 ` git-rebase-walk Nico Williams
2026-10-01 16:50   ` Alejandro Colomar [this message]
2026-10-01 17:40     ` git-rebase-walk Nico Williams
2026-10-01 20:29       ` git-rebase-walk Alejandro Colomar
2026-10-01 21:01         ` git-rebase-walk Nico Williams
2026-10-01 21:35           ` git-rebase-walk Nico Williams
2026-10-02  2:49 ` git-rebase-walk Simon Richter
2026-10-02  3:19   ` git-rebase-walk Nico Williams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ar6LUeH3AjxbiMgd@debian \
    --to=alx@kernel.org \
    --cc=git@vger.kernel.org \
    --cc=nico@cryptonector.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.