From: Alejandro Colomar <alx@kernel.org>
To: Nico Williams <nico@cryptonector.com>
Cc: Junio C Hamano <gitster@pobox.com>,
git@vger.kernel.org, Ben Boeckel <mathstuf@gmail.com>,
Viktor Dukhovni <viktor@openssl.org>
Subject: Re: [RFC] git-brebase
Date: Sat, 3 Oct 2026 23:38:29 +0200 [thread overview]
Message-ID: <asF0DkNtlnJ9-Sng@debian> (raw)
In-Reply-To: <asFv9QcpLgzPnnFb@ubby>
[-- Attachment #1: Type: text/plain, Size: 5987 bytes --]
Hi Nico,
> Date: 2026-10-03 16:13:25-0500
> From: Nico Williams <nico@cryptonector.com>
>
> On Sat, Oct 03, 2026 at 10:56:25PM +0200, Alejandro Colomar wrote:
> > > I also have a getopts_long-like function (see my gists) for bash if you
> > > like.
> >
> > I think getopts(1) is not usable for git(1)-related scripts, because
> > getopts(1) interprets '--' as the end of the options, but git(1) uses it
> > for distinguishing commits from paths. If anyone shows me how it can be
> > used, I'd be interested, because I've hit this issue in the past with
> > other script.
>
> https://gist.github.com/nicowilliams/f3fe2b10b380aecdef403acb246dced2
>
> Though there's many ways to do this.
That one still consumes the '--', but we don't want to consume it. We
want it to remain there in $@ after the options have been parsed.
> > > > cat >"$callback" <<__EOF__
> > > > #!/bin/bash
> > > > ...
> > > > __EOF__
> > > > chmod +x "$callback";
> > >
> > > Here what might be better is to have a command-line option to execute
> > > this callback without having to write it to a file,
> >
> > How would you do it?
>
> I'd have an option or sub-command of the main script that says "do the
> callback thing", then when you run `git bisect run ...` put in the name
> of this script as the command and the "do the callback thing" option
> next.
I'd need to see some code. I'm not seeing it. :)
> > > and use environment
> > > variables to pass arguments to it.
> >
> > The callback doesn't really need any arguments, since 'git bisect run'
> > won't pass any arguments to it.
>
> But you're embedding values into the temp executable script -- if you
> don't have that any more you'll have to pass those in.
But why would we want to not have it?
That would complicate the script, no?
> > > which means I can't use this in detached HEAD mode :(
> >
> > Oh! I wasn't aware that git-rebase(1) supported detached HEAD mode.
>
> Sure does!
>
> > > I work in detached HEAD mode almost exclusively. I know, that's..
> > > weird. But it works for me.
> >
> > Ouch! Indeed. :)
> > Out of curiosity, are there any interesting reasons for such
> > self-implied pain?
>
> I often do:
>
> : ; git checkout origin/master
> : ; <do some work>
> : ; git add ...; git commit -m '...'
> : ; git push myfork HEAD:refs/heads/the-branch-name-here # <-- I name it here
>
> then open a PR.
>
> Now I don't have a branch here, but who cares? If I switch to other
> work and later want to come back to this work I'll either a) create a
> local branch then, and/or b) when I resume work on the first thing I'll
> `git checkout myfork/the-branch-name-here` and... once more work in
> detached HEAD mode.
>
> And if I need to see "what was I doing?" then I use `git log --oneline`
> and `git reflog` and I quickly see the remote branch of interest.
>
> The remote branches are the symbolic names I need to preserve, and my
> clone will know them, so I only need local branch names for things I
> work on w/o a network or over a long time.
>
> I do exaggerate a bit. I do this a lot, but maybe not quite "almost
> exclusively". Often I'm forced to have a local branch by opinionated
> tools other than git itself.
Hmmm, actually resembles what I do. I use branches, then push to
a remote, and once it's in the remote, I remove the local branch.
I try to remove the local branches as soon as I can, because that way
I don't need to remember whether there was something I forgot to push,
or I wanted to explicitly discard it. If there's no local branch,
there's no confusion. Since I work with two local computers, having the
source of truth be the remote makes it less ambiguous. But while
working locally, the branch helps a lot.
Anyway, I've patched it to work with detached HEAD. (I need to remember
to add two traps, now.)
diff --git i/src/bin/git-brebase w/src/bin/git-brebase
index d652c37ef08d..a57acc350d7e 100755
--- i/src/bin/git-brebase
+++ w/src/bin/git-brebase
@@ -50,8 +50,16 @@ if test $# -gt 1; then
fi;
git rev-list -1 "$1" \
| read -r tgt;
-git rev-parse --abbrev-ref HEAD \
+
+mktemp \
| read -r branch;
+{
+ git rev-parse --abbrev-ref HEAD;
+ git rev-list -1 HEAD;
+} \
+| sed '/^HEAD$/d' \
+| sed '1!d' \
+>"$branch";
# Set up the callback script for 'git rebase run'.
mktemp \
@@ -91,7 +99,8 @@ cat >"$callback" <<__EOF__
fi;
fi;
- git switch '$branch' >/dev/null 2>/dev/null;
+ cat '$branch' \
+ | xargs -I{} git checkout {} >/dev/null 2>/dev/null;
git rev-list -1 HEAD \
| read -r old_head;
printf '%s' 'Rebase: ';
@@ -103,6 +112,13 @@ cat >"$callback" <<__EOF__
git checkout --detach "\$bisect_head" 2>/dev/null;
exit 1;
fi;
+ {
+ git rev-parse --abbrev-ref HEAD;
+ git rev-list -1 HEAD;
+ } \
+ | sed '/^HEAD$/d' \
+ | sed '1!d' \
+ >"$branch";
if test -n '$post'; then
printf '%s' 'Post-rebase exec: ';
@@ -146,7 +162,8 @@ fi;
# shellcheck disable=SC2248 # gbopts may hold multiple options
git bisect start $gbopts >/dev/null;
git bisect bad "$tgt" >/dev/null;
-git merge-base "$branch" "$tgt" \
+cat "$branch" \
+| xargs -I{} git merge-base {} "$tgt" \
| xargs -I{} git bisect good {};
git bisect run "$callback";
git rev-list -1 bisect/bad \
@@ -154,7 +171,8 @@ git rev-list -1 bisect/bad \
git bisect reset >/dev/null 2>/dev/null;
# Perform the conflicting rebase
-git switch "$branch";
+cat "$branch" \
+| xargs -I{} git checkout {};
# shellcheck disable=SC2086 # gropts may hold multiple options
git rebase $gropts "$bad";
if test -v post; then
I've tested it, and it works fine with a detached HEAD.
Cheers,
Alex
>
> Nico
> --
--
<https://www.alejandro-colomar.es>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2026-10-03 21:38 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-03 20:11 [RFC] git-brebase Alejandro Colomar
2026-10-03 20:13 ` Alejandro Colomar
2026-10-03 20:39 ` Nico Williams
2026-10-03 20:48 ` Nico Williams
2026-10-03 21:07 ` Alejandro Colomar
2026-10-03 21:17 ` Nico Williams
2026-10-03 21:29 ` Alejandro Colomar
2026-10-03 21:50 ` Nico Williams
2026-10-03 20:56 ` Alejandro Colomar
2026-10-03 21:13 ` Nico Williams
2026-10-03 21:38 ` Alejandro Colomar [this message]
2026-10-03 22:19 ` Nico Williams
2026-10-03 21:17 ` Alejandro Colomar
2026-10-08 22:18 ` [RFC v3] git-bisect-rebase Alejandro Colomar
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=asF0DkNtlnJ9-Sng@debian \
--to=alx@kernel.org \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=mathstuf@gmail.com \
--cc=nico@cryptonector.com \
--cc=viktor@openssl.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox