[RFC PATCH 0/9][Outreachy] rebase -i: add options to fixup command

STALE2073d

Revision rfc of 5 in this series.

97 messages, 6 authors, 2021-02-06 · page 2 of 2 · open the first message on its own page

Re: [PATCH v4 6/9] rebase -i: add fixup [-C | -c] command

From: Eric Sunshine <hidden>
Date: 2021-02-03 05:06:39

On Tue, Feb 2, 2021 at 10:29 AM Charvi Mendiratta [off-list ref] wrote:
On Tue, 2 Feb 2021 at 06:17, Eric Sunshine [off-list ref] wrote:
quoted
When `-c` says "edit the commit message" it's not clear what will be
edited. The original's commit message? The replacement's message? A
combination of the two? If you can come up with a succinct way to word
it such that it states more precisely what exactly will be edited, it
would be nice, but not necessarily worth a re-roll.
Here the editor shows the commented out commit message of original commit and
the replacement commit message (of fixup -c commit) is not commented out.

So maybe s/edit the commit message/edit this commit message  is better.
Yes, that would be clearer and is just as succinct.
quoted
This code adds to the confusion. In the function argument list, `flag`
has been declared as a single enum item, yet this code is treating
`flag` as if it is a combination of bits. So, it's not clear what the
intention is here. Is `flag` always going to be a specific enum item
in this context or is it going to be a combination of bits? If it is
only ever going to be a distinct enum item, then one would expect this
code to be written like this:

    return command == TODO_FIXUP &&
        (flag == TODO_REPLACE_FIXUP_MSG ||
        flag == TODO_EDIT_FIXUP_MSG);
I admit it resulted in a bit of confusion. Here, its true that flag is always
going to be specific enum item( as command can be merge -c, fixup -c, or
fixup -C ) and I combined the bag of bits to denote
the specific enum item. So, maybe we can go with the first method?
Sounds fine. It would clarify the intent.
quoted
By the way, the function name check_fixup_flag() doesn't necessarily
do a good job conveying the purpose of this function. Based upon the
implementation, I gather that it is checking whether the command is a
"fixup" command, so perhaps the name could reflect that. Perhaps
is_fixup() or something?
Agree, here it's checking if the command is fixup and the flag value (
which implies either user has given command fixup -c or fixup -C )
So, I wonder if we can write is_fixup_flag() ?
Reasonable.
quoted
I was wondering if the above could be rephrased like this to avoid the
repetition:
[...]
but perhaps it's too magical and ugly.
I agree, this [tolower(bol[1]) == 'c'] is actually doing all the
magic, but I am not
sure if we should change it or not ? As in the source code just after
this code we
are checking in a similar way for the 'merge' command. So, maybe implementing
in a similar way is easier to read ?
Keeping it similar to nearby code makes sense.

Re: [PATCH v4 7/9] t3437: test script for fixup [-C|-c] options in interactive rebase

From: Eric Sunshine <hidden>
Date: 2021-02-03 05:45:38

On Tue, Feb 2, 2021 at 5:02 AM Christian Couder
[off-list ref] wrote:
On Tue, Feb 2, 2021 at 3:01 AM Eric Sunshine [off-list ref] wrote:
quoted
On Fri, Jan 29, 2021 at 1:25 PM Charvi Mendiratta [off-list ref] wrote:
quoted
+               merge_*|fixup_*)
+                       action=$(echo "$line" | sed 's/_/ /g');;
What is "merge_" doing here? It doesn't seem to be used by this patch.
Yeah, it's not used, but it might be a good thing to add this for
consistency while at it.
It confuses readers (as it did to me), causing them to waste
brain-cycles trying to figure out why it's present. Thus, it would be
better to add it when it's actually needed. The waste of brain-cycles
and time is especially important on a project like Git for which
reviewers and reviewer time are limited resources.
quoted
quoted
+# Copyright (c) 2018 Phillip Wood
Did Phillip write this script? Is this patch based upon an old patch from him?
Yeah, it might be a good idea to add a "Based-on-patch-by: Phillip ..."
Agreed.
quoted
The implementation of test_commit_message() is a bit hard to follow.
It might be simpler to write it more concisely and directly like this:

    git show --no-patch --pretty=format:%B "$1" >actual &&
    case "$2" in
    -m) echo "$3" >expect && test_cmp expect actual ;;
I think we try to avoid many commands on the same line.
For something this minor, it's not likely to matter but, of course, it
could be split over two lines:

    -m) echo "$3" >expect &&
        test_cmp expect actual ;;
quoted
    *) test_cmp "$2" actual ;;
    esac
In general I am not sure that using $1, $2, $3 directly makes things
easier to understand, but yeah, with the function documentation that
you suggest, it might be better to write the function using them
directly.
The direct $1, $2, etc. was just an example. It's certainly possible
to give them names even in the rewritten code I presented. One good
reason, however, for just using $1, $2, etc. is that $2 is not well
defined; sometimes it's a switch ("-m") and sometimes its a pathname,
so it's hard to invent a suitable variable name for it. Also, this
function becomes so simple (in the rewritten version) that explicit
variable names don't add a lot of value (the cognitive load is quite
low because the function is so short).
quoted
Style nit: In Git test scripts, the here-doc body and EOF are indented
the same amount as the command which opened the here-doc:
I don't think we are very consistent with this and I didn't find
anything about this in CodingGuidelines.

In t0008 and t0021 for example, the indentation is more like:

     cat >message <<-EOF &&
          amend! B
          ...
          body
     EOF

and I like this style, as it seems clearer than the other styles.
I performed a quick survey of the heredoc styles in the tests. Here
are the results[1] of my analysis on the 'seen' branch:

total-heredocs=4128

same-indent=3053 (<<EOF & body & EOF share indent)

    cat >expect <<-\EOF
    body
    EOF

body-eof-indented=24 (body & EOF indented)

    cat >expect <<-\EOF
        body
        EOF

body-indented=735 (body indented; EOF not)

    cat >expect <<-\EOF
        body
    EOF

left-margin=316 (<<EOF indented; body & EOF not)

        cat >expect <<\EOF
    body
    EOF

So, the indentation recommended in my review -- with 3053 instances
out of 4128 heredocs -- is by far the most prevalent in the project.

[1]: Note that there is a miniscule amount of inaccuracy in the
numbers because there are a few cases in which heredocs contain other
heredocs, and some scripts build heredocs piecemeal when constructing
other scripts, and I didn't bother making my analysis script handle
those few cases. The inaccuracy is tiny, thus not meaningful to the
overall picture.
quoted
I see that you mirrored the implementation of FAKE_LINES handling of
"exec" here for "fixup", but the cases are quite different. The
argument to "exec" is arbitrary and can have any number of spaces
embedded in it, which conflicts with the meaning of spaces in
FAKE_LINES, which separate the individual commands in FAKE_LINES.
Consequently, "_" was chosen as a placeholder in "exec" to mean
"space".

However, "fixup" is a very different beast. Its arguments are not
arbitrary at all, so there isn't a good reason to mirror the choice of
"_" to represent a space, which leads to rather unsightly tokens such
as "fixup_-C". It would work just as well to use simpler tokens such
as "fixup-C" and "fixup-c", in which case t/lib-rebase.sh might parse
them like this (note that I also dropped `g` from the `sed` action):

    fixup-*)
        action=$(echo "$line" | sed 's/-/ -/');;
I agree that "fixup" arguments are not arbitrary at all, but I think
it makes things simpler to just use one way to encode spaces instead
of many different ways.
Is that the intention here, though? Is the idea that some day `fixup`
will accept arbitrary arguments thus needs to encode spaces? If not,
then mirroring the treatment given to `exec` confuses readers into
thinking that it will/should accept arbitrary arguments. I brought
this up in my review specifically because it was confusing to a person
(me) new to this topic and reading the patches for the first time. The
more specific and exact the code can be, the less likely it will
confuse readers in the future.

Anyhow, it's a minor point, not worth expending a lot of time discussing.
quoted
It feels clunky and fragile for this test to be changing
"expected-message" which was created in the "setup" test and used
unaltered up to this point. If the content of "expected-message" is
really going to change from test to test (as I see it changes again in
a later test), then it would be easier to reason about the behavior if
each test gives "expected-message" the precise content it should have
in that local context. As it is currently implemented, it's too
difficult to follow along and remember the value of "expected-message"
from test to test. It also makes it difficult to extend tests or add
new tests in between existing tests without negatively impacting other
tests. If each test sets up "expected-message" to the precise content
needed by the test, then both those problems go away.
Yeah, perhaps the global "expected-message" could be renamed for
example "global-expected-message", and tests which need a specific one
could prepare and use a custom "expected-message" (maybe named
"custom-expected-message") without ever changing
"global-expected-message".
That would be fine, though I wondered while reviewing the patch if a
global "expect-message" file was even needed since it didn't seem like
very many tests used it (but I didn't spend a lot of time counting the
exact number of tests due to the high cognitive load tracing how that
file might mutate as it passed through each test).

Another really good reason for avoiding having later tests depend upon
mutations from earlier tests, if possible, is that it makes it easier
to run tests selectively with --run or GIT_SKIP_TESTS.

Re: [PATCH v4 6/9] rebase -i: add fixup [-C | -c] command

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 00:02:00

On Wed, 3 Feb 2021 at 10:35, Eric Sunshine [off-list ref] wrote:
quoted
quoted
    return command == TODO_FIXUP &&
        (flag == TODO_REPLACE_FIXUP_MSG ||
        flag == TODO_EDIT_FIXUP_MSG);
I admit it resulted in a bit of confusion. Here, its true that flag is always
going to be specific enum item( as command can be merge -c, fixup -c, or
fixup -C ) and I combined the bag of bits to denote
the specific enum item. So, maybe we can go with the first method?
Sounds fine. It would clarify the intent.
(Apology for confusion) After, looking again at the source code, as we are using
the flag element of  the structure todo_item of in sequencer.h. So, I
think right
way is to let it be in binary only and change type from 'enum todo_item_flag' to
'unsigned' , as you suggested below (better than first method) :

Otherwise, if `flag` will actually be a bag of bits, then the argument
should be declared as such:

    static int check_fixup_flag(enum todo_command command,
        unsigned flag)
quoted
Agree, here it's checking if the command is fixup and the flag value (
which implies either user has given command fixup -c or fixup -C )
So, I wonder if we can write is_fixup_flag() ?
Reasonable.
[...]
quoted
I agree, this [tolower(bol[1]) == 'c'] is actually doing all the
magic, but I am not
sure if we should change it or not ? As in the source code just after
this code we
are checking in a similar way for the 'merge' command. So, maybe implementing
in a similar way is easier to read ?
Keeping it similar to nearby code makes sense.
Thanks for confirming!

Thanks and Regards,
Charvi

Re: [PATCH v4 7/9] t3437: test script for fixup [-C|-c] options in interactive rebase

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 00:05:41

On Wed, 3 Feb 2021 at 11:14, Eric Sunshine [off-list ref] wrote:
quoted
quoted
What is "merge_" doing here? It doesn't seem to be used by this patch.
Yeah, it's not used, but it might be a good thing to add this for
consistency while at it.
It confuses readers (as it did to me), causing them to waste
brain-cycles trying to figure out why it's present. Thus, it would be
better to add it when it's actually needed. The waste of brain-cycles
and time is especially important on a project like Git for which
reviewers and reviewer time are limited resources.
Okay, I will remove "merge_" from this patch series and maybe later will make
separate patch for it and also adding its tests and updating
t3430-rebase-merges.sh
quoted
quoted
quoted
+# Copyright (c) 2018 Phillip Wood
Did Phillip write this script? Is this patch based upon an old patch from him?
Yeah, it might be a good idea to add a "Based-on-patch-by: Phillip ..."
Agreed.
quoted
quoted
The implementation of test_commit_message() is a bit hard to follow.
It might be simpler to write it more concisely and directly like this:

    git show --no-patch --pretty=format:%B "$1" >actual &&
    case "$2" in
    -m) echo "$3" >expect && test_cmp expect actual ;;
I think we try to avoid many commands on the same line.
For something this minor, it's not likely to matter but, of course, it
could be split over two lines:

    -m) echo "$3" >expect &&
        test_cmp expect actual ;;
quoted
quoted
    *) test_cmp "$2" actual ;;
    esac
In general I am not sure that using $1, $2, $3 directly makes things
easier to understand, but yeah, with the function documentation that
you suggest, it might be better to write the function using them
directly.
The direct $1, $2, etc. was just an example. It's certainly possible
to give them names even in the rewritten code I presented. One good
reason, however, for just using $1, $2, etc. is that $2 is not well
defined; sometimes it's a switch ("-m") and sometimes its a pathname,
so it's hard to invent a suitable variable name for it. Also, this
function becomes so simple (in the rewritten version) that explicit
variable names don't add a lot of value (the cognitive load is quite
low because the function is so short).
Agree, and will update it.
quoted
quoted
Style nit: In Git test scripts, the here-doc body and EOF are indented
the same amount as the command which opened the here-doc:
I don't think we are very consistent with this and I didn't find
anything about this in CodingGuidelines.

In t0008 and t0021 for example, the indentation is more like:

     cat >message <<-EOF &&
          amend! B
          ...
          body
     EOF

and I like this style, as it seems clearer than the other styles.
I performed a quick survey of the heredoc styles in the tests. Here
are the results[1] of my analysis on the 'seen' branch:

total-heredocs=4128

same-indent=3053 (<<EOF & body & EOF share indent)

    cat >expect <<-\EOF
    body
    EOF

body-eof-indented=24 (body & EOF indented)

    cat >expect <<-\EOF
        body
        EOF

body-indented=735 (body indented; EOF not)

    cat >expect <<-\EOF
        body
    EOF

left-margin=316 (<<EOF indented; body & EOF not)

        cat >expect <<\EOF
    body
    EOF

So, the indentation recommended in my review -- with 3053 instances
out of 4128 heredocs -- is by far the most prevalent in the project.

[1]: Note that there is a miniscule amount of inaccuracy in the
numbers because there are a few cases in which heredocs contain other
heredocs, and some scripts build heredocs piecemeal when constructing
other scripts, and I didn't bother making my analysis script handle
those few cases. The inaccuracy is tiny, thus not meaningful to the
overall picture.
Okay, will update the indentation.

[...]
quoted
quoted
    fixup-*)
        action=$(echo "$line" | sed 's/-/ -/');;
I agree that "fixup" arguments are not arbitrary at all, but I think
it makes things simpler to just use one way to encode spaces instead
of many different ways.
Is that the intention here, though? Is the idea that some day `fixup`
will accept arbitrary arguments thus needs to encode spaces? If not,
then mirroring the treatment given to `exec` confuses readers into
thinking that it will/should accept arbitrary arguments. I brought
this up in my review specifically because it was confusing to a person
(me) new to this topic and reading the patches for the first time. The
more specific and exact the code can be, the less likely it will
confuse readers in the future.
I also agree that fixup will not accept arbitrary arguments, So I think to
go with the method using fixup-*) (as suggested above).

[...]
quoted
Yeah, perhaps the global "expected-message" could be renamed for
example "global-expected-message", and tests which need a specific one
could prepare and use a custom "expected-message" (maybe named
"custom-expected-message") without ever changing
"global-expected-message".
That would be fine, though I wondered while reviewing the patch if a
global "expect-message" file was even needed since it didn't seem like
very many tests used it (but I didn't spend a lot of time counting the
exact number of tests due to the high cognitive load tracing how that
file might mutate as it passed through each test).

Another really good reason for avoiding having later tests depend upon
mutations from earlier tests, if possible, is that it makes it easier
to run tests selectively with --run or GIT_SKIP_TESTS.
Agree, also for this patch series I think to remove all tests for
amend!, change the
test setup and will take care this time to remove the test dependency
(in case of expected-message).

Thanks and Regards,
Charvi

Re: [PATCH v4 6/9] rebase -i: add fixup [-C | -c] command

From: Eric Sunshine <hidden>
Date: 2021-02-04 00:15:47

On Wed, Feb 3, 2021 at 7:01 PM Charvi Mendiratta [off-list ref] wrote:
quoted
quoted
I admit it resulted in a bit of confusion. Here, its true that flag is always
going to be specific enum item( as command can be merge -c, fixup -c, or
fixup -C ) and I combined the bag of bits to denote
the specific enum item. So, maybe we can go with the first method?
Sounds fine. It would clarify the intent.
(Apology for confusion) After, looking again at the source code, as we are using
the flag element of  the structure todo_item of in sequencer.h. So, I
think right
way is to let it be in binary only and change type from 'enum todo_item_flag' to
'unsigned' , as you suggested below (better than first method) :
That would be fine, as well. Thanks.

Re: [PATCH v4 7/9] t3437: test script for fixup [-C|-c] options in interactive rebase

From: Phillip Wood <hidden>
Date: 2021-02-04 10:47:52

Hi Eric

Thanks for taking such a close look at this series.

On 02/02/2021 02:01, Eric Sunshine wrote:
On Fri, Jan 29, 2021 at 1:25 PM Charvi Mendiratta [off-list ref] wrote:
[...]
quoted
+       ORIG_AUTHOR_NAME="$GIT_AUTHOR_NAME" &&
+       ORIG_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" &&
+       GIT_AUTHOR_NAME="Amend Author" &&
+       GIT_AUTHOR_EMAIL="amend@example.com" &&
+       test_commit "$(cat message)" A A1 A1 &&
+       test_commit A2 A &&
+       test_commit A3 A &&
+       GIT_AUTHOR_NAME="$ORIG_AUTHOR_NAME" &&
+       GIT_AUTHOR_EMAIL="$ORIG_AUTHOR_EMAIL" &&
Are the timestamps of these commits meaningful in this context?
I think we want to ensure that the timestamp of the commits created with the different author are different from the previous commits. We ought to be checking that the author date of the rebased commit matches the author date of the original commit and not the author date of the fixup commit created with the different author.
If not, another way to do this would be to assign the new author
name/email values in a subshell so that the values do not need to be
restored manually. For instance:

     (
         GIT_AUTHOR_NAME="Amend Author" &&
         GIT_AUTHOR_EMAIL="amend@example.com" &&
         test_commit "$(cat message)" A A1 A1 &&
         test_commit A2 A &&
         test_commit A3 A
     ) &&

It's a matter of taste whether or not that is preferable, though.
quoted
+       echo B1 >B &&
+       test_tick &&
+       git commit --fixup=HEAD -a &&
+       test_tick &&
Same question about whether the commit timestamps have any
significance in these tests.
Same answer as above - we want different author dates so we can check the original author date is not modified.

I'm not sure that we are actually checking the dates yet though it looks like we only check the author name and email at the moment.

Best Wishes

Phillip
If not, then these test_tick() calls
mislead the reader into thinking that the timestamps are significant,
thus it would make sense to drop them.
quoted
+test_expect_success 'simple fixup -C works' '
+       test_when_finished "test_might_fail git rebase --abort" &&
+       git checkout --detach A2 &&
+       FAKE_LINES="1 fixup_-C 2" git rebase -i B &&
I see that you mirrored the implementation of FAKE_LINES handling of
"exec" here for "fixup", but the cases are quite different. The
argument to "exec" is arbitrary and can have any number of spaces
embedded in it, which conflicts with the meaning of spaces in
FAKE_LINES, which separate the individual commands in FAKE_LINES.
Consequently, "_" was chosen as a placeholder in "exec" to mean
"space".

