Volume XXII, number 279Tuesday, October 6, 2026Latest message 21 minutes ago

The Git List

News and archive of git@vger.kernel.org, since April 2005

git-rebase-walk

18 messages between Oct 1, 2026 and Oct 5, 2026, from Alejandro Colomar, Patrick Steinhardt, Nico Williams, Junio C Hamano, Simon Richter, Phillip Wood.

Plain Markdown or JSON for tools and agents.

Alejandro ColomarOct 1, 2026, 11:58 UTC on lore
Hi!

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;

The source code is trivial, so I guess I don't need to explain much. It behaves quite nicely, IME.

You may of course want to adapt it a little bit for merging in git(1). I could help improve it a little bit.

Have a lovely day! Alex

-- 
<https://www.alejandro-colomar.es>
Patrick SteinhardtOct 1, 2026, 13:22 UTC in reply to Alejandro Colomar on lore

Re: git-rebase-walk

Hi,
On Thu, Oct 01, 2026 at 01:58:42PM +0200, Alejandro Colomar wrote:
Show 23 quoted lines
> Hi!
> 
> 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;
> 
> The source code is trivial, so I guess I don't need to explain much.
> It behaves quite nicely, IME.
> 
> You may of course want to adapt it a little bit for merging in git(1).
> I could help improve it a little bit.

this reminds me a bit of git-imerge [1]. What this tool does is to basically perform a merge between two branches incrementally using a matrix. The tool tries to address exactly your use case, which is to "present the user with one pairwise conflict at a time for resolution".

Maybe that tool is interesting to you. But it's certainly fallen a bit out of date, as it hasn't received any updates for more than 6 years by now. Chances are it stll works alright though.

Thanks!
Patrick
[1]: https://github.com/mhagger/git-imerge
Alejandro ColomarOct 1, 2026, 15:51 UTC in reply to Patrick Steinhardt on lore

Re: git-rebase-walk

Hi Patrick,
Show 34 quoted lines
> Date: 2026-10-01 15:22:02+0200
> From: Patrick Steinhardt <ps@pks.im>
>
> Hi,
> 
> On Thu, Oct 01, 2026 at 01:58:42PM +0200, Alejandro Colomar wrote:
> > Hi!
> > 
> > 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;
> > 
> > The source code is trivial, so I guess I don't need to explain much.
> > It behaves quite nicely, IME.
> > 
> > You may of course want to adapt it a little bit for merging in git(1).
> > I could help improve it a little bit.
> 
> this reminds me a bit of git-imerge [1]. What this tool does is to
> basically perform a merge between two branches incrementally using a
> matrix. The tool tries to address exactly your use case, which is to
> "present the user with one pairwise conflict at a time for resolution".

Yup, from the description, it seems to do the same thing. Thanks! I've also seen at least one other tool that does the same thing.

> Maybe that tool is interesting to you.

Not much, because I prefer a 9-line shell script that's robust as a rock vs. a 4k+ LoC python script for the same functionality. :-)

> But it's certainly fallen a bit
> out of date, as it hasn't received any updates for more than 6 years by
> now. Chances are it stll works alright though.

My script I use it in shadow-utils and in the Linux man-pages project, and is in use today. I was wondering if there was interest in integrating it to git(1). If not, I will likely provide it in the man-pages repository as a help tool (which might end up packed by distros as part of manpages-utils). Is that okay to you? (I ask mainly because it's using the git- namespace for commands, so you should at lease be aware of it.)

Have a lovely day! Alex

Show 6 quoted lines
> 
> Thanks!
> 
> Patrick
> 
> [1]: https://github.com/mhagger/git-imerge
-- 
<https://www.alejandro-colomar.es>
Nico WilliamsOct 1, 2026, 16:10 UTC in reply to Alejandro Colomar on lore

Re: git-rebase-walk

On Thu, Oct 01, 2026 at 01:58:42PM +0200, Alejandro Colomar wrote:
Show 15 quoted lines
> 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
But:
 - you need to add conflict handling
 - this is very slow

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

Also, you need some extra handling of conflicts.
> 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

(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.

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.

Nico
Alejandro ColomarOct 1, 2026, 16:50 UTC in reply to Nico Williams on lore

Re: git-rebase-walk

Hi Nico,
Show 24 quoted lines
> 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.

Show 5 quoted lines
> 
> 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.

Show 6 quoted lines
> > 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.

Show 6 quoted lines
> (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. :)

Show 20 quoted lines
> 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>
Junio C HamanoOct 1, 2026, 17:31 UTC in reply to Patrick Steinhardt on lore

Re: git-rebase-walk

Patrick Steinhardt <ps@pks.im> writes:
Show 5 quoted lines
> Maybe that tool is interesting to you. But it's certainly fallen a bit
> out of date, as it hasn't received any updates for more than 6 years by
> now. Chances are it stll works alright though.
>
> [1]: https://github.com/mhagger/git-imerge
;-)

imerge is one of the best things since sliced bread, and what I still occasinally fall back on when I encounter a really difficult merges and rebases.

Nico WilliamsOct 1, 2026, 17:40 UTC in reply to Alejandro Colomar on lore

Re: git-rebase-walk

On Thu, Oct 01, 2026 at 06:50:08PM +0200, Alejandro Colomar wrote:
Show 5 quoted lines
> > 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.
Oh, because of `set -euo pipefail`, hah, yes.
> > https://gist.github.com/nicowilliams/ea2fa2b445c2db50d2ee6509c3526297
> 
> Hmmm, 93 LoC is certainly more interesting than the 4k+ python script.
There is that, indeed.
> I'll have a look.  I'll also attempt at writing a bisect-rebase from
> scratch myself, to compare.
I love that attitude!
> I'll certainly try your script; thanks!
> 
> Out of curiosity, did you offer this script to git(1)?

No, though I think I've mentioned it here before. I'd be happy to submit a patch, but I'd first have to get employer approval for it (which is not a problem -- it will only take time).

> If not, why not?
No real reason other than bureaucracy on my side.
> This is something that would clearly be helpful to people solving rebase
> conflicts in many projects.
I agree!
> Have a lovely night!
Cheers!
Nico
Alejandro ColomarOct 1, 2026, 20:29 UTC in reply to Nico Williams on lore

Re: git-rebase-walk

Hi Nico,
Show 11 quoted lines
> Date: 2026-10-01 12:40:00-0500
> From: Nico Williams <nico@cryptonector.com>
>
> On Thu, Oct 01, 2026 at 06:50:08PM +0200, Alejandro Colomar wrote:
> > > 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.
> 
> Oh, because of `set -euo pipefail`, hah, yes.
:-)
Show 10 quoted lines
> > > https://gist.github.com/nicowilliams/ea2fa2b445c2db50d2ee6509c3526297
> > 
> > Hmmm, 93 LoC is certainly more interesting than the 4k+ python script.
> 
> There is that, indeed.
> 
> > I'll have a look.  I'll also attempt at writing a bisect-rebase from
> > scratch myself, to compare.
> 
> I love that attitude!
Heh!  Thanks!

I've already tried it, and it seems to work (I've only tried it once; I'll test it more before considering it stable).

Here's the implementation:
	$ cat $(which git-bisect-rebase)
	#!/bin/bash
	set -Eeufo pipefail;
	shopt -s lastpipe;
	tgt="$(git rev-list -1 "$1")";
	## Try a regular rebase.
	if
		git rebase "$tgt" >/dev/null 2>/dev/null;
		test $? -eq 0;
	then
		echo 'Successfully rebased.';
		exit 0;
	else
		echo '[conflict]';
		git rebase --abort >/dev/null 2>/dev/null;
	fi;
	## Bisect.
	while
		git merge-base HEAD "$tgt" \
		| xargs -I{} git rev-list {}.."$tgt" \
		| wc -l \
		| read -r n;
		test $n -gt 1;
	do
		if
			git merge-base HEAD "$tgt" \
			| xargs -I{} git rev-list {}.."$tgt" \
			| sed "$(echo "($n + 2) / 2" | bc)!d" \
			| read -r mid;
			echo "$n commits left to test in the target branch (trying $mid)";
			git rebase $mid >/dev/null 2>/dev/null;
			test $? -eq 0;
		then
			echo '[ok]';
		else
			echo '[conflict]';
			tgt="$(git rev-list -1 "$mid")";
			git rebase --abort >/dev/null 2>/dev/null;
		fi;
	done;
	## Perform the conflicting rebase
	echo "The conflict is at $tgt; about to rebase now.";
	git rebase "$tgt";
