torbiak / git-autofixup

create fixup commits for topic branches

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Default strict mode doesn't limit to single "adjacent" topic commit

johnddx opened this issue · comments

The default strict mode indicates:

    0: exactly one topic branch commit is blamed in hunk context or 
       changed lines are adjacent to exactly one topic branch commit

However, when it finds a "-" line, it will almost always blame the commit that added it even if it is neighboring a "+" line that blames a different commit.

In get_fixup_targets_from_adjacent_context(), this block will always mark a blamed sha:

        if (startswith($line, '-')) {
            my $sha = $blame->{$bi}{sha};
            $blamed{$sha} = 1;
        } elsif (startswith($line, '+')) {

This guarantees that a non-empty blamed set is returned, without testing for adjacency or strictness. In the '+' case, a pair of blamed commits will be discarded (because the conditions require exactly one blamed commit), which will still leave a commit added by the '-' case. If the '+' case finds more than one adjacent commit, why would the '-' case be kept?

I took some liberties with the strictness level descriptions in the -h output regarding removed lines for the sake of brevity. Removed lines correspond definitely with the commit they're blamed on, unlike added lines, for which we have to guess which topic branch commit they correspond to based on which commits the adjacent pre-existing lines are blamed on. And so removed lines intentionally aren't subject to the adjacency/surrounded checks that added lines are.

After reading the POD's DESCRIPTION of strictness levels again I believe it matches up with the code, and it's more precise and verbose, so it's probably more helpful for getting an understanding of what git-autofixup is trying to do.

If you have an example that doesn't behave as expected, I'd like to see it.

I'll try to come up with better short descriptions of the strictness levels.

What do you think of this?

-s N, --strict N   set strictness (default 0)
    Assign a hunk to fixup a topic branch commit if:

    0: either only one topic branch commit is blamed in the hunk context or
       blocks of added lines are adjacent to exactly one topic branch commit.
       Removing upstream lines is allowed for this level.
    1: blocks of added lines are adjacent to exactly one topic branch commit
    2: blocks of added lines are surrounded by exactly one topic branch commit

    Removed lines are correlated with the commit they're blamed on. Regardless
    of strictness level, all the blocks of changed lines in a hunk must be
    correlated with the same topic branch commit in order to be assigned to it.
    See the --help for more details.

I've tweaked that final paragraph some more:

-s N, --strict N   set strictness (default 0)
    Assign a hunk to fixup a topic branch commit if:

    0: either only one topic branch commit is blamed in the hunk context or
       blocks of added lines are adjacent to exactly one topic branch commit.
       Removing upstream lines is allowed for this level.
    1: blocks of added lines are adjacent to exactly one topic branch commit
    2: blocks of added lines are surrounded by exactly one topic branch commit

    Regardless of strictness level, removed lines are correlated with the
    commit they're blamed on, and all the blocks of changed lines in a hunk
    must be correlated with the same topic branch commit in order to be
    assigned to it. See the --help for more details.

@campbellr, do you have any thoughts on how to improve the short help, in particular the descriptions of the strictness levels? The description in my previous comment is pretty long for a usage synopsis, but the strict option is inscrutable without something like it. In the code I describe the strictness levels as CONTEXT, ADJACENT, and SURROUND, but there's a lot of background necessary to understand what those words imply. Maybe --strict isn't useful enough to warrant a description in the short help and describing it only in the long help would be better than having an imprecise description in the short help?