However, "fixup" is a very different beast. Its arguments are not
arbitrary at all, so there isn't a good reason to mirror the choice of
"_" to represent a space, which leads to rather unsightly tokens such
as "fixup_-C". It would work just as well to use simpler tokens such
as "fixup-C" and "fixup-c", in which case t/lib-rebase.sh might parse
them like this (note that I also dropped `g` from the `sed` action):

     fixup-*)
         action=$(echo "$line" | sed 's/-/ -/');;

In fact, the recognized set of options following "fixup" is so small,
that you could even get by with simpler tokens "fixupC" and "fixupc":

     fixupC)
         action="fixup -C";;
     fixupc)
         actions="fixup -c";;

Though it's subjective whether or not "fixupC" and "fixupc" are nicer
than "fixup-C" and "fixup-c", respectively.
quoted
+test_expect_success 'fixup -C removes amend! from message' '
+       test_when_finished "test_might_fail git rebase --abort" &&
+       git checkout --detach A1 &&
+       FAKE_LINES="1 fixup_-C 2" git rebase -i A &&
+       test_cmp_rev HEAD^ A &&
+       test_cmp_rev HEAD^{tree} A1^{tree} &&
+       test_commit_message HEAD expected-message &&
+       get_author HEAD >actual-author &&
+       test_cmp expected-author actual-author
+'
This test seems out of place. I would expect to see it added in the
patch which adds "amend!" functionality.

Alternatively, if the intention really is to support "amend!" this
early in the series in [6/9], then the commit message of [6/9] should
talk about it.
quoted
+test_expect_success 'fixup -C with conflicts gives correct message' '
+       test_when_finished "test_might_fail git rebase --abort" &&
Is there a reason this isn't written as:

     test_when_finished "reset_rebase" &&

which is more common? Is there something non-obvious which makes
reset_rebase() inappropriate in these tests?
quoted
+       git checkout --detach A1 &&
+       test_must_fail env FAKE_LINES="1 fixup_-C 2" git rebase -i conflicts &&
+       git checkout --theirs -- A &&
+       git add A &&
+       FAKE_COMMIT_AMEND=edited git rebase --continue &&
+       test_cmp_rev HEAD^ conflicts &&
+       test_cmp_rev HEAD^{tree} A1^{tree} &&
+       test_write_lines "" edited >>expected-message &&
It feels clunky and fragile for this test to be changing
"expected-message" which was created in the "setup" test and used
unaltered up to this point. If the content of "expected-message" is
really going to change from test to test (as I see it changes again in
a later test), then it would be easier to reason about the behavior if
each test gives "expected-message" the precise content it should have
in that local context. As it is currently implemented, it's too
difficult to follow along and remember the value of "expected-message"
from test to test. It also makes it difficult to extend tests or add
new tests in between existing tests without negatively impacting other
tests. If each test sets up "expected-message" to the precise content
needed by the test, then both those problems go away.
quoted
+test_expect_success 'multiple fixup -c opens editor once' '
+       test_when_finished "test_might_fail git rebase --abort" &&
+       git checkout --detach A3 &&
+       base=$(git rev-parse HEAD~4) &&
+       FAKE_COMMIT_MESSAGE="Modified-A3" \
+               FAKE_LINES="1 fixup_-C 2 fixup_-c 3 fixup_-c 4" \
+               EXPECT_HEADER_COUNT=4 \
+               git rebase -i $base &&
+       test_cmp_rev $base HEAD^ &&
+       test 1 = $(git show | grep Modified-A3 | wc -l)
+'
These days, we would phrase the last part of the test as:

     git show > raw &&
     grep Modified-A3 raw >out &&
     test_line_count = 1 out

Re: [PATCH v4 7/9] t3437: test script for fixup [-C|-c] options in interactive rebase

From: Eric Sunshine <hidden>
Date: 2021-02-04 16:16:29

On Thu, Feb 4, 2021 at 5:47 AM Phillip Wood [off-list ref] wrote:
On 02/02/2021 02:01, Eric Sunshine wrote:
quoted
Are the timestamps of these commits meaningful in this context?
I think we want to ensure that the timestamp of the commits created with
the different author are different from the previous commits. We ought
to be checking that the author date of the rebased commit matches the
author date of the original commit and not the author date of the fixup
commit created with the different author.
Such date-checking would indeed make sense and would remove any
potential confusion a reader might have concerning the manual
test_tick() calls. (It's not super important, but I still lean toward
dropping the test_tick() calls until they are actually needed simply
to avoid confusing readers. I asked about it in my review since their
purpose was unclear and I was genuinely wondering if I was overlooking
the reason for their presence. Future readers of the code may
experience the same puzzlement without necessarily having ready access
to the original author of the code from whom to receive an answer.)

[PATCH v5 0/8][Outreachy] rebase -i: add options to fixup command

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:06:48

This patch series adds fixup [-C|-c] options to interactive rebase. In
addition to amending the contents of the commit as the `fixup` command
does now, `fixup -C` replaces the commit message of the original commit
which we are fixing up with the message of the fixup commit.
And to edit the fixup commit message before committing, `fixup -c`
command is used instead of `fixup -C`. This convention is similar to
the existing `merge` command in the interactive rebase, that also supports
`-c` and `-C` options with similar meanings.

Also, `fixup -C` is intended to support amend! commit upon --autosquash
and it's working will be added in another patch series with the implementation
of amend! commit.

Changes from v4 :
(Thanks to Eric Sunshine, Christian Couder and Phillip Wood for suggestions
 and reviews)

The major change in this version is to remove the working of `fixup -C`
with amend! commit and will include in the another patch series, in order
to avoid the confusion. So there are following changes :
* removed the patch (rebase -i : teach --autosquash to work with amend!)
* updated the test script (t3437-*.sh), changed the test setup and removed
  two tests.

  Earlier every test includes the commit message having subject starting
  with amend! So, now it includes a setup of different branch for testing
  fixup with options and also updated all the tests.
  Removed the test - "skip fixup -C removes amend! from message" and also
  "sequence of fixup, fixup -C & squash --signoff works" as I think it would
  be better to test this also in the branch with amend! commit with different
  author. (Will add these tests with amend! commit implementation)

* changed the flag type from enum todo_item_flags to unsigned
* Removed amend! conditions from sequencer.c and
* Replaced fixup_-* with fixup-* in lib-rebase.sh
* fixup a small nit in Documentation

Charvi Mendiratta (5):
  sequencer: pass todo_item to do_pick_commit()
  sequencer: use const variable for commit message comments
  rebase -i: add fixup [-C | -c] command
  t3437: test script for fixup [-C|-c] options in interactive rebase
  doc/git-rebase: add documentation for fixup [-C|-c] options

Phillip Wood (3):
  rebase -i: only write fixup-message when it's needed
  sequencer: factor out code to append squash message
  rebase -i: comment out squash!/fixup! subjects from squash message

 Documentation/git-rebase.txt      |  13 +-
 rebase-interactive.c              |   4 +-
 sequencer.c                       | 270 ++++++++++++++++++++++++++----
 t/lib-rebase.sh                   |   8 +-
 t/t3415-rebase-autosquash.sh      |  30 ++--
 t/t3437-rebase-fixup-options.sh   | 133 +++++++++++++++
 t/t3437/expected-combined-message |  19 +++
 t/t3900-i18n-commit.sh            |   4 -
 8 files changed, 425 insertions(+), 56 deletions(-)
 create mode 100755 t/t3437-rebase-fixup-options.sh
 create mode 100644 t/t3437/expected-combined-message

--
2.29.0.rc1

[PATCH v5 1/8] rebase -i: only write fixup-message when it's needed

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:06:52

From: Phillip Wood <redacted>

The file "$GIT_DIR/rebase-merge/fixup-message" is only used for fixup
commands, there's no point in writing it for squash commands as it is
immediately deleted.

Signed-off-by: Phillip Wood <redacted>
Reviewed-by: Taylor Blau <redacted>
Signed-off-by: Charvi Mendiratta <redacted>
---
 sequencer.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index 8909a46770..a59e0c84af 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1757,11 +1757,10 @@ static int update_squash_messages(struct repository *r,
 			return error(_("could not read HEAD's commit message"));
 
 		find_commit_subject(head_message, &body);
-		if (write_message(body, strlen(body),
-				  rebase_path_fixup_msg(), 0)) {
+		if (command == TODO_FIXUP && write_message(body, strlen(body),
+							rebase_path_fixup_msg(), 0) < 0) {
 			unuse_commit_buffer(head_commit, head_message);
-			return error(_("cannot write '%s'"),
-				     rebase_path_fixup_msg());
+			return error(_("cannot write '%s'"), rebase_path_fixup_msg());
 		}
 
 		strbuf_addf(&buf, "%c ", comment_line_char);
-- 
2.29.0.rc1

[PATCH v5 3/8] rebase -i: comment out squash!/fixup! subjects from squash message

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:07:35

From: Phillip Wood <redacted>

When squashing commit messages the squash!/fixup! subjects are not of
interest so comment them out to stop them becoming part of the final
message.

This change breaks a bunch of --autosquash tests which rely on the
"squash! <subject>" line appearing in the final commit message. This is
addressed by adding a second line to the commit message of the "squash!
..." commits and testing for that.

Signed-off-by: Phillip Wood <redacted>
Reviewed-by: Taylor Blau <redacted>
Signed-off-by: Charvi Mendiratta <redacted>
---
 sequencer.c                  | 21 ++++++++++++++++++++-
 t/t3415-rebase-autosquash.sh | 30 ++++++++++++++++--------------
 t/t3900-i18n-commit.sh       |  4 ----
 3 files changed, 36 insertions(+), 19 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index 08cce40834..034149f24d 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1718,15 +1718,34 @@ static int is_pick_or_similar(enum todo_command command)
 	}
 }
 