And here's now it behaves:
	$ git bisect-rebase agetpass
	[conflict]
	215 commits left to test in the target branch (trying 0482fd5f353c473268aff39e38513df2fb589a52)
	[conflict]
	108 commits left to test in the target branch (trying b21a76f759492f88388840d69f85b8d27ad5dffe)
	[conflict]
	54 commits left to test in the target branch (trying db3ca9f917efff9e2dab2fe36fa02fd6ef81ab08)
	[ok]
	27 commits left to test in the target branch (trying 4df3f783c4d936e6985590981a2ddaf0377a3785)
	[ok]
	13 commits left to test in the target branch (trying 93c675ef030e4eb226f60a317f3759755cd5bc5d)
	[ok]
	6 commits left to test in the target branch (trying b4adbe6387ae8d95dbe0bd547a157492842bea12)
	[conflict]
	3 commits left to test in the target branch (trying f7c712c3ade10c1d14916ea44408e42495fd1a8a)
	[conflict]
	2 commits left to test in the target branch (trying 0bb39793716a2466aa1f477e4634e9d86532df80)
	[ok]
	The conflict is at f7c712c3ade10c1d14916ea44408e42495fd1a8a; about to rebase now.
	Auto-merging src/gpasswd.c
	Auto-merging src/newgrp.c
	CONFLICT (content): Merge conflict in src/newgrp.c
	Auto-merging src/passwd.c
	CONFLICT (content): Merge conflict in src/passwd.c
	error: could not apply e22c98497c16... lib/, src/: Use getpassa()/passzero() instead of agetpass()/erase_pass()
	hint: Resolve all conflicts manually, mark them as resolved with
	hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
	hint: You can instead skip this commit: run "git rebase --skip".
	hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
	hint: Disable this message with "git config set advice.mergeConflict false"
	Could not apply e22c98497c16... # lib/, src/: Use getpassa()/passzero() instead of agetpass()/erase_pass()

It seems to work fine, and the source file uses 52 lines (including blank lines). The behavior seems intuitive, and not too verbose.

Now, compared to your script, the source length is similar (most of the difference is printf calls). I use more pipes, while you use shell features like arrays (I have a very hard time reading shell code that does heavy use of shell features). Other than that, they look fundamentally similar (except for the paragraph below). :)

One thing I'm surprised, though, is that you take two parameters instead of just the target branch. I very much prefer my script in this sense, which is like git-rebase(1), which rebases the active branch on top of the target commit. It's up to the caller to make sure that the active branch is the right one.

Show 7 quoted lines
> > I'll certainly try your script; thanks!
> > 
> > Out of curiosity, did you offer this script to git(1)?
> 
> No, though I think I've mentioned it here before.  I'd be happy to
> submit a patch, but I'd first have to get employer approval for it
> (which is not a problem -- it will only take time).
Please!  :)

Or I could send mine; I don't need to do any paperwork. Actually, due to the difference in parameters, I prefer to send mine.

> 
> > If not, why not?
> 
> No real reason other than bureaucracy on my side.
Ok.
Show 5 quoted lines
> 
> > This is something that would clearly be helpful to people solving rebase
> > conflicts in many projects.
> 
> I agree!
:)
> 
> > Have a lovely night!
> 
> Cheers!

Cheers, Alex

-- 
<https://www.alejandro-colomar.es>
Nico WilliamsOct 1, 2026, 21:35 UTC in reply to Nico Williams on lore

Re: git-rebase-walk

On Thu, Oct 01, 2026 at 04:01:01PM -0500, Nico Williams wrote:
>                                       though.. it's fairly obvious
Concisely: repeatedly try to rebase to the new base, then fall back
on bisection to find the upstream commit that causes conflicts.

`bisect-rebase` is kind of a misnomer, because the best-case behavior is O(1), and worst-case is O(N log N) when _every_ upstream commit introduces conflicts, whereas one would expect O(log N). Still, it's a reasonable name given the intent.

Nico
Nico WilliamsOct 1, 2026, 21:01 UTC in reply to Alejandro Colomar on lore

Re: git-rebase-walk

On Thu, Oct 01, 2026 at 10:29:41PM +0200, Alejandro Colomar wrote:
Show 6 quoted lines
> Here's the implementation:
> 
> [...]
> 
> It seems to work fine, and the source file uses 52 lines (including
> blank lines).  The behavior seems intuitive, and not too verbose.
Yes, exactly.
Show 5 quoted lines
> Now, compared to your script, the source length is similar (most of the
> difference is printf calls).  I use more pipes, while you use shell
> features like arrays (I have a very hard time reading shell code that
> does heavy use of shell features).  Other than that, they look
> fundamentally similar (except for the paragraph below).  :)

Indeed. My script minus unnecessary vertical whitespace and printfs is very similar in size.

Show 5 quoted lines
> One thing I'm surprised, though, is that you take two parameters instead
> of just the target branch.  I very much prefer my script in this sense,
> which is like git-rebase(1), which rebases the active branch on top of
> the target commit.  It's up to the caller to make sure that the active
> branch is the right one.

Oh, I know... I... was being paternalistic there. It's completely unnecessary, I agree. I'll remove it.

Show 12 quoted lines
> > > I'll certainly try your script; thanks!
> > > 
> > > Out of curiosity, did you offer this script to git(1)?
> > 
> > No, though I think I've mentioned it here before.  I'd be happy to
> > submit a patch, but I'd first have to get employer approval for it
> > (which is not a problem -- it will only take time).
> 
> Please!  :)
> 
> Or I could send mine; I don't need to do any paperwork.
> Actually, due to the difference in parameters, I prefer to send mine.

You're there already, so go for it. You can credit Vitor Dukhovni and me for this idea (he wrote slow-rebase.sh, and he and I rewrote it together into bisect-rebase.sh when I just didn't have the patience to babysit a slow rebase of my PG work), though.. it's fairly obvious, so much so that there's also the three alternatives mentioned by @pabs3 in a comment on my gist any or all of which you could credit as well, and probably more if you look hard enough:

    https://github.com/CTSRD-CHERI/git-mergify-rebase
    https://github.com/mhagger/git-imerge/
    https://github.com/brooksdavis/mergify/

I agree with you: smaller and simpler is better, which is one reason I prefer bisect-rebase.sh over git-imerge. But I confess I've not looked a those three alternatives in much detail because, frankly, bisect-rebase.sh is so simple and easy to use, and since I [co-]wrote it, I know it well, so for me it's the best choice. Since it seems to be a best choice for someone other than me, it might actually be a good choice for others.

Nico
Simon RichterOct 2, 2026, 02:49 UTC in reply to Alejandro Colomar on lore

Re: git-rebase-walk

Hi,
On 10/1/26 8:58 PM, 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?
I use something similar:
[alias]
         slowrebase = "!bash -c 'for i in $(git rev-list --reverse $(git 
merge-base HEAD @{u})..@{u}); do git rebase $i || break; done'"
         slowrebasemerges = "!bash -c 'for i in $(git rev-list --merges 
--reverse $(git merge-base HEAD @{u})..@{u}); do git rebase $i || break; 
done'"

Alas, this breaks down with merges, and it is slow, so I've been thinking about only listing those revisions that modify the same files as the branch being rebased, and their immediate predecessors -- the latter because the rebase should apply cleanly there.

I wonder if it would make sense to have a rebase-bisect (bisect-rebase?) command that finds the first commit that the branch cannot be cleanly rebased onto, optionally with a test command to see if there are semantic conflicts.

So given
     A --- B --- C --- D --- E --- F (main)
       \
         a --- b --- c (feature)

I'd like to be able to use "git bisect rebase main -x 'make check'" to attempt rebasing onto D first, and continue on to B or E, depending on whether the merge goes cleanly and "make check" succeeds, maybe with an option to try F first if the resolution is trivial.

    Simon
Nico WilliamsOct 2, 2026, 03:19 UTC in reply to Simon Richter on lore

Re: git-rebase-walk

On Fri, Oct 02, 2026 at 11:49:26AM +0900, Simon Richter wrote:
Show 12 quoted lines
> On 10/1/26 8:58 PM, 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?
> 
> I use something similar:
> 
> [alias]
>         slowrebase = "!bash -c 'for i in $(git rev-list --reverse $(git
> merge-base HEAD @{u})..@{u}); do git rebase $i || break; done'"
>         slowrebasemerges = "!bash -c 'for i in $(git rev-list --merges
> --reverse $(git merge-base HEAD @{u})..@{u}); do git rebase $i || break;
> done'"
Nice!
> Alas, this breaks down with merges, and it is slow, so I've been thinking
> [...]

A slow-rebase or bisect-rebase works best when a) you follow a rebase workflow, and b) the upstream has linear history (i.e., they also do a rebase workflow). When the upstream has merges then... improving this experience gets difficult, and the easiest thing to do is to treat the merge as a single [large] commit and not try to bisect-rebase on the merge author's branch side. But if you're looking for a slow-rebase or a bisect-rebase then chances are you're doing (a), and if the upstream doesn't have linear history then you accept the trouble.

