Re: "bubbling up" patches in a commit sequence.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Yves,

On Sat, 13 Aug 2022, demerphq wrote:

> I keep finding myself using interactive rebase to try to find the
> earliest place in a change sequence that a given commit can be placed
> without conflicting with any other patch.

I find myself doing that a lot, too. So much so that I wrote shell code to
do that for me. The essential idea is to use the diff hunk header of the
hunk that I want to stage and transmogrify it into the `-L
<start>,<end>:<path>` parameter of `git log` (and yes, the `sed` call to
transmogrify that is a bit hard to read).

The relevant part of the code looks like this:

-- snip --
sh_quote () {
	for arg
	do
		echo "'$(echo "$arg" | sed "s/'/'\\''/g")'"
	done
}

staged_log () { # [--upstream=<ref> | -u <ref>]
	upstream=not\ set
	while case "$1" in
	--upstream) shift; upstream="$1";;
	--upstream=*) upstream="${1#*=}";;
	-u) shift; upstream="$1";;
	-*) die "Unknown option: $1";;
	*) break;;
	esac; do shift; done

	test not\ set != "$upstream" ||
	upstream="$(git rev-parse @{upstream} 2>/dev/null)"

	# look beyond upstream if identical to HEAD
	test -z "$upstream" || test 0 != $(git rev-list --count $upstream..) || upstream=
	diff="$(git diff --cached -U1)"
	cached_diff="$diff"
	test -n "$diff" ||
	diff="$(git diff -U1)"
	test -n "$diff" ||
	die "No changes"

	args="$(echo "$diff" |
		sed -ne '/^--- a\//{s/^-* a\/\(.*\)/'\''\1'\''/;x}' -e \
			'/^@@ -/{s/^@@ -\([^, ]*\),\([^ ]*\).*/-L \1,+\2/;s/^@@ -\([^,]*\) .*/-L \1,+1/;G;s/\n/:/g;p}' |
			tr '\n' ' ') ${upstream:+$upstream..} $(sh_quote "$@")"

	eval "git log $args"

	revs="$(eval "git log --pretty=%H --no-patch $args")"
	case "$revs" in
	*[!0-9a-z]*) ;; # multiple revs
	'')
		# not a single rev
		test -z "$upstream" ||
		staged_log -u ''
		;;
	?*)
		printf "Commit (yes/no/edit)? "
		read line
		case "$line" in
		[Yy]*) git commit --fixup "$revs" $(test -n "$cached_diff" || echo "-a");;
		[Ee]*) git commit --fixup "$revs" $(test -n "$cached_diff" || echo "-a") -se;;
		esac
		;;
	esac
}
-- snap --

Unfortunately, the `-L <...>` code currently works reliably only for a
single hunk, if I use multiple hunks, I sometimes run into assertions.

To help with that, the shell code looks at the staged hunk(s), if any.
Only if no changes are staged, it falls back to the unstaged diff.

Ciao,
Dscho



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux