threads / patch / 39593

v3git-rebase--interactive.sh: add config option for custom instruction format

Subject: [PATCH v3] git-rebase--interactive.sh: add config option for custom instruction format

## tl;dr

5 messages between Jun 11, 2015 and Jun 11, 2015. Diffs are folded; open one to read it.

replies: 4people: 2as markdown or json

Michael Rappazzo· Jun 11, 2015, 01:30 UTC · lore
Difference between v2 and v3 of this patch:
    - Fixed autosquash
    - Added documentation on the config options
    - Added two tests to t3414 (rebase-autosquash)
Michael Rappazzo (1):
  git-rebase--interactive.sh: add config option for custom instruction
    format
 Documentation/git-rebase.txt |  7 +++++++
 git-rebase--interactive.sh   | 34 ++++++++++++++++++++++++++++------
 t/t3415-rebase-autosquash.sh | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+), 6 deletions(-)
-- 
2.4.2
Michael Rappazzo· Jun 11, 2015, 01:30 UTC · re: Michael Rappazzo · lore

[PATCH] git-rebase--interactive.sh: add config option for custom instruction format

A config option 'rebase.instructionFormat' can override the default 'oneline' format of the rebase instruction list.

Since the list is parsed using the left, right or boundary mark plus the sha1, they are prepended to the instruction format.

Signed-off-by: Michael Rappazzo <rappazzo@gmail.com>
---
 Documentation/git-rebase.txt |  7 +++++++
 git-rebase--interactive.sh   | 34 ++++++++++++++++++++++++++++------
 t/t3415-rebase-autosquash.sh | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 68 insertions(+), 6 deletions(-)
Show changes to 3 files +68 −6

Documentation/git-rebase.txt, git-rebase--interactive.sh, t/t3415-rebase-autosquash.sh

diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 1d01baa..8ddab77 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -213,6 +213,9 @@ rebase.autoSquash::
 rebase.autoStash::
 	If set to true enable '--autostash' option by default.
 
+rebase.instructionFormat::
+   Custom commit list format to use during an '--interactive' rebase.
+
 OPTIONS
 -------
 --onto <newbase>::
@@ -359,6 +362,10 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
 	Make a list of the commits which are about to be rebased.  Let the
 	user edit that list before rebasing.  This mode can also be used to
 	split commits (see SPLITTING COMMITS below).