> I wonder if it would make sense to have a rebase-bisect (bisect-rebase?)
We had a whole sub-thread on this thread about just that! :)
Show 14 quoted lines
> command that finds the first commit that the branch cannot be cleanly
> rebased onto, optionally with a test command to see if there are semantic
> conflicts.
> 
> So given
> 
>     A --- B --- C --- D --- E --- F (main)
>       \
>         a --- b --- c (feature)
> 
> I'd like to be able to use "git bisect rebase main -x 'make check'" to
> attempt rebasing onto D first, and continue on to B or E, depending on
> whether the merge goes cleanly and "make check" succeeds, maybe with an
> option to try F first if the resolution is trivial.

I linked to my version of this, then Alejandro re-wrote it, on this thread.

I've used mine a few times to rebase across thousands of upstream commits. It works very well, IMO.

Nico
Patrick SteinhardtOct 2, 2026, 06:46 UTC in reply to Alejandro Colomar on lore

Re: git-rebase-walk

On Thu, Oct 01, 2026 at 05:51:58PM +0200, Alejandro Colomar wrote:
Show 52 quoted lines
> Hi Patrick,
> 
> > Date: 2026-10-01 15:22:02+0200
> > From: Patrick Steinhardt <ps@pks.im>
> >
> > Hi,
> > 
> > On Thu, Oct 01, 2026 at 01:58:42PM +0200, Alejandro Colomar wrote:
> > > Hi!
> > > 
> > > 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;
> > > 
> > > The source code is trivial, so I guess I don't need to explain much.
> > > It behaves quite nicely, IME.
> > > 
> > > You may of course want to adapt it a little bit for merging in git(1).
> > > I could help improve it a little bit.
> > 
> > this reminds me a bit of git-imerge [1]. What this tool does is to
> > basically perform a merge between two branches incrementally using a
> > matrix. The tool tries to address exactly your use case, which is to
> > "present the user with one pairwise conflict at a time for resolution".
> 
> Yup, from the description, it seems to do the same thing.  Thanks!
> I've also seen at least one other tool that does the same thing.
> 
> > Maybe that tool is interesting to you.
> 
> Not much, because I prefer a 9-line shell script that's robust as a rock
> vs. a 4k+ LoC python script for the same functionality.  :-)
> 
> > But it's certainly fallen a bit
> > out of date, as it hasn't received any updates for more than 6 years by
> > now. Chances are it stll works alright though.
> 
> My script I use it in shadow-utils and in the Linux man-pages project,
> and is in use today.  I was wondering if there was interest in
> integrating it to git(1). 

I guess the answer is "maybe". The fact that multiple folks have solved similar issues over the course of many years is an indicator that the funcitonality may be more generally useful. But it probably shouldn't be a separate script, so if we wanted to integrate it I'd think the best way forward would be to integrate it into git-rebase(1) directly.

That's of course more involved though, so I understand in case you're not interested in doing that.

> If not, I will likely provide it in the man-pages repository as a help
> tool (which might end up packed by distros as part of manpages-utils).
> Is that okay to you?  (I ask mainly because it's using the git-
> namespace for commands, so you should at lease be aware of it.)

I mean overall this is our primary way of extension, by picking up utilities that have the "git-" prefix. So arguably you don't have to ask us for permission to do that.

Whether it makes sense to distribute such a tool as part of manpages-utils is a different question, and one where I myself am of a split mind. But that feels more like a question for distributors rather than for us in the Git project.

Thanks!
Patrick
Alejandro ColomarOct 2, 2026, 07:19 UTC in reply to Patrick Steinhardt on lore

Re: git-rebase-walk

Hi Patrick,
> Date: 2026-10-02 08:46:36+0200
> From: Patrick Steinhardt <ps@pks.im>
>
[...]
Show 7 quoted lines
> > My script I use it in shadow-utils and in the Linux man-pages project,
> > and is in use today.  I was wondering if there was interest in
> > integrating it to git(1). 
> 
> I guess the answer is "maybe". The fact that multiple folks have solved
> similar issues over the course of many years is an indicator that the
> funcitonality may be more generally useful.
Nice.  :)
> But it probably shouldn't be
> a separate script, so if we wanted to integrate it I'd think the best
> way forward would be to integrate it into git-rebase(1) directly.

For a git-rebase(1) option, I guess it would have to be named something like --first-conflict. --first conflict because it doesn't really rebase on the target commit, but rather on the first commit of that branch which causes conflict.

> That's of course more involved though, so I understand in case you're
> not interested in doing that.

I'd still be interested, but it may take me time, and I'll probably need help.

Show 8 quoted lines
> > If not, I will likely provide it in the man-pages repository as a help
> > tool (which might end up packed by distros as part of manpages-utils).
> > Is that okay to you?  (I ask mainly because it's using the git-
> > namespace for commands, so you should at lease be aware of it.)
> 
> I mean overall this is our primary way of extension, by picking up
> utilities that have the "git-" prefix. So arguably you don't have to ask
> us for permission to do that.

I think I'll do this to provide the command in the meantime as an easy extension, with the goal of deprecating it eventually once it lands in git-rebase(1).

> Whether it makes sense to distribute such a tool as part of
> manpages-utils is a different question, and one where I myself am of a
> split mind. But that feels more like a question for distributors rather
> than for us in the Git project.

We already have other tools that are generally useful, such as grepc(1), which finds C source code with a grep(1)-like interface. It's essentially similar to things like ctags, but it has a traditional command-line interface, and doesn't use any index or cache (yet it's very fast).

So, it wouldn't hurt having this one.

Have a lovely day! Alex

> 
> Thanks!
> 
> Patrick
-- 
<https://www.alejandro-colomar.es>
Nico WilliamsOct 3, 2026, 19:37 UTC in reply to Alejandro Colomar on lore

Re: git-rebase-walk

On Fri, Oct 02, 2026 at 09:19:56AM +0200, Alejandro Colomar wrote:
> For a git-rebase(1) option, I guess it would have to be named something
> like --first-conflict.  --first conflict because it doesn't really
> rebase on the target commit, but rather on the first commit of that
> branch which causes conflict.
I really like this.  Or `git rebase --onto-first-conflict`.
Nico
Phillip WoodOct 4, 2026, 10:03 UTC in reply to Patrick Steinhardt on lore

Re: git-rebase-walk

On 02/10/2026 07:46, Patrick Steinhardt wrote:
Show 11 quoted lines
> On Thu, Oct 01, 2026 at 05:51:58PM +0200, Alejandro Colomar wrote:
>>
>> My script I use it in shadow-utils and in the Linux man-pages project,
>> and is in use today.  I was wondering if there was interest in
>> integrating it to git(1).
> 
> I guess the answer is "maybe". The fact that multiple folks have solved
> similar issues over the course of many years is an indicator that the
> funcitonality may be more generally useful. But it probably shouldn't be
> a separate script, so if we wanted to integrate it I'd think the best
> way forward would be to integrate it into git-rebase(1) directly.

I agree that would be the best way forward. Adding an "--incremental", or "--progressive" option to rebase would be useful I think. For ease of use, I have a strong preference for an implementation where "rebase --continue" handles rebasing onto progressively more recent bases, rather than the multi shot approach where the user has to run "git rebase --incremental" multiple times. Having a multi-shot approach makes it much less clear when we've successfully rebased onto the desired base.

Thanks
Phillip
Show 20 quoted lines
> That's of course more involved though, so I understand in case you're
> not interested in doing that.
> 
>> If not, I will likely provide it in the man-pages repository as a help
>> tool (which might end up packed by distros as part of manpages-utils).
>> Is that okay to you?  (I ask mainly because it's using the git-
>> namespace for commands, so you should at lease be aware of it.)
> 
> I mean overall this is our primary way of extension, by picking up
> utilities that have the "git-" prefix. So arguably you don't have to ask
> us for permission to do that.
> 
> Whether it makes sense to distribute such a tool as part of
> manpages-utils is a different question, and one where I myself am of a
> split mind. But that feels more like a question for distributors rather
> than for us in the Git project.
> 
> Thanks!
> 
> Patrick
Alejandro ColomarOct 5, 2026, 13:28 UTC in reply to Phillip Wood on lore

Re: git-rebase-walk

Hi Phillip,
Show 23 quoted lines
> Date: 2026-10-04 11:03:39+0100
> From: Phillip Wood <phillip.wood123@gmail.com>
>
> On 02/10/2026 07:46, Patrick Steinhardt wrote:
> > On Thu, Oct 01, 2026 at 05:51:58PM +0200, Alejandro Colomar wrote:
> > > 
> > > My script I use it in shadow-utils and in the Linux man-pages project,
> > > and is in use today.  I was wondering if there was interest in
> > > integrating it to git(1).
> > 
> > I guess the answer is "maybe". The fact that multiple folks have solved
> > similar issues over the course of many years is an indicator that the
> > funcitonality may be more generally useful. But it probably shouldn't be
> > a separate script, so if we wanted to integrate it I'd think the best
> > way forward would be to integrate it into git-rebase(1) directly.
> 
> I agree that would be the best way forward. Adding an "--incremental", or
> "--progressive" option to rebase would be useful I think. For ease of use, I
> have a strong preference for an implementation where "rebase --continue"
> handles rebasing onto progressively more recent bases, rather than the multi
> shot approach where the user has to run "git rebase --incremental" multiple
> times. Having a multi-shot approach makes it much less clear when we've
> successfully rebased onto the desired base.

For rebasing a single branch, having --continue do what you suggest wouldn't be too problematic.

However, for when rebasing a tree of branches, I really need a multi-shot operation, since I want to advance branches in a very specific order.

Below is a shell session performing such a rebase, which hopefully shows why I need this to be multi-shot.

On the simpler case of a single branch, I'd still prefer a multi-shot approach where --continue only advances one rebase operation, because at the end of it I want to stop, and check git-range-diff(1) to make sure it all makes sense.

I've indented the output of commands, so that they are easier to distinguish.

	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* G ada8aff4f08a (r/B, B) foo j
		* G d6163efdc2db bar i
		| * G 450f3a7f4f25 (r/HEAD, r/C, C) bar l
		| * G f7309b21ebfa bar k
		|/  
		* G e949e24ba457 (HEAD -> A, r/A) bar h
		*   G 607b450498be bar g
		|\  
		| * G b787bcd373d9 bar e
		* | G c496b325576f baz f
		|/  
		| * G dfd9156d099a (r/main, main) foo d
		| * G 4940c7d739be bar c
		| * G cebc8fde25bb foo b
		|/  
		* G 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git brebase --rebase-merges main
		Rebase: conflict
		Bisecting: 0 revisions left to test after this (roughly 1 step)
		[4940c7d739be44c0ca32c1d610b85fd5650e1528] bar c
		running '.git/bisect-rebase/git-bisect-run-callback'
		Rebase: conflict
		Bisecting: 0 revisions left to test after this (roughly 0 steps)
		[cebc8fde25bbe16c0f5f48e39642b3551f4f56e6] foo b
		running '.git/bisect-rebase/git-bisect-run-callback'
		Rebase: success
		4940c7d739be44c0ca32c1d610b85fd5650e1528 is the first 'bad' commit
		commit 4940c7d739be44c0ca32c1d610b85fd5650e1528
		Author: Alejandro Colomar <alx@kernel.org>
		Date:   2026-10-05 14:42:32 +0200
		    bar c
		 bar | 1 +
		 1 file changed, 1 insertion(+)
		 create mode 100644 bar
		bisect found first 'bad' commit
		Auto-merging bar
		CONFLICT (add/add): Merge conflict in bar
		error: could not apply 899eeb5c4e32... bar e
		hint: Resolve all conflicts manually, mark them as resolved with
		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
		hint: You can instead skip this commit: run "git rebase --skip".
		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
		hint: Disable this message with "git config set advice.mergeConflict false"
		Could not apply 899eeb5c4e32... # bar e
	alx@debian:~/tmp/brebase$ git rebase --abort 
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* 655c38e3cee8 (HEAD -> A) bar h
		*   1ababced193d bar g
		|\  
		| * 899eeb5c4e32 bar e
		* | 761c9dbcfa5b baz f
		|/  
		| * ada8aff4f08a (r/B, B) foo j
		| * d6163efdc2db bar i
		| | * 450f3a7f4f25 (r/HEAD, r/C, C) bar l
		| | * f7309b21ebfa bar k
		| |/  
		| * e949e24ba457 (r/A) bar h
		| *   607b450498be bar g
		| |\  
		| | * b787bcd373d9 bar e
		| * | c496b325576f baz f
		| |/  
		| | * dfd9156d099a (r/main, main) foo d
		| | * 4940c7d739be bar c
		| |/  
		|/|   
		* | cebc8fde25bb foo b
		|/  
		* 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git switch B 
		Switched to branch 'B'
		Your branch is up to date with 'r/B'.
	alx@debian:~/tmp/brebase$ git brebase A
		Rebase: conflict
		Bisecting: 2 revisions left to test after this (roughly 1 step)
		[899eeb5c4e32397f0fe138c5b9f486d4682939cb] bar e
		running '.git/bisect-rebase/git-bisect-run-callback'
		Rebase: conflict
		Bisecting: 0 revisions left to test after this (roughly 0 steps)
		[cebc8fde25bbe16c0f5f48e39642b3551f4f56e6] foo b
		running '.git/bisect-rebase/git-bisect-run-callback'
		Rebase: conflict
		cebc8fde25bbe16c0f5f48e39642b3551f4f56e6 is the first 'bad' commit
		commit cebc8fde25bbe16c0f5f48e39642b3551f4f56e6
		Author: Alejandro Colomar <alx@kernel.org>
		Date:   2026-10-05 14:42:04 +0200
		    foo b
		 foo | 2 +-
		 1 file changed, 1 insertion(+), 1 deletion(-)
		bisect found first 'bad' commit
		Auto-merging foo
		CONFLICT (content): Merge conflict in foo
		error: could not apply ada8aff4f08a... foo j
		hint: Resolve all conflicts manually, mark them as resolved with
		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
		hint: You can instead skip this commit: run "git rebase --skip".
		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
		hint: Disable this message with "git config set advice.mergeConflict false"
		Could not apply ada8aff4f08a... # foo j
	alx@debian:~/tmp/brebase$ echo j >foo
	alx@debian:~/tmp/brebase$ git add foo 
	alx@debian:~/tmp/brebase$ git rebase --continue 
		[detached HEAD 2e0b72e7440a] foo j
		 1 file changed, 1 insertion(+), 1 deletion(-)
		Successfully rebased and updated refs/heads/B.
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* 2e0b72e7440a (HEAD -> B) foo j
		* a1c6c1fb7ca2 bar i
		* d8fa6c4da463 bar h
		* bef9f1c4da4d bar e
		* 0bac26895b94 baz f
		| * 655c38e3cee8 (A) bar h
		| *   1ababced193d bar g
		| |\  
		| | * 899eeb5c4e32 bar e
		| |/  
		|/|   
		| * 761c9dbcfa5b baz f
		|/  
		| * ada8aff4f08a (r/B) foo j
		| * d6163efdc2db bar i
		| | * 450f3a7f4f25 (r/HEAD, r/C, C) bar l
		| | * f7309b21ebfa bar k
		| |/  
		| * e949e24ba457 (r/A) bar h
		| *   607b450498be bar g
		| |\  
		| | * b787bcd373d9 bar e
		| * | c496b325576f baz f
		| |/  
		| | * dfd9156d099a (r/main, main) foo d
		| | * 4940c7d739be bar c
		| |/  
		|/|   
		* | cebc8fde25bb foo b
		|/  
		* 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git brebase A
		Rebase: success
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* 5ff93a00f9f2 (HEAD -> B) foo j
		* 01522206a7bc bar i
		* 655c38e3cee8 (A) bar h
		*   1ababced193d bar g
		|\  
		| * 899eeb5c4e32 bar e
		* | 761c9dbcfa5b baz f
		|/  
		| * ada8aff4f08a (r/B) foo j
		| * d6163efdc2db bar i
		| | * 450f3a7f4f25 (r/HEAD, r/C, C) bar l
		| | * f7309b21ebfa bar k
		| |/  
		| * e949e24ba457 (r/A) bar h
		| *   607b450498be bar g
		| |\  
		| | * b787bcd373d9 bar e
		| * | c496b325576f baz f
		| |/  
		| | * dfd9156d099a (r/main, main) foo d
		| | * 4940c7d739be bar c
		| |/  
		|/|   
		* | cebc8fde25bb foo b
		|/  
		* 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git switch C
		Switched to branch 'C'
	alx@debian:~/tmp/brebase$ git brebase A
		Rebase: success
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* 06d462903420 (HEAD -> C) bar l
		* 20f0a887b83b bar k
		| * 5ff93a00f9f2 (B) foo j
		| * 01522206a7bc bar i
		|/  
		* 655c38e3cee8 (A) bar h
		*   1ababced193d bar g
		|\  
		| * 899eeb5c4e32 bar e
		* | 761c9dbcfa5b baz f
		|/  
		| * ada8aff4f08a (r/B) foo j
		| * d6163efdc2db bar i
		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
		| | * f7309b21ebfa bar k
		| |/  
		| * e949e24ba457 (r/A) bar h
		| *   607b450498be bar g
		| |\  
		| | * b787bcd373d9 bar e
		| * | c496b325576f baz f
		| |/  
		| | * dfd9156d099a (r/main, main) foo d
		| | * 4940c7d739be bar c
		| |/  
		|/|   
		* | cebc8fde25bb foo b
		|/  
		* 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git switch A
		Switched to branch 'A'
	alx@debian:~/tmp/brebase$ git brebase --rebase-merges main
		Rebase: conflict
		Bisecting: 0 revisions left to test after this (roughly 0 steps)
		[4940c7d739be44c0ca32c1d610b85fd5650e1528] bar c
		running '.git/bisect-rebase/git-bisect-run-callback'
		Rebase: conflict
		4940c7d739be44c0ca32c1d610b85fd5650e1528 is the first 'bad' commit
		commit 4940c7d739be44c0ca32c1d610b85fd5650e1528
		Author: Alejandro Colomar <alx@kernel.org>
		Date:   2026-10-05 14:42:32 +0200
		    bar c
		 bar | 1 +
		 1 file changed, 1 insertion(+)
		 create mode 100644 bar
		bisect found first 'bad' commit
		Auto-merging bar
		CONFLICT (add/add): Merge conflict in bar
		error: could not apply 899eeb5c4e32... bar e
		hint: Resolve all conflicts manually, mark them as resolved with
		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
		hint: You can instead skip this commit: run "git rebase --skip".
		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
		hint: Disable this message with "git config set advice.mergeConflict false"
		Could not apply 899eeb5c4e32... # bar e
	alx@debian:~/tmp/brebase$ echo e >bar
	alx@debian:~/tmp/brebase$ git add bar 
	alx@debian:~/tmp/brebase$ git rebase --continue 
		[detached HEAD 2a4fa7fe2f44] bar e
		 1 file changed, 1 insertion(+), 1 deletion(-)
		Successfully rebased and updated refs/heads/A.
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* 0954f3d9b9e1 (HEAD -> A) bar h
		*   4f09c21bf2ca bar g
		|\  
		| * 2a4fa7fe2f44 bar e
		* | e42246e75159 baz f
		|/  
		| * 06d462903420 (C) bar l
		| * 20f0a887b83b bar k
		| | * 5ff93a00f9f2 (B) foo j
		| | * 01522206a7bc bar i
		| |/  
		| * 655c38e3cee8 bar h
		| *   1ababced193d bar g
		| |\  
		| | * 899eeb5c4e32 bar e
		| * | 761c9dbcfa5b baz f
		| |/  
		| | * ada8aff4f08a (r/B) foo j
		| | * d6163efdc2db bar i
		| | | * 450f3a7f4f25 (r/HEAD, r/C) bar l
		| | | * f7309b21ebfa bar k
		| | |/  
		| | * e949e24ba457 (r/A) bar h
		| | *   607b450498be bar g
		| | |\  
		| | | * b787bcd373d9 bar e
		| | * | c496b325576f baz f
		| | |/  
		| | | * dfd9156d099a (r/main, main) foo d
		| |_|/  
		|/| |   
		* | | 4940c7d739be bar c
		|/ /  
		* / cebc8fde25bb foo b
		|/  
		* 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git rebase --onto A 655c38e3cee8 B
		Successfully rebased and updated refs/heads/B.
	alx@debian:~/tmp/brebase$ git rebase --onto A 655c38e3cee8 C
		Successfully rebased and updated refs/heads/C.
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* 4a4ba76f55a4 (HEAD -> C) bar l
		* 86350e1490f3 bar k
		| * 4b6b40b14255 (B) foo j
		| * ba5a233ee4bc bar i
		|/  
		* 0954f3d9b9e1 (A) bar h
		*   4f09c21bf2ca bar g
		|\  
		| * 2a4fa7fe2f44 bar e
		* | e42246e75159 baz f
		|/  
		| * ada8aff4f08a (r/B) foo j
		| * d6163efdc2db bar i
		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
		| | * f7309b21ebfa bar k
		| |/  
		| * e949e24ba457 (r/A) bar h
		| *   607b450498be bar g
		| |\  
		| | * b787bcd373d9 bar e
		| * | c496b325576f baz f
		| |/  
		| | * dfd9156d099a (r/main, main) foo d
		| |/  
		|/|   
		* | 4940c7d739be bar c
		* | cebc8fde25bb foo b
		|/  
		* 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git switch A
		Switched to branch 'A'
	alx@debian:~/tmp/brebase$ git brebase --rebase-merges main
		Rebase: success
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* 30e2d96b3da5 (HEAD -> A) bar h
		*   01702a5b5d6b bar g
		|\  
		| * c961883d543a bar e
		* | e17aadb725c4 baz f
		|/  
		* dfd9156d099a (r/main, main) foo d
		| * 4a4ba76f55a4 (C) bar l
		| * 86350e1490f3 bar k
		| | * 4b6b40b14255 (B) foo j
		| | * ba5a233ee4bc bar i
		| |/  
		| * 0954f3d9b9e1 bar h
		| *   4f09c21bf2ca bar g
		| |\  
		| | * 2a4fa7fe2f44 bar e
		| |/  
		|/|   
		| * e42246e75159 baz f
		|/  
		* 4940c7d739be bar c
		* cebc8fde25bb foo b
		| * ada8aff4f08a (r/B) foo j
		| * d6163efdc2db bar i
		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
		| | * f7309b21ebfa bar k
		| |/  
		| * e949e24ba457 (r/A) bar h
		| *   607b450498be bar g
		| |\  
		| | * b787bcd373d9 bar e
		| |/  
		|/|   
		| * c496b325576f baz f
		|/  
		* 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git rebase --onto A 0954f3d9b9e1 C
		Successfully rebased and updated refs/heads/C.
	alx@debian:~/tmp/brebase$ git rebase --onto A 0954f3d9b9e1 B
		Auto-merging foo
		CONFLICT (content): Merge conflict in foo
		error: could not apply 4b6b40b14255... foo j
		hint: Resolve all conflicts manually, mark them as resolved with
		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
		hint: You can instead skip this commit: run "git rebase --skip".
		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
		hint: Disable this message with "git config set advice.mergeConflict false"
		Could not apply 4b6b40b14255... # foo j
	alx@debian:~/tmp/brebase$ git rebase --abort 
	alx@debian:~/tmp/brebase$ git switch B
		Already on 'B'
		Your branch and 'r/B' have diverged,
		and have 8 and 6 different commits each, respectively.
		  (use "git pull" if you want to integrate the remote branch with yours)
	alx@debian:~/tmp/brebase$ git brebase A
		Rebase: conflict
		Bisecting: 2 revisions left to test after this (roughly 1 step)
		[c961883d543a2393aacfd6a8345e1d29e6857f7f] bar e
		running '.git/bisect-rebase/git-bisect-run-callback'
		Rebase: conflict
		Bisecting: 0 revisions left to test after this (roughly 0 steps)
		[dfd9156d099ad3507a2850294c7a584b80712f04] foo d
		running '.git/bisect-rebase/git-bisect-run-callback'
		Rebase: conflict
		dfd9156d099ad3507a2850294c7a584b80712f04 is the first 'bad' commit
		commit dfd9156d099ad3507a2850294c7a584b80712f04
		Author: Alejandro Colomar <alx@kernel.org>
		Date:   2026-10-05 14:42:50 +0200
		    foo d
		 foo | 2 +-
		 1 file changed, 1 insertion(+), 1 deletion(-)
		bisect found first 'bad' commit
		Auto-merging foo
		CONFLICT (content): Merge conflict in foo
		error: could not apply 4b6b40b14255... foo j
		hint: Resolve all conflicts manually, mark them as resolved with
		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
		hint: You can instead skip this commit: run "git rebase --skip".
		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
		hint: Disable this message with "git config set advice.mergeConflict false"
		Could not apply 4b6b40b14255... # foo j
	alx@debian:~/tmp/brebase$ echo j >foo
	alx@debian:~/tmp/brebase$ git add foo 
	alx@debian:~/tmp/brebase$ git rebase --continue 
		[detached HEAD e7fdf07fd077] foo j
		 1 file changed, 1 insertion(+), 1 deletion(-)
		Successfully rebased and updated refs/heads/B.
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* e7fdf07fd077 (HEAD -> B) foo j
		* dddf632a735f bar i
		* 7ac284de12ba bar h
		* e4541508ab3e bar e
		* cefec5878c67 baz f
		| * 6c7952d6fec5 (C) bar l
		| * bd43684f73c8 bar k
		| * 30e2d96b3da5 (A) bar h
		| *   01702a5b5d6b bar g
		| |\  
		| | * c961883d543a bar e
		| |/  
		|/|   
		| * e17aadb725c4 baz f
		|/  
		* dfd9156d099a (r/main, main) foo d
		* 4940c7d739be bar c
		* cebc8fde25bb foo b
		| * ada8aff4f08a (r/B) foo j
		| * d6163efdc2db bar i
		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
		| | * f7309b21ebfa bar k
		| |/  
		| * e949e24ba457 (r/A) bar h
		| *   607b450498be bar g
		| |\  
		| | * b787bcd373d9 bar e
		| |/  
		|/|   
		| * c496b325576f baz f
		|/  
		* 1dcb901ebf60 foo a
	alx@debian:~/tmp/brebase$ git brebase A
		Rebase: success
	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
		* 1201c4f20b19 (HEAD -> B) foo j
		* 44103f51a783 bar i
		| * 6c7952d6fec5 (C) bar l
		| * bd43684f73c8 bar k
		|/  
		* 30e2d96b3da5 (A) bar h
		*   01702a5b5d6b bar g
		|\  
		| * c961883d543a bar e
		* | e17aadb725c4 baz f
		|/  
		* dfd9156d099a (r/main, main) foo d
		* 4940c7d739be bar c
		* cebc8fde25bb foo b
		| * ada8aff4f08a (r/B) foo j
		| * d6163efdc2db bar i
		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
		| | * f7309b21ebfa bar k
		| |/  
		| * e949e24ba457 (r/A) bar h
		| *   607b450498be bar g
		| |\  
		| | * b787bcd373d9 bar e
		| |/  
		|/|   
		| * c496b325576f baz f
		|/  
		* 1dcb901ebf60 foo a

This would be impossible with an approach that handles all the way until the end. I need to be able to stop a bisect-rebase operation on one branch in the middle, then do a bisect-rebase on its descendants, then come back to bisect-rebase the parent branch. Does this make sense?

Have a lovely day! Alex

Show 27 quoted lines
> 
> Thanks
> 
> Phillip
> 
> 
> > That's of course more involved though, so I understand in case you're
> > not interested in doing that.
> > 
> > > If not, I will likely provide it in the man-pages repository as a help
> > > tool (which might end up packed by distros as part of manpages-utils).
> > > Is that okay to you?  (I ask mainly because it's using the git-
> > > namespace for commands, so you should at lease be aware of it.)
> > 
> > I mean overall this is our primary way of extension, by picking up
> > utilities that have the "git-" prefix. So arguably you don't have to ask
> > us for permission to do that.
> > 
> > Whether it makes sense to distribute such a tool as part of
> > manpages-utils is a different question, and one where I myself am of a
> > split mind. But that feels more like a question for distributors rather
> > than for us in the Git project.
> > 
> > Thanks!
> > 
> > Patrick
> 
-- 
<https://www.alejandro-colomar.es>
Alejandro ColomarOct 5, 2026, 13:37 UTC in reply to Alejandro Colomar on lore

Re: git-rebase-walk

Show 412 quoted lines
> Date: 2026-10-05 15:28:28+0200
> From: Alejandro Colomar <alx@kernel.org>
>
> Hi Phillip,
> 
> > Date: 2026-10-04 11:03:39+0100
> > From: Phillip Wood <phillip.wood123@gmail.com>
> >
> > On 02/10/2026 07:46, Patrick Steinhardt wrote:
> > > On Thu, Oct 01, 2026 at 05:51:58PM +0200, Alejandro Colomar wrote:
> > > > 
> > > > My script I use it in shadow-utils and in the Linux man-pages project,
> > > > and is in use today.  I was wondering if there was interest in
> > > > integrating it to git(1).
> > > 
> > > I guess the answer is "maybe". The fact that multiple folks have solved
> > > similar issues over the course of many years is an indicator that the
> > > funcitonality may be more generally useful. But it probably shouldn't be
> > > a separate script, so if we wanted to integrate it I'd think the best
> > > way forward would be to integrate it into git-rebase(1) directly.
> > 
> > I agree that would be the best way forward. Adding an "--incremental", or
> > "--progressive" option to rebase would be useful I think. For ease of use, I
> > have a strong preference for an implementation where "rebase --continue"
> > handles rebasing onto progressively more recent bases, rather than the multi
> > shot approach where the user has to run "git rebase --incremental" multiple
> > times. Having a multi-shot approach makes it much less clear when we've
> > successfully rebased onto the desired base.
> 
> For rebasing a single branch, having --continue do what you suggest
> wouldn't be too problematic.
> 
> However, for when rebasing a tree of branches, I really need a
> multi-shot operation, since I want to advance branches in a very
> specific order.
> 
> Below is a shell session performing such a rebase, which hopefully shows
> why I need this to be multi-shot.
> 
> On the simpler case of a single branch, I'd still prefer a multi-shot
> approach where --continue only advances one rebase operation, because at
> the end of it I want to stop, and check git-range-diff(1) to make sure
> it all makes sense.
> 
> I've indented the output of commands, so that they are easier to
> distinguish.
> 
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* G ada8aff4f08a (r/B, B) foo j
> 		* G d6163efdc2db bar i
> 		| * G 450f3a7f4f25 (r/HEAD, r/C, C) bar l
> 		| * G f7309b21ebfa bar k
> 		|/  
> 		* G e949e24ba457 (HEAD -> A, r/A) bar h
> 		*   G 607b450498be bar g
> 		|\  
> 		| * G b787bcd373d9 bar e
> 		* | G c496b325576f baz f
> 		|/  
> 		| * G dfd9156d099a (r/main, main) foo d
> 		| * G 4940c7d739be bar c
> 		| * G cebc8fde25bb foo b
> 		|/  
> 		* G 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git brebase --rebase-merges main
> 		Rebase: conflict
> 		Bisecting: 0 revisions left to test after this (roughly 1 step)
> 		[4940c7d739be44c0ca32c1d610b85fd5650e1528] bar c
> 		running '.git/bisect-rebase/git-bisect-run-callback'
> 		Rebase: conflict
> 		Bisecting: 0 revisions left to test after this (roughly 0 steps)
> 		[cebc8fde25bbe16c0f5f48e39642b3551f4f56e6] foo b
> 		running '.git/bisect-rebase/git-bisect-run-callback'
> 		Rebase: success
> 		4940c7d739be44c0ca32c1d610b85fd5650e1528 is the first 'bad' commit
> 		commit 4940c7d739be44c0ca32c1d610b85fd5650e1528
> 		Author: Alejandro Colomar <alx@kernel.org>
> 		Date:   2026-10-05 14:42:32 +0200
> 
> 		    bar c
> 
> 		 bar | 1 +
> 		 1 file changed, 1 insertion(+)
> 		 create mode 100644 bar
> 		bisect found first 'bad' commit
> 		Auto-merging bar
> 		CONFLICT (add/add): Merge conflict in bar
> 		error: could not apply 899eeb5c4e32... bar e
> 		hint: Resolve all conflicts manually, mark them as resolved with
> 		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
> 		hint: You can instead skip this commit: run "git rebase --skip".
> 		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
> 		hint: Disable this message with "git config set advice.mergeConflict false"
> 		Could not apply 899eeb5c4e32... # bar e
> 	alx@debian:~/tmp/brebase$ git rebase --abort 
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* 655c38e3cee8 (HEAD -> A) bar h
> 		*   1ababced193d bar g
> 		|\  
> 		| * 899eeb5c4e32 bar e
> 		* | 761c9dbcfa5b baz f
> 		|/  
> 		| * ada8aff4f08a (r/B, B) foo j
> 		| * d6163efdc2db bar i
> 		| | * 450f3a7f4f25 (r/HEAD, r/C, C) bar l
> 		| | * f7309b21ebfa bar k
> 		| |/  
> 		| * e949e24ba457 (r/A) bar h
> 		| *   607b450498be bar g
> 		| |\  
> 		| | * b787bcd373d9 bar e
> 		| * | c496b325576f baz f
> 		| |/  
> 		| | * dfd9156d099a (r/main, main) foo d
> 		| | * 4940c7d739be bar c
> 		| |/  
> 		|/|   
> 		* | cebc8fde25bb foo b
> 		|/  
> 		* 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git switch B 
> 		Switched to branch 'B'
> 		Your branch is up to date with 'r/B'.
> 	alx@debian:~/tmp/brebase$ git brebase A
> 		Rebase: conflict
> 		Bisecting: 2 revisions left to test after this (roughly 1 step)
> 		[899eeb5c4e32397f0fe138c5b9f486d4682939cb] bar e
> 		running '.git/bisect-rebase/git-bisect-run-callback'
> 		Rebase: conflict
> 		Bisecting: 0 revisions left to test after this (roughly 0 steps)
> 		[cebc8fde25bbe16c0f5f48e39642b3551f4f56e6] foo b
> 		running '.git/bisect-rebase/git-bisect-run-callback'
> 		Rebase: conflict
> 		cebc8fde25bbe16c0f5f48e39642b3551f4f56e6 is the first 'bad' commit
> 		commit cebc8fde25bbe16c0f5f48e39642b3551f4f56e6
> 		Author: Alejandro Colomar <alx@kernel.org>
> 		Date:   2026-10-05 14:42:04 +0200
> 
> 		    foo b
> 
> 		 foo | 2 +-
> 		 1 file changed, 1 insertion(+), 1 deletion(-)
> 		bisect found first 'bad' commit
> 		Auto-merging foo
> 		CONFLICT (content): Merge conflict in foo
> 		error: could not apply ada8aff4f08a... foo j
> 		hint: Resolve all conflicts manually, mark them as resolved with
> 		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
> 		hint: You can instead skip this commit: run "git rebase --skip".
> 		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
> 		hint: Disable this message with "git config set advice.mergeConflict false"
> 		Could not apply ada8aff4f08a... # foo j
> 	alx@debian:~/tmp/brebase$ echo j >foo
> 	alx@debian:~/tmp/brebase$ git add foo 
> 	alx@debian:~/tmp/brebase$ git rebase --continue 
> 		[detached HEAD 2e0b72e7440a] foo j
> 		 1 file changed, 1 insertion(+), 1 deletion(-)
> 		Successfully rebased and updated refs/heads/B.
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* 2e0b72e7440a (HEAD -> B) foo j
> 		* a1c6c1fb7ca2 bar i
> 		* d8fa6c4da463 bar h
> 		* bef9f1c4da4d bar e
> 		* 0bac26895b94 baz f
> 		| * 655c38e3cee8 (A) bar h
> 		| *   1ababced193d bar g
> 		| |\  
> 		| | * 899eeb5c4e32 bar e
> 		| |/  
> 		|/|   
> 		| * 761c9dbcfa5b baz f
> 		|/  
> 		| * ada8aff4f08a (r/B) foo j
> 		| * d6163efdc2db bar i
> 		| | * 450f3a7f4f25 (r/HEAD, r/C, C) bar l
> 		| | * f7309b21ebfa bar k
> 		| |/  
> 		| * e949e24ba457 (r/A) bar h
> 		| *   607b450498be bar g
> 		| |\  
> 		| | * b787bcd373d9 bar e
> 		| * | c496b325576f baz f
> 		| |/  
> 		| | * dfd9156d099a (r/main, main) foo d
> 		| | * 4940c7d739be bar c
> 		| |/  
> 		|/|   
> 		* | cebc8fde25bb foo b
> 		|/  
> 		* 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git brebase A
> 		Rebase: success
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* 5ff93a00f9f2 (HEAD -> B) foo j
> 		* 01522206a7bc bar i
> 		* 655c38e3cee8 (A) bar h
> 		*   1ababced193d bar g
> 		|\  
> 		| * 899eeb5c4e32 bar e
> 		* | 761c9dbcfa5b baz f
> 		|/  
> 		| * ada8aff4f08a (r/B) foo j
> 		| * d6163efdc2db bar i
> 		| | * 450f3a7f4f25 (r/HEAD, r/C, C) bar l
> 		| | * f7309b21ebfa bar k
> 		| |/  
> 		| * e949e24ba457 (r/A) bar h
> 		| *   607b450498be bar g
> 		| |\  
> 		| | * b787bcd373d9 bar e
> 		| * | c496b325576f baz f
> 		| |/  
> 		| | * dfd9156d099a (r/main, main) foo d
> 		| | * 4940c7d739be bar c
> 		| |/  
> 		|/|   
> 		* | cebc8fde25bb foo b
> 		|/  
> 		* 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git switch C
> 		Switched to branch 'C'
> 	alx@debian:~/tmp/brebase$ git brebase A
> 		Rebase: success
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* 06d462903420 (HEAD -> C) bar l
> 		* 20f0a887b83b bar k
> 		| * 5ff93a00f9f2 (B) foo j
> 		| * 01522206a7bc bar i
> 		|/  
> 		* 655c38e3cee8 (A) bar h
> 		*   1ababced193d bar g
> 		|\  
> 		| * 899eeb5c4e32 bar e
> 		* | 761c9dbcfa5b baz f
> 		|/  
> 		| * ada8aff4f08a (r/B) foo j
> 		| * d6163efdc2db bar i
> 		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
> 		| | * f7309b21ebfa bar k
> 		| |/  
> 		| * e949e24ba457 (r/A) bar h
> 		| *   607b450498be bar g
> 		| |\  
> 		| | * b787bcd373d9 bar e
> 		| * | c496b325576f baz f
> 		| |/  
> 		| | * dfd9156d099a (r/main, main) foo d
> 		| | * 4940c7d739be bar c
> 		| |/  
> 		|/|   
> 		* | cebc8fde25bb foo b
> 		|/  
> 		* 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git switch A
> 		Switched to branch 'A'
> 	alx@debian:~/tmp/brebase$ git brebase --rebase-merges main
> 		Rebase: conflict
> 		Bisecting: 0 revisions left to test after this (roughly 0 steps)
> 		[4940c7d739be44c0ca32c1d610b85fd5650e1528] bar c
> 		running '.git/bisect-rebase/git-bisect-run-callback'
> 		Rebase: conflict
> 		4940c7d739be44c0ca32c1d610b85fd5650e1528 is the first 'bad' commit
> 		commit 4940c7d739be44c0ca32c1d610b85fd5650e1528
> 		Author: Alejandro Colomar <alx@kernel.org>
> 		Date:   2026-10-05 14:42:32 +0200
> 
> 		    bar c
> 
> 		 bar | 1 +
> 		 1 file changed, 1 insertion(+)
> 		 create mode 100644 bar
> 		bisect found first 'bad' commit
> 		Auto-merging bar
> 		CONFLICT (add/add): Merge conflict in bar
> 		error: could not apply 899eeb5c4e32... bar e
> 		hint: Resolve all conflicts manually, mark them as resolved with
> 		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
> 		hint: You can instead skip this commit: run "git rebase --skip".
> 		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
> 		hint: Disable this message with "git config set advice.mergeConflict false"
> 		Could not apply 899eeb5c4e32... # bar e
> 	alx@debian:~/tmp/brebase$ echo e >bar
> 	alx@debian:~/tmp/brebase$ git add bar 
> 	alx@debian:~/tmp/brebase$ git rebase --continue 
> 		[detached HEAD 2a4fa7fe2f44] bar e
> 		 1 file changed, 1 insertion(+), 1 deletion(-)
> 		Successfully rebased and updated refs/heads/A.
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* 0954f3d9b9e1 (HEAD -> A) bar h
> 		*   4f09c21bf2ca bar g
> 		|\  
> 		| * 2a4fa7fe2f44 bar e
> 		* | e42246e75159 baz f
> 		|/  
> 		| * 06d462903420 (C) bar l
> 		| * 20f0a887b83b bar k
> 		| | * 5ff93a00f9f2 (B) foo j
> 		| | * 01522206a7bc bar i
> 		| |/  
> 		| * 655c38e3cee8 bar h
> 		| *   1ababced193d bar g
> 		| |\  
> 		| | * 899eeb5c4e32 bar e
> 		| * | 761c9dbcfa5b baz f
> 		| |/  
> 		| | * ada8aff4f08a (r/B) foo j
> 		| | * d6163efdc2db bar i
> 		| | | * 450f3a7f4f25 (r/HEAD, r/C) bar l
> 		| | | * f7309b21ebfa bar k
> 		| | |/  
> 		| | * e949e24ba457 (r/A) bar h
> 		| | *   607b450498be bar g
> 		| | |\  
> 		| | | * b787bcd373d9 bar e
> 		| | * | c496b325576f baz f
> 		| | |/  
> 		| | | * dfd9156d099a (r/main, main) foo d
> 		| |_|/  
> 		|/| |   
> 		* | | 4940c7d739be bar c
> 		|/ /  
> 		* / cebc8fde25bb foo b
> 		|/  
> 		* 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git rebase --onto A 655c38e3cee8 B
> 		Successfully rebased and updated refs/heads/B.
> 	alx@debian:~/tmp/brebase$ git rebase --onto A 655c38e3cee8 C
> 		Successfully rebased and updated refs/heads/C.
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* 4a4ba76f55a4 (HEAD -> C) bar l
> 		* 86350e1490f3 bar k
> 		| * 4b6b40b14255 (B) foo j
> 		| * ba5a233ee4bc bar i
> 		|/  
> 		* 0954f3d9b9e1 (A) bar h
> 		*   4f09c21bf2ca bar g
> 		|\  
> 		| * 2a4fa7fe2f44 bar e
> 		* | e42246e75159 baz f
> 		|/  
> 		| * ada8aff4f08a (r/B) foo j
> 		| * d6163efdc2db bar i
> 		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
> 		| | * f7309b21ebfa bar k
> 		| |/  
> 		| * e949e24ba457 (r/A) bar h
> 		| *   607b450498be bar g
> 		| |\  
> 		| | * b787bcd373d9 bar e
> 		| * | c496b325576f baz f
> 		| |/  
> 		| | * dfd9156d099a (r/main, main) foo d
> 		| |/  
> 		|/|   
> 		* | 4940c7d739be bar c
> 		* | cebc8fde25bb foo b
> 		|/  
> 		* 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git switch A
> 		Switched to branch 'A'
> 	alx@debian:~/tmp/brebase$ git brebase --rebase-merges main
> 		Rebase: success
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* 30e2d96b3da5 (HEAD -> A) bar h
> 		*   01702a5b5d6b bar g
> 		|\  
> 		| * c961883d543a bar e
> 		* | e17aadb725c4 baz f
> 		|/  
> 		* dfd9156d099a (r/main, main) foo d
> 		| * 4a4ba76f55a4 (C) bar l
> 		| * 86350e1490f3 bar k
> 		| | * 4b6b40b14255 (B) foo j
> 		| | * ba5a233ee4bc bar i
> 		| |/  
> 		| * 0954f3d9b9e1 bar h
> 		| *   4f09c21bf2ca bar g
> 		| |\  
> 		| | * 2a4fa7fe2f44 bar e
> 		| |/  
> 		|/|   
> 		| * e42246e75159 baz f
> 		|/  
> 		* 4940c7d739be bar c
> 		* cebc8fde25bb foo b
> 		| * ada8aff4f08a (r/B) foo j
> 		| * d6163efdc2db bar i
> 		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
> 		| | * f7309b21ebfa bar k
> 		| |/  
> 		| * e949e24ba457 (r/A) bar h
> 		| *   607b450498be bar g
> 		| |\  
> 		| | * b787bcd373d9 bar e
> 		| |/  
> 		|/|   
> 		| * c496b325576f baz f
> 		|/  
> 		* 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git rebase --onto A 0954f3d9b9e1 C
> 		Successfully rebased and updated refs/heads/C.
> 	alx@debian:~/tmp/brebase$ git rebase --onto A 0954f3d9b9e1 B
> 		Auto-merging foo
> 		CONFLICT (content): Merge conflict in foo
> 		error: could not apply 4b6b40b14255... foo j
> 		hint: Resolve all conflicts manually, mark them as resolved with
> 		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
> 		hint: You can instead skip this commit: run "git rebase --skip".
> 		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
> 		hint: Disable this message with "git config set advice.mergeConflict false"
> 		Could not apply 4b6b40b14255... # foo j
> 	alx@debian:~/tmp/brebase$ git rebase --abort 

Oh, this was a mistake; I should have resolved the conflict here instead of using brebase below. (brebase produced the same exact conflict). :)

Cheers, Alex

Show 145 quoted lines
> 	alx@debian:~/tmp/brebase$ git switch B
> 		Already on 'B'
> 		Your branch and 'r/B' have diverged,
> 		and have 8 and 6 different commits each, respectively.
> 		  (use "git pull" if you want to integrate the remote branch with yours)
> 	alx@debian:~/tmp/brebase$ git brebase A
> 		Rebase: conflict
> 		Bisecting: 2 revisions left to test after this (roughly 1 step)
> 		[c961883d543a2393aacfd6a8345e1d29e6857f7f] bar e
> 		running '.git/bisect-rebase/git-bisect-run-callback'
> 		Rebase: conflict
> 		Bisecting: 0 revisions left to test after this (roughly 0 steps)
> 		[dfd9156d099ad3507a2850294c7a584b80712f04] foo d
> 		running '.git/bisect-rebase/git-bisect-run-callback'
> 		Rebase: conflict
> 		dfd9156d099ad3507a2850294c7a584b80712f04 is the first 'bad' commit
> 		commit dfd9156d099ad3507a2850294c7a584b80712f04
> 		Author: Alejandro Colomar <alx@kernel.org>
> 		Date:   2026-10-05 14:42:50 +0200
> 
> 		    foo d
> 
> 		 foo | 2 +-
> 		 1 file changed, 1 insertion(+), 1 deletion(-)
> 		bisect found first 'bad' commit
> 		Auto-merging foo
> 		CONFLICT (content): Merge conflict in foo
> 		error: could not apply 4b6b40b14255... foo j
> 		hint: Resolve all conflicts manually, mark them as resolved with
> 		hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
> 		hint: You can instead skip this commit: run "git rebase --skip".
> 		hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
> 		hint: Disable this message with "git config set advice.mergeConflict false"
> 		Could not apply 4b6b40b14255... # foo j
> 	alx@debian:~/tmp/brebase$ echo j >foo
> 	alx@debian:~/tmp/brebase$ git add foo 
> 	alx@debian:~/tmp/brebase$ git rebase --continue 
> 		[detached HEAD e7fdf07fd077] foo j
> 		 1 file changed, 1 insertion(+), 1 deletion(-)
> 		Successfully rebased and updated refs/heads/B.
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* e7fdf07fd077 (HEAD -> B) foo j
> 		* dddf632a735f bar i
> 		* 7ac284de12ba bar h
> 		* e4541508ab3e bar e
> 		* cefec5878c67 baz f
> 		| * 6c7952d6fec5 (C) bar l
> 		| * bd43684f73c8 bar k
> 		| * 30e2d96b3da5 (A) bar h
> 		| *   01702a5b5d6b bar g
> 		| |\  
> 		| | * c961883d543a bar e
> 		| |/  
> 		|/|   
> 		| * e17aadb725c4 baz f
> 		|/  
> 		* dfd9156d099a (r/main, main) foo d
> 		* 4940c7d739be bar c
> 		* cebc8fde25bb foo b
> 		| * ada8aff4f08a (r/B) foo j
> 		| * d6163efdc2db bar i
> 		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
> 		| | * f7309b21ebfa bar k
> 		| |/  
> 		| * e949e24ba457 (r/A) bar h
> 		| *   607b450498be bar g
> 		| |\  
> 		| | * b787bcd373d9 bar e
> 		| |/  
> 		|/|   
> 		| * c496b325576f baz f
> 		|/  
> 		* 1dcb901ebf60 foo a
> 	alx@debian:~/tmp/brebase$ git brebase A
> 		Rebase: success
> 	alx@debian:~/tmp/brebase$ git log --all --graph --oneline
> 		* 1201c4f20b19 (HEAD -> B) foo j
> 		* 44103f51a783 bar i
> 		| * 6c7952d6fec5 (C) bar l
> 		| * bd43684f73c8 bar k
> 		|/  
> 		* 30e2d96b3da5 (A) bar h
> 		*   01702a5b5d6b bar g
> 		|\  
> 		| * c961883d543a bar e
> 		* | e17aadb725c4 baz f
> 		|/  
> 		* dfd9156d099a (r/main, main) foo d
> 		* 4940c7d739be bar c
> 		* cebc8fde25bb foo b
> 		| * ada8aff4f08a (r/B) foo j
> 		| * d6163efdc2db bar i
> 		| | * 450f3a7f4f25 (r/HEAD, r/C) bar l
> 		| | * f7309b21ebfa bar k
> 		| |/  
> 		| * e949e24ba457 (r/A) bar h
> 		| *   607b450498be bar g
> 		| |\  
> 		| | * b787bcd373d9 bar e
> 		| |/  
> 		|/|   
> 		| * c496b325576f baz f
> 		|/  
> 		* 1dcb901ebf60 foo a
> 
> This would be impossible with an approach that handles all the way until
> the end.  I need to be able to stop a bisect-rebase operation on one
> branch in the middle, then do a bisect-rebase on its descendants, then
> come back to bisect-rebase the parent branch.  Does this make sense?
> 
> 
> Have a lovely day!
> Alex
> 
> 
> > 
> > Thanks
> > 
> > Phillip
> > 
> > 
> > > That's of course more involved though, so I understand in case you're
> > > not interested in doing that.
> > > 
> > > > If not, I will likely provide it in the man-pages repository as a help
> > > > tool (which might end up packed by distros as part of manpages-utils).
> > > > Is that okay to you?  (I ask mainly because it's using the git-
> > > > namespace for commands, so you should at lease be aware of it.)
> > > 
> > > I mean overall this is our primary way of extension, by picking up
> > > utilities that have the "git-" prefix. So arguably you don't have to ask
> > > us for permission to do that.
> > > 
> > > Whether it makes sense to distribute such a tool as part of
> > > manpages-utils is a different question, and one where I myself am of a
> > > split mind. But that feels more like a question for distributors rather
> > > than for us in the Git project.
> > > 
> > > Thanks!
> > > 
> > > Patrick
> > 
> 
> -- 
> <https://www.alejandro-colomar.es>
-- 
<https://www.alejandro-colomar.es>

Back to recent threads