+static size_t subject_length(const char *body)
+{
+	const char *p = body;
+	while (*p) {
+		const char *next = skip_blank_lines(p);
+		if (next != p)
+			break;
+		p = strchrnul(p, '\n');
+		if (*p)
+			p++;
+	}
+	return p - body;
+}
+
 static void append_squash_message(struct strbuf *buf, const char *body,
 				  struct replay_opts *opts)
 {
+	size_t commented_len = 0;
+
 	unlink(rebase_path_fixup_msg());
+	if (starts_with(body, "squash!") || starts_with(body, "fixup!"))
+		commented_len = subject_length(body);
 	strbuf_addf(buf, "\n%c ", comment_line_char);
 	strbuf_addf(buf, _("This is the commit message #%d:"),
 		    ++opts->current_fixup_count + 1);
 	strbuf_addstr(buf, "\n\n");
-	strbuf_addstr(buf, body);
+	strbuf_add_commented_lines(buf, body, commented_len);
+	strbuf_addstr(buf, body + commented_len);
 }
 
 static int update_squash_messages(struct repository *r,
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index e7087befd4..78cc2260cc 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -84,8 +84,7 @@ test_auto_squash () {
 	echo 1 >file1 &&
 	git add -u &&
 	test_tick &&
-	git commit -m "squash! first" &&
-
+	git commit -m "squash! first" -m "extra para for first" &&
 	git tag $1 &&
 	test_tick &&
 	git rebase $2 -i HEAD^^^ &&
@@ -142,7 +141,7 @@ test_expect_success 'auto squash that matches 2 commits' '
 	echo 1 >file1 &&
 	git add -u &&
 	test_tick &&
-	git commit -m "squash! first" &&
+	git commit -m "squash! first" -m "extra para for first" &&
 	git tag final-multisquash &&
 	test_tick &&
 	git rebase --autosquash -i HEAD~4 &&
@@ -195,7 +194,7 @@ test_expect_success 'auto squash that matches a sha1' '
 	git add -u &&
 	test_tick &&
 	oid=$(git rev-parse --short HEAD^) &&
-	git commit -m "squash! $oid" &&
+	git commit -m "squash! $oid" -m "extra para" &&
 	git tag final-shasquash &&
 	test_tick &&
 	git rebase --autosquash -i HEAD^^^ &&
@@ -206,7 +205,8 @@ test_expect_success 'auto squash that matches a sha1' '
 	git cat-file blob HEAD^:file1 >actual &&
 	test_cmp expect actual &&
 	git cat-file commit HEAD^ >commit &&
-	grep squash commit >actual &&
+	! grep "squash" commit &&
+	grep "^extra para" commit >actual &&
 	test_line_count = 1 actual
 '
 
@@ -216,7 +216,7 @@ test_expect_success 'auto squash that matches longer sha1' '
 	git add -u &&
 	test_tick &&
 	oid=$(git rev-parse --short=11 HEAD^) &&
-	git commit -m "squash! $oid" &&
+	git commit -m "squash! $oid" -m "extra para" &&
 	git tag final-longshasquash &&
 	test_tick &&
 	git rebase --autosquash -i HEAD^^^ &&
@@ -227,7 +227,8 @@ test_expect_success 'auto squash that matches longer sha1' '
 	git cat-file blob HEAD^:file1 >actual &&
 	test_cmp expect actual &&
 	git cat-file commit HEAD^ >commit &&
-	grep squash commit >actual &&
+	! grep "squash" commit &&
+	grep "^extra para" commit >actual &&
 	test_line_count = 1 actual
 '
 
@@ -236,7 +237,7 @@ test_auto_commit_flags () {
 	echo 1 >file1 &&
 	git add -u &&
 	test_tick &&
-	git commit --$1 first-commit &&
+	git commit --$1 first-commit -m "extra para for first" &&
 	git tag final-commit-$1 &&
 	test_tick &&
 	git rebase --autosquash -i HEAD^^^ &&
@@ -264,11 +265,11 @@ test_auto_fixup_fixup () {
 	echo 1 >file1 &&
 	git add -u &&
 	test_tick &&
-	git commit -m "$1! first" &&
+	git commit -m "$1! first" -m "extra para for first" &&
 	echo 2 >file1 &&
 	git add -u &&
 	test_tick &&
-	git commit -m "$1! $2! first" &&
+	git commit -m "$1! $2! first" -m "second extra para for first" &&
 	git tag "final-$1-$2" &&
 	test_tick &&
 	(
@@ -329,12 +330,12 @@ test_expect_success C_LOCALE_OUTPUT 'autosquash with custom inst format' '
 	git add -u &&
 	test_tick &&
 	oid=$(git rev-parse --short HEAD^) &&
-	git commit -m "squash! $oid" &&
+	git commit -m "squash! $oid" -m "extra para for first" &&
 	echo 1 >file1 &&
 	git add -u &&
 	test_tick &&
 	subject=$(git log -n 1 --format=%s HEAD~2) &&
-	git commit -m "squash! $subject" &&
+	git commit -m "squash! $subject" -m "second extra para for first" &&
 	git tag final-squash-instFmt &&
 	test_tick &&
 	git rebase --autosquash -i HEAD~4 &&
@@ -345,8 +346,9 @@ test_expect_success C_LOCALE_OUTPUT 'autosquash with custom inst format' '
 	git cat-file blob HEAD^:file1 >actual &&
 	test_cmp expect actual &&
 	git cat-file commit HEAD^ >commit &&
-	grep squash commit >actual &&
-	test_line_count = 2 actual
+	! grep "squash" commit &&
+	grep first commit >actual &&
+	test_line_count = 3 actual
 '
 
 test_expect_success 'autosquash with empty custom instructionFormat' '
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index d277a9f4b7..bfab245eb3 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -226,10 +226,6 @@ test_commit_autosquash_multi_encoding () {
 		git rev-list HEAD >actual &&
 		test_line_count = 3 actual &&
 		iconv -f $old -t UTF-8 "$TEST_DIRECTORY"/t3900/$msg >expect &&
-		if test $flag = squash; then
-			subject="$(head -1 expect)" &&
-			printf "\nsquash! %s\n" "$subject" >>expect
-		fi &&
 		git cat-file commit HEAD^ >raw &&
 		(sed "1,/^$/d" raw | iconv -f $new -t utf-8) >actual &&
 		test_cmp expect actual
-- 
2.29.0.rc1

[PATCH v5 7/8] t3437: test script for fixup [-C|-c] options in interactive rebase

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:08:06

Original-patch-by: Phillip Wood [off-list ref]
Mentored-by: Christian Couder [off-list ref]
Mentored-by: Phillip Wood [off-list ref]
Reviewed-by: Eric Sunshine <redacted>
Signed-off-by: Charvi Mendiratta <redacted>
---
 t/lib-rebase.sh                   |   8 +-
 t/t3437-rebase-fixup-options.sh   | 133 ++++++++++++++++++++++++++++++
 t/t3437/expected-combined-message |  19 +++++
 3 files changed, 158 insertions(+), 2 deletions(-)
 create mode 100755 t/t3437-rebase-fixup-options.sh
 create mode 100644 t/t3437/expected-combined-message
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index b72c051f47..d9afed7b47 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -4,6 +4,7 @@
 #
 # - override the commit message with $FAKE_COMMIT_MESSAGE
 # - amend the commit message with $FAKE_COMMIT_AMEND
+# - copy the original commit message to a file with $FAKE_MESSAGE_COPY
 # - check that non-commit messages have a certain line count with $EXPECT_COUNT
 # - check the commit count in the commit message header with $EXPECT_HEADER_COUNT
 # - rewrite a rebase -i script as directed by $FAKE_LINES.
@@ -14,8 +15,8 @@
 #       specified line.
 #
 #   "<cmd> <lineno>" -- add a line with the specified command
-#       ("pick", "squash", "fixup", "edit", "reword" or "drop") and the
-#       SHA1 taken from the specified line.
+#       ("pick", "squash", "fixup"|"fixup-C"|"fixup-c", "edit", "reword" or "drop")
+#       and the SHA1 taken from the specified line.
 #
 #   "exec_cmd_with_args" -- add an "exec cmd with args" line.
 #
@@ -33,6 +34,7 @@ set_fake_editor () {
 			exit
 		test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
 		test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
+		test -z "$FAKE_MESSAGE_COPY" || cat "$1" >"$FAKE_MESSAGE_COPY"
 		exit
 		;;
 	esac
@@ -51,6 +53,8 @@ set_fake_editor () {
 			action="$line";;
 		exec_*|x_*|break|b)
 			echo "$line" | sed 's/_/ /g' >> "$1";;
+		fixup-*)
+			action=$(echo "$line" | sed 's/-/ -/');;
 		"#")
 			echo '# comment' >> "$1";;
 		">")
diff --git a/t/t3437-rebase-fixup-options.sh b/t/t3437-rebase-fixup-options.sh
new file mode 100755
index 0000000000..c2875803af
--- /dev/null
+++ b/t/t3437-rebase-fixup-options.sh
@@ -0,0 +1,133 @@
+#!/bin/sh
+#
+# Copyright (c) 2018 Phillip Wood
+#
+
+test_description='git rebase interactive fixup options
+
+This test checks the "fixup [-C|-c]" command of rebase interactive.
+In addition to amending the contents of the commit, "fixup -C"
+replaces the original commit message with the message of the fixup
+commit. "fixup -c" also replaces the original message, but opens the
+editor to allow the user to edit the message before committing.
+'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+EMPTY=""
+
+# test_commit_message <rev> -m <msg>
+# test_commit_message <rev> <path>
+# Verify that the commit message of <rev> matches
+# <msg> or the content of <path>.
+test_commit_message () {
+	git show --no-patch --pretty=format:%B "$1" >actual &&
+	case "$2" in
+	-m) echo "$3" >expect &&
+	    test_cmp expect actual ;;
+	*) test_cmp "$2" actual ;;
+	esac
+}
+
+test_expect_success 'setup' '
+	cat >message <<-EOF &&
+	new subject
+	$EMPTY
+	new
+	body
+	EOF
+	test_commit A A &&
+	test_commit B B &&
+
+	set_fake_editor &&
+	git checkout -b test-branch &&
+	test_commit "$(cat message)" A A1 A1 &&
+	test_commit A2 A &&
+	test_commit A3 A &&
+	git checkout -b conflicts-branch A &&
+	test_commit conflicts A
+'
+
+test_expect_success 'simple fixup -C works' '
+	test_when_finished "test_might_fail git rebase --abort" &&
+	git checkout --detach A1 &&
+	git log -1 --pretty=format:%B >expected-message &&
+	FAKE_LINES="1 fixup-C 2 " git rebase -i A &&
+	test_cmp_rev HEAD^ A &&
+	test_cmp_rev HEAD^{tree} A1^{tree} &&
+	test_commit_message HEAD expected-message
+'
+
+test_expect_success 'simple fixup -c works' '
+	test_when_finished "test_might_fail git rebase --abort" &&
+	git checkout --detach A2 &&
+	git log -1 --pretty=format:%B HEAD~ >expected-message &&
+	test_write_lines "" "Modified A1" >>expected-message &&
+	FAKE_LINES="1 fixup-c 2 3" \
+		FAKE_COMMIT_AMEND="Modified A1" \
+		git rebase -i A &&
+	test_cmp_rev HEAD^{tree} A2^{tree} &&
+	test_commit_message HEAD~ expected-message
+'
+
+test_expect_success 'fixup -C with conflicts gives correct message' '
+	test_when_finished "test_might_fail git rebase --abort" &&
+	git checkout --detach A1 &&
+	git log -1 --pretty=format:%B HEAD >expected-message &&
+	test_write_lines "" "edited" >>expected-message &&
+	test_must_fail env FAKE_LINES="1 fixup-C 2" git rebase -i conflicts &&
+	git checkout --theirs -- A &&
+	git add A &&
+	FAKE_COMMIT_AMEND=edited git rebase --continue &&
+	test_cmp_rev HEAD^ conflicts &&
+	test_cmp_rev HEAD^{tree} A1^{tree} &&
+	test_commit_message HEAD expected-message
+'
+
+test_expect_success 'skipping fixup -C after fixup gives correct message' '
+	test_when_finished "test_might_fail git rebase --abort" &&
+	git checkout --detach A3 &&
+	test_must_fail env FAKE_LINES="1 fixup 2 fixup-C 4" git rebase -i A &&
+	git reset --hard &&
+	FAKE_COMMIT_AMEND=edited git rebase --continue &&
+	test_commit_message HEAD -m "B"
+'
+
+test_expect_success 'first fixup -C commented out in sequence fixup fixup -C fixup -C' '
+	test_when_finished "test_might_fail git rebase --abort" &&
+	git checkout --detach A3 &&
+	git log -1 --pretty=format:%B >expected-message &&
+	FAKE_LINES="1 fixup 2 fixup-C 3 fixup-C 4" git rebase -i A &&
+	test_cmp_rev HEAD^ A &&
+	test_commit_message HEAD expected-message
+'
+
+test_expect_success 'multiple fixup -c opens editor once' '
+	test_when_finished "test_might_fail git rebase --abort" &&
+	git checkout --detach A3 &&
+	base=$(git rev-parse HEAD~4) &&
+	FAKE_COMMIT_MESSAGE="Modified-A3" \
+		FAKE_LINES="1 fixup-C 2 fixup-c 3 fixup-c 4" \
+		EXPECT_HEADER_COUNT=4 \
+		git rebase -i $base &&
+	test_commit_message HEAD -m "Modified-A3" &&
+	test_cmp_rev $base HEAD^ &&
+	git show > raw &&
+	grep Modified-A3 raw >out &&
+	test_line_count = 1 out
+'
+
+test_expect_success 'sequence squash, fixup & fixup -c gives combined message' '
+	test_when_finished "test_might_fail git rebase --abort" &&
+	git checkout --detach A3 &&
+	FAKE_LINES="1 squash 2 fixup 3 fixup-c 4" \
+		FAKE_MESSAGE_COPY=actual-combined-message \
+		git -c commit.status=false rebase -i A &&
+	test_i18ncmp "$TEST_DIRECTORY/t3437/expected-combined-message" \
+		actual-combined-message &&
+	test_cmp_rev HEAD^ A
+'
+
+test_done
diff --git a/t/t3437/expected-combined-message b/t/t3437/expected-combined-message
new file mode 100644
index 0000000000..d21bd1b6bb
--- /dev/null
+++ b/t/t3437/expected-combined-message
@@ -0,0 +1,19 @@
+# This is a combination of 4 commits.
+# This is the 1st commit message:
+
+B
+
+# This is the commit message #2:
+
+new subject
+
+new
+body
+
+# The commit message #3 will be skipped:
+
+# A2
+
+# This is the commit message #4:
+
+A3
-- 
2.29.0.rc1

[PATCH v5 6/8] rebase -i: add fixup [-C | -c] command

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:08:06

Add options to `fixup` command to fixup both the commit contents and
message. `fixup -C` command is used to replace the original commit
message and `fixup -c`, additionally allows to edit the commit message.

This convention is similar to the existing `merge` command in the
interactive rebase, that also supports `-c` and `-C` options with
similar meanings.

Original-patch-by: Phillip Wood [off-list ref]
Mentored-by: Christian Couder [off-list ref]
Mentored-by: Phillip Wood [off-list ref]
Reviewed-by: Eric Sunshine <redacted>
Signed-off-by: Charvi Mendiratta <redacted>
---
 rebase-interactive.c |   4 +-
 sequencer.c          | 211 +++++++++++++++++++++++++++++++++++++++----
 2 files changed, 195 insertions(+), 20 deletions(-)
diff --git a/rebase-interactive.c b/rebase-interactive.c
index 762853bc7e..13e7a6c475 100644
--- a/rebase-interactive.c
+++ b/rebase-interactive.c
@@ -44,7 +44,9 @@ void append_todo_help(int command_count,
 "r, reword <commit> = use commit, but edit the commit message\n"
 "e, edit <commit> = use commit, but stop for amending\n"
 "s, squash <commit> = use commit, but meld into previous commit\n"
-"f, fixup <commit> = like \"squash\", but discard this commit's log message\n"
+"f, fixup [-C | -c] <commit> = like \"squash\", but discard this\n"
+"                   commit's log message; use -C to replace with this\n"
+"                   commit message or -c to edit this commit message\n"
 "x, exec <command> = run command (the rest of the line) using shell\n"
 "b, break = stop here (continue rebase later with 'git rebase --continue')\n"
 "d, drop <commit> = remove commit\n"
diff --git a/sequencer.c b/sequencer.c
index 6d9a10afcf..324fc5698a 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1718,6 +1718,12 @@ static int is_pick_or_similar(enum todo_command command)
 	}
 }
 
+enum todo_item_flags {
+	TODO_EDIT_MERGE_MSG    = (1 << 0),
+	TODO_REPLACE_FIXUP_MSG = (1 << 1),
+	TODO_EDIT_FIXUP_MSG    = (1 << 2),
+};
+
 static size_t subject_length(const char *body)
 {
 	const char *p = body;
@@ -1734,32 +1740,174 @@ static size_t subject_length(const char *body)
 
 static const char first_commit_msg_str[] = N_("This is the 1st commit message:");
 static const char nth_commit_msg_fmt[] = N_("This is the commit message #%d:");
+static const char skip_first_commit_msg_str[] = N_("The 1st commit message will be skipped:");
 static const char skip_nth_commit_msg_fmt[] = N_("The commit message #%d will be skipped:");
 static const char combined_commit_msg_fmt[] = N_("This is a combination of %d commits.");
 
-static void append_squash_message(struct strbuf *buf, const char *body,
-				  struct replay_opts *opts)
+static int is_fixup_flag(enum todo_command command, unsigned flag)
+{
+	return command == TODO_FIXUP && ((flag & TODO_REPLACE_FIXUP_MSG) ||
+					 (flag & TODO_EDIT_FIXUP_MSG));
+}
+
+/*
+ * Wrapper around strbuf_add_commented_lines() which avoids double
+ * commenting commit subjects.
+ */
+static void add_commented_lines(struct strbuf *buf, const void *str, size_t len)
+{
+	const char *s = str;
+	while (len > 0 && s[0] == comment_line_char) {
+		size_t count;
+		const char *n = memchr(s, '\n', len);
+		if (!n)
+			count = len;
+		else
+			count = n - s + 1;
+		strbuf_add(buf, s, count);
+		s += count;
+		len -= count;
+	}
+	strbuf_add_commented_lines(buf, s, len);
+}
+
+/* Does the current fixup chain contain a squash command? */
+static int seen_squash(struct replay_opts *opts)
+{
+	return starts_with(opts->current_fixups.buf, "squash") ||
+		strstr(opts->current_fixups.buf, "\nsquash");
+}
+
+static void update_comment_bufs(struct strbuf *buf1, struct strbuf *buf2, int n)
 {
-	size_t commented_len = 0;
+	strbuf_setlen(buf1, 2);
+	strbuf_addf(buf1, _(nth_commit_msg_fmt), n);
+	strbuf_addch(buf1, '\n');
+	strbuf_setlen(buf2, 2);
+	strbuf_addf(buf2, _(skip_nth_commit_msg_fmt), n);
+	strbuf_addch(buf2, '\n');
+}
 
-	unlink(rebase_path_fixup_msg());
-	if (starts_with(body, "squash!") || starts_with(body, "fixup!"))
+/*
+ * Comment out any un-commented commit messages, updating the message comments
+ * to say they will be skipped but do not comment out the empty lines that
+ * surround commit messages and their comments.
+ */
+static void update_squash_message_for_fixup(struct strbuf *msg)
+{
+	void (*copy_lines)(struct strbuf *, const void *, size_t) = strbuf_add;
+	struct strbuf buf1 = STRBUF_INIT, buf2 = STRBUF_INIT;
+	const char *s, *start;
+	char *orig_msg;
+	size_t orig_msg_len;
+	int i = 1;
+
+	strbuf_addf(&buf1, "# %s\n", _(first_commit_msg_str));
+	strbuf_addf(&buf2, "# %s\n", _(skip_first_commit_msg_str));
+	s = start = orig_msg = strbuf_detach(msg, &orig_msg_len);
+	while (s) {
+		const char *next;
+		size_t off;
+		if (skip_prefix(s, buf1.buf, &next)) {
+			/*
+			 * Copy the last message, preserving the blank line
+			 * preceding the current line
+			 */
+			off = (s > start + 1 && s[-2] == '\n') ? 1 : 0;
+			copy_lines(msg, start, s - start - off);
+			if (off)
+				strbuf_addch(msg, '\n');
+			/*
+			 * The next message needs to be commented out but the
+			 * message header is already commented out so just copy
+			 * it and the blank line that follows it.
+			 */
+			strbuf_addbuf(msg, &buf2);
+			if (*next == '\n')
+				strbuf_addch(msg, *next++);
+			start = s = next;
+			copy_lines = add_commented_lines;
+			update_comment_bufs(&buf1, &buf2, ++i);
+		} else if (skip_prefix(s, buf2.buf, &next)) {
+			off = (s > start + 1 && s[-2] == '\n') ? 1 : 0;
+			copy_lines(msg, start, s - start - off);
+			start = s - off;
+			s = next;
+			copy_lines = strbuf_add;
+			update_comment_bufs(&buf1, &buf2, ++i);
+		} else {
+			s = strchr(s, '\n');
+			if (s)
+				s++;
+		}
+	}
+	copy_lines(msg, start, orig_msg_len - (start - orig_msg));
+	free(orig_msg);
+	strbuf_release(&buf1);
+	strbuf_release(&buf2);
+}
+
+static int append_squash_message(struct strbuf *buf, const char *body,
+			 enum todo_command command, struct replay_opts *opts,
+			 unsigned flag)
+{
+	const char *fixup_msg;
+	size_t commented_len = 0, fixup_off;
+	/*
+	 * fixup -C is non-interactive and not normally used with fixup!
+	 * or squash! commits, so only comment out those subjects when
+	 * squashing commit messages.
+	 */
+	if ((command == TODO_SQUASH || seen_squash(opts)) &&
+	    (starts_with(body, "squash!") || starts_with(body, "fixup!")))
 		commented_len = subject_length(body);
+
 	strbuf_addf(buf, "\n%c ", comment_line_char);
 	strbuf_addf(buf, _(nth_commit_msg_fmt),
 		    ++opts->current_fixup_count + 1);
 	strbuf_addstr(buf, "\n\n");
 	strbuf_add_commented_lines(buf, body, commented_len);
+	/* buf->buf may be reallocated so store an offset into the buffer */
+	fixup_off = buf->len;
 	strbuf_addstr(buf, body + commented_len);
+
+	/* fixup -C after squash behaves like squash */
+	if (is_fixup_flag(command, flag) && !seen_squash(opts)) {
+		/*
+		 * We're replacing the commit message so we need to
+		 * append the Signed-off-by: trailer if the user
+		 * requested '--signoff'.
+		 */
+		if (opts->signoff)
+			append_signoff(buf, 0, 0);
+
+		if ((command == TODO_FIXUP) &&
+		    (flag & TODO_REPLACE_FIXUP_MSG) &&
+		    (file_exists(rebase_path_fixup_msg()) ||
+		     !file_exists(rebase_path_squash_msg()))) {
+			fixup_msg = skip_blank_lines(buf->buf + fixup_off);
+			if (write_message(fixup_msg, strlen(fixup_msg),
+					rebase_path_fixup_msg(), 0) < 0)
+				return error(_("cannot write '%s'"),
+					rebase_path_fixup_msg());
+		} else {
+			unlink(rebase_path_fixup_msg());
+		}
+	} else  {
+		unlink(rebase_path_fixup_msg());
+	}
+
+	return 0;
 }
 
 static int update_squash_messages(struct repository *r,
 				  enum todo_command command,
 				  struct commit *commit,
-				  struct replay_opts *opts)
+				  struct replay_opts *opts,
+				  unsigned flag)
 {
 	struct strbuf buf = STRBUF_INIT;
-	int res;
+	int res = 0;
 	const char *message, *body;
 	const char *encoding = get_commit_output_encoding();
 
@@ -1779,6 +1927,8 @@ static int update_squash_messages(struct repository *r,
 			    opts->current_fixup_count + 2);
 		strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
 		strbuf_release(&header);
+		if (is_fixup_flag(command, flag) && !seen_squash(opts))
+			update_squash_message_for_fixup(&buf);
 	} else {
 		struct object_id head;
 		struct commit *head_commit;
@@ -1792,18 +1942,22 @@ static int update_squash_messages(struct repository *r,
 			return error(_("could not read HEAD's commit message"));
 
 		find_commit_subject(head_message, &body);
-		if (command == TODO_FIXUP && write_message(body, strlen(body),
+		if (command == TODO_FIXUP && !flag && write_message(body, strlen(body),
 							rebase_path_fixup_msg(), 0) < 0) {
 			unuse_commit_buffer(head_commit, head_message);
 			return error(_("cannot write '%s'"), rebase_path_fixup_msg());
 		}
-
 		strbuf_addf(&buf, "%c ", comment_line_char);
 		strbuf_addf(&buf, _(combined_commit_msg_fmt), 2);
 		strbuf_addf(&buf, "\n%c ", comment_line_char);
-		strbuf_addstr(&buf, _(first_commit_msg_str));
+		strbuf_addstr(&buf, is_fixup_flag(command, flag) ?
+			      _(skip_first_commit_msg_str) :
+			      _(first_commit_msg_str));
 		strbuf_addstr(&buf, "\n\n");
-		strbuf_addstr(&buf, body);
+		if (is_fixup_flag(command, flag))
+			strbuf_add_commented_lines(&buf, body, strlen(body));
+		else
+			strbuf_addstr(&buf, body);
 
 		unuse_commit_buffer(head_commit, head_message);
 	}
@@ -1813,8 +1967,8 @@ static int update_squash_messages(struct repository *r,
 			     oid_to_hex(&commit->object.oid));
 	find_commit_subject(message, &body);
 
-	if (command == TODO_SQUASH) {
-		append_squash_message(&buf, body, opts);
+	if (command == TODO_SQUASH || is_fixup_flag(command, flag)) {
+		res = append_squash_message(&buf, body, command, opts, flag);
 	} else if (command == TODO_FIXUP) {
 		strbuf_addf(&buf, "\n%c ", comment_line_char);
 		strbuf_addf(&buf, _(skip_nth_commit_msg_fmt),
@@ -1825,7 +1979,9 @@ static int update_squash_messages(struct repository *r,
 		return error(_("unknown command: %d"), command);
 	unuse_commit_buffer(commit, message);
 
-	res = write_message(buf.buf, buf.len, rebase_path_squash_msg(), 0);
+	if (!res)
+		res = write_message(buf.buf, buf.len, rebase_path_squash_msg(),
+				    0);
 	strbuf_release(&buf);
 
 	if (!res) {
@@ -2026,7 +2182,8 @@ static int do_pick_commit(struct repository *r,
 	if (command == TODO_REWORD)
 		reword = 1;
 	else if (is_fixup(command)) {
-		if (update_squash_messages(r, command, commit, opts))
+		if (update_squash_messages(r, command, commit,
+					   opts, item->flags))
 			return -1;
 		flags |= AMEND_MSG;
 		if (!final_fixup)
@@ -2191,10 +2348,6 @@ static int read_and_refresh_cache(struct repository *r,
 	return 0;
 }
 
-enum todo_item_flags {
-	TODO_EDIT_MERGE_MSG = 1
-};
-
 void todo_list_release(struct todo_list *todo_list)
 {
 	strbuf_release(&todo_list->buf);
@@ -2281,6 +2434,18 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
 		return 0;
 	}
 
+	if (item->command == TODO_FIXUP) {
+		if (skip_prefix(bol, "-C", &bol) &&
+		   (*bol == ' ' || *bol == '\t')) {
+			bol += strspn(bol, " \t");
+			item->flags |= TODO_REPLACE_FIXUP_MSG;
+		} else if (skip_prefix(bol, "-c", &bol) &&
+				  (*bol == ' ' || *bol == '\t')) {
+			bol += strspn(bol, " \t");
+			item->flags |= TODO_EDIT_FIXUP_MSG;
+		}
+	}
+
 	if (item->command == TODO_MERGE) {
 		if (skip_prefix(bol, "-C", &bol))
 			bol += strspn(bol, " \t");
@@ -5287,6 +5452,14 @@ static void todo_list_to_strbuf(struct repository *r, struct todo_list *todo_lis
 					  short_commit_name(item->commit) :
 					  oid_to_hex(&item->commit->object.oid);
 
+			if (item->command == TODO_FIXUP) {
+				if (item->flags & TODO_EDIT_FIXUP_MSG)
+					strbuf_addstr(buf, " -c");
+				else if (item->flags & TODO_REPLACE_FIXUP_MSG) {
+					strbuf_addstr(buf, " -C");
+				}
+			}
+
 			if (item->command == TODO_MERGE) {
 				if (item->flags & TODO_EDIT_MERGE_MSG)
 					strbuf_addstr(buf, " -c");
-- 
2.29.0.rc1

[PATCH v5 2/8] sequencer: factor out code to append squash message

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:08:06

From: Phillip Wood <redacted>

This code is going to grow over the next two commits so move it to
its own function.

Signed-off-by: Phillip Wood <redacted>
Signed-off-by: Charvi Mendiratta <redacted>
---
 sequencer.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index a59e0c84af..08cce40834 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1718,6 +1718,17 @@ static int is_pick_or_similar(enum todo_command command)
 	}
 }
 
+static void append_squash_message(struct strbuf *buf, const char *body,
+				  struct replay_opts *opts)
+{
+	unlink(rebase_path_fixup_msg());
+	strbuf_addf(buf, "\n%c ", comment_line_char);
+	strbuf_addf(buf, _("This is the commit message #%d:"),
+		    ++opts->current_fixup_count + 1);
+	strbuf_addstr(buf, "\n\n");
+	strbuf_addstr(buf, body);
+}
+
 static int update_squash_messages(struct repository *r,
 				  enum todo_command command,
 				  struct commit *commit,
@@ -1779,12 +1790,7 @@ static int update_squash_messages(struct repository *r,
 	find_commit_subject(message, &body);
 
 	if (command == TODO_SQUASH) {
-		unlink(rebase_path_fixup_msg());
-		strbuf_addf(&buf, "\n%c ", comment_line_char);
-		strbuf_addf(&buf, _("This is the commit message #%d:"),
-			    ++opts->current_fixup_count + 1);
-		strbuf_addstr(&buf, "\n\n");
-		strbuf_addstr(&buf, body);
+		append_squash_message(&buf, body, opts);
 	} else if (command == TODO_FIXUP) {
 		strbuf_addf(&buf, "\n%c ", comment_line_char);
 		strbuf_addf(&buf, _("The commit message #%d will be skipped:"),
-- 
2.29.0.rc1

[PATCH v5 5/8] sequencer: use const variable for commit message comments

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:09:00

This makes it easier to use and reuse the comments.

Mentored-by: Christian Couder [off-list ref]
Mentored-by: Phillip Wood [off-list ref]
Reviewed-by: Taylor Blau <redacted>
Signed-off-by: Charvi Mendiratta <redacted>
---
 sequencer.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index 09cbb17f87..6d9a10afcf 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1732,6 +1732,11 @@ static size_t subject_length(const char *body)
 	return p - body;
 }
 
+static const char first_commit_msg_str[] = N_("This is the 1st commit message:");
+static const char nth_commit_msg_fmt[] = N_("This is the commit message #%d:");
+static const char skip_nth_commit_msg_fmt[] = N_("The commit message #%d will be skipped:");
+static const char combined_commit_msg_fmt[] = N_("This is a combination of %d commits.");
+
 static void append_squash_message(struct strbuf *buf, const char *body,
 				  struct replay_opts *opts)
 {
@@ -1741,7 +1746,7 @@ static void append_squash_message(struct strbuf *buf, const char *body,
 	if (starts_with(body, "squash!") || starts_with(body, "fixup!"))
 		commented_len = subject_length(body);
 	strbuf_addf(buf, "\n%c ", comment_line_char);
-	strbuf_addf(buf, _("This is the commit message #%d:"),
+	strbuf_addf(buf, _(nth_commit_msg_fmt),
 		    ++opts->current_fixup_count + 1);
 	strbuf_addstr(buf, "\n\n");
 	strbuf_add_commented_lines(buf, body, commented_len);
@@ -1770,7 +1775,7 @@ static int update_squash_messages(struct repository *r,
 			buf.buf : strchrnul(buf.buf, '\n');
 
 		strbuf_addf(&header, "%c ", comment_line_char);
-		strbuf_addf(&header, _("This is a combination of %d commits."),
+		strbuf_addf(&header, _(combined_commit_msg_fmt),
 			    opts->current_fixup_count + 2);
 		strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
 		strbuf_release(&header);
@@ -1794,9 +1799,9 @@ static int update_squash_messages(struct repository *r,
 		}
 
 		strbuf_addf(&buf, "%c ", comment_line_char);
-		strbuf_addf(&buf, _("This is a combination of %d commits."), 2);
+		strbuf_addf(&buf, _(combined_commit_msg_fmt), 2);
 		strbuf_addf(&buf, "\n%c ", comment_line_char);
-		strbuf_addstr(&buf, _("This is the 1st commit message:"));
+		strbuf_addstr(&buf, _(first_commit_msg_str));
 		strbuf_addstr(&buf, "\n\n");
 		strbuf_addstr(&buf, body);
 
@@ -1812,7 +1817,7 @@ static int update_squash_messages(struct repository *r,
 		append_squash_message(&buf, body, opts);
 	} else if (command == TODO_FIXUP) {
 		strbuf_addf(&buf, "\n%c ", comment_line_char);
-		strbuf_addf(&buf, _("The commit message #%d will be skipped:"),
+		strbuf_addf(&buf, _(skip_nth_commit_msg_fmt),
 			    ++opts->current_fixup_count + 1);
 		strbuf_addstr(&buf, "\n\n");
 		strbuf_add_commented_lines(&buf, body, strlen(body));
-- 
2.29.0.rc1

[PATCH v5 8/8] doc/git-rebase: add documentation for fixup [-C|-c] options

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:09:00

Mentored-by: Christian Couder [off-list ref]
Mentored-by: Phillip Wood [off-list ref]
Reviewed-by: Marc Branchaud <redacted>
Reviewed-by: Eric Sunshine <redacted>
Signed-off-by: Charvi Mendiratta <redacted>
---
 Documentation/git-rebase.txt | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index a0487b5cc5..97a8d2e1aa 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -887,9 +887,16 @@ If you want to fold two or more commits into one, replace the command
 "pick" for the second and subsequent commits with "squash" or "fixup".
 If the commits had different authors, the folded commit will be
 attributed to the author of the first commit.  The suggested commit
-message for the folded commit is the concatenation of the commit
-messages of the first commit and of those with the "squash" command,
-but omits the commit messages of commits with the "fixup" command.
+message for the folded commit is the concatenation of the first
+commit's message with those identified by "squash" commands, omitting the
+messages of commits identified by "fixup" commands, unless "fixup -c"
+is used.  In that case the suggested commit message is only the message
+of the "fixup -c" commit, and an editor is opened allowing you to edit
+the message.  The contents (patch) of the "fixup -c" commit are still
+incorporated into the folded commit. If there is more than one "fixup -c"
+commit, the message from the final one is used.  You can also use
+"fixup -C" to get the same behavior as "fixup -c" except without opening
+an editor.
 
 'git rebase' will stop when "pick" has been replaced with "edit" or
 when a command fails due to merge errors. When you are done editing
-- 
2.29.0.rc1

[PATCH v5 4/8] sequencer: pass todo_item to do_pick_commit()

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:09:00

As an additional member of the structure todo_item will be required in
future commits pass the complete structure.

Mentored-by: Christian Couder [off-list ref]
Mentored-by: Phillip Wood [off-list ref]
Signed-off-by: Charvi Mendiratta <redacted>
---
 sequencer.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/sequencer.c b/sequencer.c
index 034149f24d..09cbb17f87 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1877,8 +1877,7 @@ static void record_in_rewritten(struct object_id *oid,
 }
 
 static int do_pick_commit(struct repository *r,
-			  enum todo_command command,
-			  struct commit *commit,
+			  struct todo_item *item,
 			  struct replay_opts *opts,
 			  int final_fixup, int *check_todo)
 {
@@ -1891,6 +1890,8 @@ static int do_pick_commit(struct repository *r,
 	struct commit_message msg = { NULL, NULL, NULL, NULL };
 	struct strbuf msgbuf = STRBUF_INIT;
 	int res, unborn = 0, reword = 0, allow, drop_commit;
+	enum todo_command command = item->command;
+	struct commit *commit = item->commit;
 
 	if (opts->no_commit) {
 		/*
@@ -4140,8 +4141,8 @@ static int pick_commits(struct repository *r,
 				setenv(GIT_REFLOG_ACTION, reflog_message(opts,
 					command_to_string(item->command), NULL),
 					1);
-			res = do_pick_commit(r, item->command, item->commit,
-					     opts, is_final_fixup(todo_list),
+			res = do_pick_commit(r, item, opts,
+					     is_final_fixup(todo_list),
 					     &check_todo);
 			if (is_rebase_i(opts))
 				setenv(GIT_REFLOG_ACTION, prev_reflog_action, 1);
@@ -4603,11 +4604,14 @@ static int single_pick(struct repository *r,
 		       struct replay_opts *opts)
 {
 	int check_todo;
+	struct todo_item item;
+
+	item.command = opts->action == REPLAY_PICK ?
+			TODO_PICK : TODO_REVERT;
+	item.commit = cmit;
 
 	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
-	return do_pick_commit(r, opts->action == REPLAY_PICK ?
-			      TODO_PICK : TODO_REVERT, cmit, opts, 0,
-			      &check_todo);
+	return do_pick_commit(r, &item, opts, 0, &check_todo);
 }
 
 int sequencer_pick_revisions(struct repository *r,
-- 
2.29.0.rc1

Re: [PATCH v4 7/9] t3437: test script for fixup [-C|-c] options in interactive rebase

From: Charvi Mendiratta <hidden>
Date: 2021-02-04 19:14:03

Hi Eric,
quoted
+test_expect_success 'fixup -C with conflicts gives correct message' '
+       test_when_finished "test_might_fail git rebase --abort" &&
Is there a reason this isn't written as:

    test_when_finished "reset_rebase" &&

which is more common? Is there something non-obvious which makes
reset_rebase() inappropriate in these tests?
I missed this earlier, but I confirmed before sending next version that as
reset_rebase() removes the untracked files so we could not use this as otherwise
it removes the fake-editor.sh file and will be required to set a fake
editor for every
test and also removes other untracked files which may be used to debug.
So, I think it's okay with:
test_when_finished "test_might_fail git rebase --abort"

Thanks and regards,
Charvi

Re: [PATCH v5 0/8][Outreachy] rebase -i: add options to fixup command

From: Eric Sunshine <hidden>
Date: 2021-02-05 07:31:32

On Thu, Feb 4, 2021 at 2:05 PM Charvi Mendiratta [off-list ref] wrote:
Changes from v4 :
(Thanks to Eric Sunshine, Christian Couder and Phillip Wood for suggestions
 and reviews)
Thanks for working on this and re-rolling. Unfortunately, it seems
that v4 already landed in Junio's `next` branch which means that he
won't be replacing v4 wholesale as would have been the case if it was
still in the `seen` branch. Once patches are in `next`, improvements
are made by building changes atop them (incrementally) rather than
replacing them. Whether or not it makes sense for you to spend time
re-doing these patches as incremental changes is not clear. In fact...
The major change in this version is to remove the working of `fixup -C`
with amend! commit and will include in the another patch series, in order
to avoid the confusion. So there are following changes :
* removed the patch (rebase -i : teach --autosquash to work with amend!)
* updated the test script (t3437-*.sh), changed the test setup and removed
  two tests.

  Earlier every test includes the commit message having subject starting
  with amend! So, now it includes a setup of different branch for testing
  fixup with options and also updated all the tests.
  Removed the test - "skip fixup -C removes amend! from message" and also
  "sequence of fixup, fixup -C & squash --signoff works" as I think it would
  be better to test this also in the branch with amend! commit with different
  author. (Will add these tests with amend! commit implementation)
Despite these being nice cleanups to the standalone series, I'm not
sure it's worth spending your time creating new patches to undo these
from `next`. Removing them only to add them back later is not
necessarily going to help "unconfuse" someone reading the commits in
the permanent project history.
* changed the flag type from enum todo_item_flags to unsigned
* Replaced fixup_-* with fixup-* in lib-rebase.sh
* fixup a small nit in Documentation
These changes are still worthwhile and can easily be done
incrementally atop what is already in next, I would think.

Anyhow, use your best judgment to decide how much work to devote to this.

Re: [PATCH v5 0/8][Outreachy] rebase -i: add options to fixup command

From: Charvi Mendiratta <hidden>
Date: 2021-02-05 09:46:46

Hi,

On Fri, 5 Feb 2021 at 13:00, Eric Sunshine [off-list ref] wrote:
[...]
Thanks for working on this and re-rolling. Unfortunately, it seems
that v4 already landed in Junio's `next` branch which means that he
won't be replacing v4 wholesale as would have been the case if it was
still in the `seen` branch. Once patches are in `next`, improvements
are made by building changes atop them (incrementally) rather than
replacing them. Whether or not it makes sense for you to spend time
re-doing these patches as incremental changes is not clear. In fact...
Okay, I admit I was not aware of this, before.
quoted
The major change in this version is to remove the working of `fixup -C`
with amend! commit and will include in the another patch series, in order
to avoid the confusion. So there are following changes :
* removed the patch (rebase -i : teach --autosquash to work with amend!)
* updated the test script (t3437-*.sh), changed the test setup and removed
  two tests.

  Earlier every test includes the commit message having subject starting
  with amend! So, now it includes a setup of different branch for testing
  fixup with options and also updated all the tests.
  Removed the test - "skip fixup -C removes amend! from message" and also
  "sequence of fixup, fixup -C & squash --signoff works" as I think it would
  be better to test this also in the branch with amend! commit with different
  author. (Will add these tests with amend! commit implementation)
Despite these being nice cleanups to the standalone series, I'm not
sure it's worth spending your time creating new patches to undo these
from `next`. Removing them only to add them back later is not
necessarily going to help "unconfuse" someone reading the commits in
the permanent project history.
Yes, I was also thinking that let's not remove the working of `fixup -C` with
amend! commit as it's true that it is intended to work like that way.
quoted
* changed the flag type from enum todo_item_flags to unsigned
* Replaced fixup_-* with fixup-* in lib-rebase.sh
* fixup a small nit in Documentation
These changes are still worthwhile and can easily be done
incrementally atop what is already in next, I would think.
I agree, these fixes are required. So, I am not sure but now to do these
fixup shall I send another patch cleaning this patch series(v4) and rebase the
patch on the 'next' branch ? Is it the right way ?

Thanks and Regards,
Charvi

Re: [PATCH v5 0/8][Outreachy] rebase -i: add options to fixup command

From: Christian Couder <hidden>
Date: 2021-02-05 18:29:32

On Fri, Feb 5, 2021 at 10:42 AM Charvi Mendiratta [off-list ref] wrote:
On Fri, 5 Feb 2021 at 13:00, Eric Sunshine [off-list ref] wrote:
quoted
quoted
* changed the flag type from enum todo_item_flags to unsigned
* Replaced fixup_-* with fixup-* in lib-rebase.sh
* fixup a small nit in Documentation
These changes are still worthwhile and can easily be done
incrementally atop what is already in next, I would think.
I agree, these fixes are required. So, I am not sure but now to do these
fixup shall I send another patch cleaning this patch series(v4) and rebase the
patch on the 'next' branch ? Is it the right way ?
Yeah, I think you can send each of the above 3 changes in a different
patch on top of the 'next' branch. That would create a new 3 patch
long series, which you should give a new name and not consider v5 of
the previous patch series.

Best,
Christian.

Re: [PATCH v5 0/8][Outreachy] rebase -i: add options to fixup command

From: Eric Sunshine <hidden>
Date: 2021-02-05 19:09:36

On Fri, Feb 5, 2021 at 1:25 PM Christian Couder
[off-list ref] wrote:
On Fri, Feb 5, 2021 at 10:42 AM Charvi Mendiratta [off-list ref] wrote:
quoted
On Fri, 5 Feb 2021 at 13:00, Eric Sunshine [off-list ref] wrote:
quoted
These changes are still worthwhile and can easily be done
incrementally atop what is already in next, I would think.
I agree, these fixes are required. So, I am not sure but now to do these
fixup shall I send another patch cleaning this patch series(v4) and rebase the
patch on the 'next' branch ? Is it the right way ?
Yeah, I think you can send each of the above 3 changes in a different
patch on top of the 'next' branch. That would create a new 3 patch
long series, which you should give a new name and not consider v5 of
the previous patch series.
Yes, whatever issues from my reviews seem worth fixing atop the
existing v4 can be included in this new patch series. (I think there
may have been a few things beyond the three listed in the v5 cover
letter, but I didn't bother doing a full audit of my review emails, so
I could be wrong.) As Christian said, just make it a new series,
though be sure to build it atop your v4 rather than building it atop
"next". (The problem with building atop "next" is that your series
then gets held hostage by _every_ series already in "next", which
makes it nearly impossible for your series to graduate to "master"
since it can't graduate until every other existing series in "next"
graduates to "master".) The one other important thing is to mention in
the cover letter that your new series is built atop "cm/rebase-i",
which lets Junio know where to place the new series when he picks it
up (and also lets reviewers know where to apply it if they want to
test it themselves).

Re: [PATCH v5 0/8][Outreachy] rebase -i: add options to fixup command

From: Charvi Mendiratta <hidden>
Date: 2021-02-06 05:38:17

On Sat, 6 Feb 2021 at 00:27, Eric Sunshine [off-list ref] wrote:
On Fri, Feb 5, 2021 at 1:25 PM Christian Couder
[off-list ref] wrote:
quoted
On Fri, Feb 5, 2021 at 10:42 AM Charvi Mendiratta [off-list ref] wrote:
quoted
On Fri, 5 Feb 2021 at 13:00, Eric Sunshine [off-list ref] wrote:
quoted
These changes are still worthwhile and can easily be done
incrementally atop what is already in next, I would think.
I agree, these fixes are required. So, I am not sure but now to do these
fixup shall I send another patch cleaning this patch series(v4) and rebase the
patch on the 'next' branch ? Is it the right way ?
Yeah, I think you can send each of the above 3 changes in a different
patch on top of the 'next' branch. That would create a new 3 patch
long series, which you should give a new name and not consider v5 of
the previous patch series.
Yes, whatever issues from my reviews seem worth fixing atop the
existing v4 can be included in this new patch series. (I think there
may have been a few things beyond the three listed in the v5 cover
letter, but I didn't bother doing a full audit of my review emails, so
I could be wrong.) As Christian said, just make it a new series,
though be sure to build it atop your v4 rather than building it atop
"next". (The problem with building atop "next" is that your series
then gets held hostage by _every_ series already in "next", which
makes it nearly impossible for your series to graduate to "master"
since it can't graduate until every other existing series in "next"
graduates to "master".) The one other important thing is to mention in
the cover letter that your new series is built atop "cm/rebase-i",
which lets Junio know where to place the new series when he picks it
up (and also lets reviewers know where to apply it if they want to
test it themselves).
Got it, Thanks !

Previous page

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help