++
+The commit list format can be changed by setting the configuration option
+rebase.instructionFormat.  A customized instruction format will automatically
+have the long commit hash prepended to the format.
 
 -p::
 --preserve-merges::
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index dc3133f..6d14315 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -740,10 +740,19 @@ collapse_todo_ids() {
 # "pick sha1 fixup!/squash! msg" appears in it so that the latter
 # comes immediately after the former, and change "pick" to
 # "fixup"/"squash".
+#
+# Note that if the config has specified a custom instruction format
+# each log message will be re-retrieved in order to normalize the 
+# autosquash arrangement
 rearrange_squash () {
 	# extract fixup!/squash! lines and resolve any referenced sha1's
-	while read -r pick sha1 message
+	while read -r pick sha1 todo_message
 	do
+		message=${todo_message}
+		if test -n "${format}"
+		then
+			message=$(git log -n 1 --format="%s" ${sha1})
+		fi
 		case "$message" in
 		"squash! "*|"fixup! "*)
 			action="${message%%!*}"
@@ -779,12 +788,17 @@ rearrange_squash () {
 	test -s "$1.sq" || return
 
 	used=
-	while read -r pick sha1 message
+	while read -r pick sha1 todo_message
 	do
 		case " $used" in
 		*" $sha1 "*) continue ;;
 		esac
-		printf '%s\n' "$pick $sha1 $message"
+		message=$todo_message
+		if test -n "${format}"
+		then
+			message=$(git log -n 1 --format="%s" ${sha1})
+		fi
+		printf '%s\n' "$pick $sha1 $todo_message"
 		used="$used$sha1 "
 		while read -r squash action msg_prefix msg_content
 		do
@@ -802,8 +816,13 @@ rearrange_squash () {
 				case "$message" in "$msg_content"*) emit=1;; esac ;;
 			esac
 			if test $emit = 1; then
-				real_prefix=$(echo "$msg_prefix" | sed "s/,/! /g")
-				printf '%s\n' "$action $squash ${real_prefix}$msg_content"
+				if test -n "${format}"
+				then
+					msg_content=$(git log -n 1 --format="${format}" ${squash})
+				else
+					msg_content="$(echo "$msg_prefix" | sed "s/,/! /g")$msg_content"
+				fi
+				printf '%s\n' "$action $squash $msg_content"
 				used="$used$squash "
 			fi
 		done <"$1.sq"
@@ -977,7 +996,10 @@ else
 	revisions=$onto...$orig_head
 	shortrevisions=$shorthead
 fi
-git rev-list $merges_option --pretty=oneline --reverse --left-right --topo-order \
+format=$(git config --get rebase.instructionFormat)
+# the 'rev-list .. | sed' requires %m to parse; the instruction requires %H to parse
+git rev-list $merges_option --format="%m%H ${format:-%s}" \
+	--reverse --left-right --topo-order \
 	$revisions ${restrict_revision+^$restrict_revision} | \
 	sed -n "s/^>//p" |
 while read -r sha1 rest
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index 41370ab..1ef96eb 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -250,4 +250,37 @@ test_expect_success 'squash! fixup!' '
 	test_auto_fixup_fixup squash fixup
 '
 
+test_expect_success 'autosquash with custom inst format matching on sha1' '
+	git reset --hard base &&
+	git config --add rebase.instructionFormat "[%an @ %ar] %s"  &&
+	echo 1 >file1 &&
+	git add -u &&
+	test_tick &&
+	git commit -m "squash! $(git rev-parse --short HEAD^)" &&
+	git tag final-shasquash-instFmt &&
+	test_tick &&
+	git rebase --autosquash -i HEAD^^^ &&
+	git log --oneline >actual &&
+	test_line_count = 3 actual &&
+	git diff --exit-code final-shasquash-instFmt &&
+	test 1 = "$(git cat-file blob HEAD^:file1)" &&
+	test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
+'
+
+test_expect_success 'autosquash with custom inst format matching on comment' '
+	git reset --hard base &&
+	git config --add rebase.instructionFormat "[%an @ %ar] %s"  &&
+	echo 1 >file1 &&
+	git add -u &&
+	test_tick &&
+	git commit -m "squash! $(git log -n 1 --format=%s HEAD^)" &&
+	git tag final-comment-squash-instFmt &&
+	test_tick &&
+	git rebase --autosquash -i HEAD^^^ &&
+	git log --oneline >actual &&
+	test_line_count = 3 actual &&
+	git diff --exit-code final-comment-squash-instFmt &&
+	test 1 = "$(git cat-file blob HEAD^:file1)" &&
+	test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
+'
 test_done
-- 
2.4.2
Johannes Schindelin· Jun 11, 2015, 13:40 UTC · re: Michael Rappazzo · lore

Re: [PATCH] git-rebase--interactive.sh: add config option for custom instruction format

Hi Michael,
On 2015-06-11 03:30, Michael Rappazzo wrote:
Show 18 quoted lines
> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
> index dc3133f..6d14315 100644
> --- a/git-rebase--interactive.sh
> +++ b/git-rebase--interactive.sh
> @@ -740,10 +740,19 @@ collapse_todo_ids() {
>  # "pick sha1 fixup!/squash! msg" appears in it so that the latter
>  # comes immediately after the former, and change "pick" to
>  # "fixup"/"squash".
> +#
> +# Note that if the config has specified a custom instruction format
> +# each log message will be re-retrieved in order to normalize the 
> +# autosquash arrangement
>  rearrange_squash () {
>  	# extract fixup!/squash! lines and resolve any referenced sha1's
> -	while read -r pick sha1 message
> +	while read -r pick sha1 todo_message
>  	do
> +		message=${todo_message}
Why not just leave the `read -r pick sha1 message` as-is and simply write
		# For "autosquash":
		test -z "$format" ||
		message="$(git log -n 1 --format="%s" $sha1)"
here?
Show 18 quoted lines
> diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
> index 41370ab..1ef96eb 100755
> --- a/t/t3415-rebase-autosquash.sh
> +++ b/t/t3415-rebase-autosquash.sh
> @@ -250,4 +250,37 @@ test_expect_success 'squash! fixup!' '
>  	test_auto_fixup_fixup squash fixup
>  '
>  
> +test_expect_success 'autosquash with custom inst format matching on sha1' '
> +	git reset --hard base &&
> +	git config --add rebase.instructionFormat "[%an @ %ar] %s"  &&
> +	echo 1 >file1 &&
> +	git add -u &&
> +	test_tick &&
> +	git commit -m "squash! $(git rev-parse --short HEAD^)" &&
> +	git tag final-shasquash-instFmt &&
> +	test_tick &&
> +	git rebase --autosquash -i HEAD^^^ &&
We usually write HEAD~3 instead of HEAD^^^...
Show 23 quoted lines
> +	git log --oneline >actual &&
> +	test_line_count = 3 actual &&
> +	git diff --exit-code final-shasquash-instFmt &&
> +	test 1 = "$(git cat-file blob HEAD^:file1)" &&
> +	test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
> +'
> +
> +test_expect_success 'autosquash with custom inst format matching on comment' '
> +	git reset --hard base &&
> +	git config --add rebase.instructionFormat "[%an @ %ar] %s"  &&
> +	echo 1 >file1 &&
> +	git add -u &&
> +	test_tick &&
> +	git commit -m "squash! $(git log -n 1 --format=%s HEAD^)" &&
> +	git tag final-comment-squash-instFmt &&
> +	test_tick &&
> +	git rebase --autosquash -i HEAD^^^ &&
> +	git log --oneline >actual &&
> +	test_line_count = 3 actual &&
> +	git diff --exit-code final-comment-squash-instFmt &&
> +	test 1 = "$(git cat-file blob HEAD^:file1)" &&
> +	test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
> +'
That is copied almost verbatim, except for the commit message. The code would be easier to maintain if it did not repeat so much code e.g. by refactoring out a function that takes the commit message as a parameter.

Ciao, Johannes

Mike Rappazzo· Jun 11, 2015, 14:02 UTC · re: Johannes Schindelin · lore

Re: [PATCH] git-rebase--interactive.sh: add config option for custom instruction format

On Thu, Jun 11, 2015 at 9:40 AM, Johannes Schindelin <johannes.schindelin@gmx.de> wrote:

Show 30 quoted lines
> Hi Michael,
>
> On 2015-06-11 03:30, Michael Rappazzo wrote:
>
>> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
>> index dc3133f..6d14315 100644
>> --- a/git-rebase--interactive.sh
>> +++ b/git-rebase--interactive.sh
>> @@ -740,10 +740,19 @@ collapse_todo_ids() {
>>  # "pick sha1 fixup!/squash! msg" appears in it so that the latter
>>  # comes immediately after the former, and change "pick" to
>>  # "fixup"/"squash".
>> +#
>> +# Note that if the config has specified a custom instruction format
>> +# each log message will be re-retrieved in order to normalize the
>> +# autosquash arrangement
>>  rearrange_squash () {
>>       # extract fixup!/squash! lines and resolve any referenced sha1's
>> -     while read -r pick sha1 message
>> +     while read -r pick sha1 todo_message
>>       do
>> +             message=${todo_message}
>
> Why not just leave the `read -r pick sha1 message` as-is and simply write
>
>                 # For "autosquash":
>                 test -z "$format" ||
>                 message="$(git log -n 1 --format="%s" $sha1)"
>
> here?

I did notice that I am not using '$todo_message' in the first loop at all, so I will adjust it. In the second loop, I do use both the original and the reformatted. I will apply your suggestion there if applicable.

Show 6 quoted lines
>
>> diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
>> +     git rebase --autosquash -i HEAD^^^ &&
>
> We usually write HEAD~3 instead of HEAD^^^...
>

Sure, I'll adjust it. I personally usually use up to 3 '^' and then switch to '~' for > 3

>
> [The two test functions are] copied almost verbatim, except for the commit message. The code would be easier to maintain if it did not repeat so much code e.g. by refactoring out a function that takes the commit message as a parameter.
Makes sense.  I'll implement that.
Johannes Schindelin· Jun 11, 2015, 14:40 UTC · re: Mike Rappazzo · lore

Re: [PATCH] git-rebase--interactive.sh: add config option for custom instruction format

Hi Mike,
On 2015-06-11 16:02, Mike Rappazzo wrote:
Show 36 quoted lines
> On Thu, Jun 11, 2015 at 9:40 AM, Johannes Schindelin
> <johannes.schindelin@gmx.de> wrote:
>>
>> On 2015-06-11 03:30, Michael Rappazzo wrote:
>>
>>> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
>>> index dc3133f..6d14315 100644
>>> --- a/git-rebase--interactive.sh
>>> +++ b/git-rebase--interactive.sh
>>> @@ -740,10 +740,19 @@ collapse_todo_ids() {
>>>  # "pick sha1 fixup!/squash! msg" appears in it so that the latter
>>>  # comes immediately after the former, and change "pick" to
>>>  # "fixup"/"squash".
>>> +#
>>> +# Note that if the config has specified a custom instruction format
>>> +# each log message will be re-retrieved in order to normalize the
>>> +# autosquash arrangement
>>>  rearrange_squash () {
>>>       # extract fixup!/squash! lines and resolve any referenced sha1's
>>> -     while read -r pick sha1 message
>>> +     while read -r pick sha1 todo_message
>>>       do
>>> +             message=${todo_message}
>>
>> Why not just leave the `read -r pick sha1 message` as-is and simply write
>>
>>                 # For "autosquash":
>>                 test -z "$format" ||
>>                 message="$(git log -n 1 --format="%s" $sha1)"
>>
>> here?
> 
> I did notice that I am not using '$todo_message' in the first loop at
> all, so I will adjust it.  In the second loop, I do use both the
> original and the reformatted.  I will apply your suggestion there if
> applicable.
It might make sense to use
                 if test -z "$format"
                 then
                         oneline="$message"
                 else
                         oneline="$(git log -n 1 --format="%s" $sha1)"
                 fi
in the instances where you need to compare against the original oneline, and then only adjust the "message" variable name in places that require the original oneline.
>> [The two test functions are] copied almost verbatim, except for the commit message. The code would be easier to maintain if it did not repeat so much code e.g. by refactoring out a function that takes the commit message as a parameter.
> 
> Makes sense.  I'll implement that.

Thank you, Johannes

← back to recent threads