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

Re: git-rebase-walk

From
ACAlejandro Colomar <alx@kernel.org>
Date
Oct 1, 2026, 20:29 UTC
Message-ID
<ar69ZZ4r9ZxISIHz@debian>
In-Reply-To
<ar6a8OkGhmYVoM7E@ubby>
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>
Previous: Nico WilliamsNext: Nico Williams
Message 17 of 21 in “git-rebase-walk”
  1. Alejandro ColomarOct 1, 2026
  2. Patrick SteinhardtOct 1, 2026
  3. Alejandro ColomarOct 1, 2026
  4. Patrick SteinhardtOct 2, 2026
  5. Alejandro ColomarOct 2, 2026
  6. Nico WilliamsOct 3, 2026
  7. Phillip WoodOct 4, 2026
  8. Alejandro ColomarOct 5, 2026
  9. Alejandro ColomarOct 5, 2026
  10. Phillip WoodOct 6, 2026
  11. Nico WilliamsOct 6, 2026
  12. Alejandro ColomarOct 6, 2026
  13. Junio C HamanoOct 1, 2026
  14. Nico WilliamsOct 1, 2026
  15. Alejandro ColomarOct 1, 2026
  16. Nico WilliamsOct 1, 2026
  17. Alejandro ColomarOct 1, 2026
  18. Nico WilliamsOct 1, 2026
  19. Nico WilliamsOct 1, 2026
  20. Simon RichterOct 2, 2026
  21. Nico WilliamsOct 2, 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.