Giter Site home page Giter Site logo

git-autofixup's Introduction

NAME

App::Git::Autofixup - create fixup commits for topic branches

SYNOPSIS

git-autofixup [<options>] [<revision>]

DESCRIPTION

git-autofixup parses hunks of changes in the working directory out of git diff output and uses git blame to assign those hunks to commits in <revision>..HEAD, which will typically represent a topic branch, and then creates fixup commits to be used with git rebase --interactive --autosquash. It is assumed that hunks near changes that were previously committed to the topic branch are related. <revision> defaults to git merge-base --fork-point HEAD @{upstream} || git merge-base HEAD @{upstream}, but this will only work if the current branch has an upstream/tracking branch. See git help revisions for info about how to specify revisions.

If any changes have been staged to the index using git add, then git-autofixup will only consider staged hunks when trying to create fixup commits. A temporary index is used to create any resulting commits.

By default a hunk will be included in a fixup commit if all the lines in the hunk's context blamed on topic branch commits refer to the same commit, so there's no ambiguity about which commit the hunk corresponds to. If there is ambiguity the assignment behaviour used under --strict 1 will be used to attempt to resolve it. If --strict 1 is given the same topic branch commit must be blamed for every removed line and at least one of the lines adjacent to each added line, and added lines must not be adjacent to lines blamed on other topic branch commits. All the same restrictions apply when --strict 2 is given, but each added line must be surrounded by lines blamed on the same topic branch commit.

For example, the added line in the hunk below is adjacent to lines committed by commits 99f370af and a1eadbe2. If these are both topic branch commits then it's ambiguous which commit the added line is fixing up and the hunk will be ignored.

COMMIT  |LINE|HEAD                          |WORKING DIRECTORY
99f370af|   1|first line                    | first line
        |    |                              |+added line
a1eadbe2|   2|second line                   | second line

But if that second line were instead blamed on an upstream commit (denoted by ^), the hunk would be added to a fixup commit for 99f370af:

99f370af|   1|first line                    | first line
        |    |                              |+added line
^       |   2|second line                   | second line

Output similar to this example can be generated by setting verbosity to 2 or greater by using the verbosity option multiple times, eg. git-autofixup -vv, and can be helpful in determining how a hunk will be handled.

git-autofixup is not to be used mindlessly. Always inspect the created fixup commits to ensure hunks have been assigned correctly, especially when used on a working directory that has been changed with a mix of fixups and new work.

Articles

OPTIONS

-h

Show usage.

--help

Show manpage.

--version

Show version.

-v, --verbose

Increase verbosity. Can be used up to two times.

-c N, --context N

Change the number of context lines git diff uses around hunks. Default: 3. This can change how hunks are assigned to fixup commits, especially with --strict 0.

-s N, --strict N

Set how strict git-autofixup is about assigning hunks to fixup commits. Default: 0. Strictness levels are described under DESCRIPTION.

-g ARG, --gitopt ARG

Specify option for git. Can be used multiple times. Useful for testing, to override config options that break git-autofixup, or to override global diff options to tweak what git-autofixup considers a hunk. Deprecated in favor of GIT_CONFIG_{COUNT,KEY,VALUE} environment variables; see git help config.

Note ARG won't be wordsplit, so to give multiple arguments, such as for setting a config option like -c diff.algorithm, this option must be used multiple times: -g -c -g diff.algorithm=patience.

-e, --exit-code

Use more detailed exit codes:

0:

All hunks have been assigned.

1:

Only some hunks have been assigned.

2:

No hunks have been assigned.

3:

There was nothing to be assigned.

255:

Unexpected error occurred.

INSTALLATION

If cpan is available, run cpan -i App::Git::Autofixup. Otherwise, copy git-autofixup to a directory in PATH and ensure it has execute permissions. It can then be invoked as either git-autofixup or git autofixup, since git searches PATH for appropriately named binaries.

Git is distributed with Perl 5 for platforms not expected to already have it installed, but installing modules with cpan requires other tools that might not be available, such as make. This script has no dependencies outside of the standard library, so it is hoped that it works on any platform that Git does without much trouble.

Requires a git supporting commit --fixup: 1.7.4 or later.

BUGS/LIMITATIONS

git-autofixup works on Windows, but be careful not to use a perl compiled for cygwin with a git compiled for msys, such as Git for Windows. It can be used from Git for Windows' "Git Bash" or "Git CMD", or you can install git using Cygwin's package manager and use git-autofixup from Cygwin. Note that while every release gets tested on Cygwin via the CPAN Testers network, testing with Git for Windows requires more effort since it's a constrained environment; thus it doesn't get tested as often. If you run into any issues, please report them on GitHub.

If a topic branch adds some lines in one commit and subsequently removes some of them in another, a hunk in the working directory that re-adds those lines will be assigned to fixup the first commit, and during rebasing they'll be removed again by the later commit.

ACKNOWLEDGEMENTS

git-autofixup was inspired by a description of hg absorb in the Mercurial Sprint Notes. While I was working on it I found git-superfixup, by oktal3700, which was helpful to examine.

COPYRIGHT AND LICENSE

Copyright (C) 2017, Jordan Torbiak.

This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License v2.0.

git-autofixup's People

Contributors

krobelus avatar lorenzleutgeb avatar szabgab avatar torbiak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

git-autofixup's Issues

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

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?

Installation fails 21/34 tests

On my Mac (macOS 10.14), installation via cpan -i App::Git::Autofixup &> log.txt fails. Full log: log.txt, but the highlight is:

# Looks like you failed 21 tests of 34.
t/autofixup.t ..
Dubious, test returned 21 (wstat 5376, 0x1500)
Failed 21/34 subtests

diff.noprefix = true not supported

Installation fails with this git configuration (in e.g. ~/.gitconfig):

[diff]
        noprefix = true

with the symptoms I had described in #9.

  • Installation via cpan -i App::Git::Autofixup &> log.txt fails.

  • Full log: log.txt, but the highlight is:

# Looks like you failed 21 tests of 34.
t/autofixup.t ..
Dubious, test returned 21 (wstat 5376, 0x1500)
Failed 21/34 subtests

FYI: alternative implementations

This is not an issue, so feel free to close straight away, but I thought you might be interested to know about my alternative implementation:

There are others too:

Use of uninitialized value $sha

Usually, git-autofixup works quite nicely. Today, I face this problem:

$ git autofixup -vv 11236e97ee
Use of uninitialized value $sha in hash element at /usr/local/bin/git-autofixup line 198.

Only one file is modified and the changes are minimal.

Limit `git autofixup` to specified files and/or to staged changes

It would be nice if it was possible to limit git-autofixup to changes in specific files, e. g.:

git autofixup <base> -- /path/to/file /path/to/something/else

Alternatively (might be even more useful), accept something like

  • --staged to only operate on already staged changes (mirroring git stash --staged), and
  • --keep-index for the opposite (mirroring git stash --keep-index).

Test::More dependency not mentioned

Following the installation instructions in the README does not work on a clean systen AFAICT. i.e. cpan -i App::Git::Autofixup. You also need to cpan -i Test::More.

Tests fail when commit.gpgsign = true

$ git config --global commit.gpgsign true
$ cpan -i App::Git::Autofixup
CPAN: LWP::UserAgent loaded ok (v6.43)
Fetching with LWP:
http://www.cpan.org/authors/01mailrc.txt.gz
Reading '/home/john/.local/share/.cpan/sources/authors/01mailrc.txt.gz'
CPAN: Compress::Zlib loaded ok (v2.084)
............................................................................DONE
Fetching with LWP:
http://www.cpan.org/modules/02packages.details.txt.gz
Reading '/home/john/.local/share/.cpan/sources/modules/02packages.details.txt.gz'
  Database was generated on Thu, 01 Apr 2021 16:29:02 GMT
.............
  New CPAN.pm version (v2.28) available.
  [Currently running version is v2.22]
  You might want to try
    install CPAN
    reload cpan
  to both upgrade CPAN.pm and run the new version without leaving
  the current session.


...............................................................DONE
Fetching with LWP:
http://www.cpan.org/modules/03modlist.data.gz
Reading '/home/john/.local/share/.cpan/sources/modules/03modlist.data.gz'
DONE
Writing /home/john/.local/share/.cpan/Metadata
Running install for module 'App::Git::Autofixup'
Fetching with LWP:
http://www.cpan.org/authors/id/T/TO/TORBIAK/App-Git-Autofixup-0.003001.tar.gz
CPAN: Digest::SHA loaded ok (v6.02)
Fetching with LWP:
http://www.cpan.org/authors/id/T/TO/TORBIAK/CHECKSUMS
Checksum for /home/john/.local/share/.cpan/sources/authors/id/T/TO/TORBIAK/App-Git-Autofixup-0.003001.tar.gz ok
'YAML' not installed, will not store persistent state
CPAN: CPAN::Meta::Requirements loaded ok (v2.140)
CPAN: Parse::CPAN::Meta loaded ok (v2.150010)
CPAN: CPAN::Meta loaded ok (v2.150010)
CPAN: Module::CoreList loaded ok (v5.20190522)
Configuring T/TO/TORBIAK/App-Git-Autofixup-0.003001.tar.gz with Makefile.PL
Checking if your kit is complete...
Looks good
WARNING: Older versions of ExtUtils::MakeMaker may errantly install README.pod as part of this distribution. It is recommended to avoid using this path in CPAN modules.
Generating a Unix-style Makefile
Writing Makefile for App::Git::Autofixup
Writing MYMETA.yml and MYMETA.json
  TORBIAK/App-Git-Autofixup-0.003001.tar.gz
  /usr/bin/perl Makefile.PL INSTALLDIRS=site -- OK
Running make for T/TO/TORBIAK/App-Git-Autofixup-0.003001.tar.gz
cp lib/App/Git/Autofixup.pm blib/lib/App/Git/Autofixup.pm
cp git-autofixup blib/script/git-autofixup
"/usr/bin/perl" -MExtUtils::MY -e 'MY->fixin(shift)' -- blib/script/git-autofixup
Manifying 1 pod document
Manifying 1 pod document
  TORBIAK/App-Git-Autofixup-0.003001.tar.gz
  /usr/bin/make -- OK
Running make test for TORBIAK/App-Git-Autofixup-0.003001.tar.gz
PERL_DL_NONLAZY=1 "/usr/bin/perl" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
t/autofixup.t .. error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad36ceee0)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad36ceee0)) called at t/autofixup.t line 253
t/autofixup.t .. 1/40
#   Failed test 'single-line change gets autofixed, strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad36ceee0)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad36ceee0)) called at t/autofixup.t line 253
t/autofixup.t .. 2/40
#   Failed test 'single-line change gets autofixed, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad36ceee0)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad36ceee0)) called at t/autofixup.t line 253

#   Failed test 'single-line change gets autofixed, strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad2d72288)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad2d72288)) called at t/autofixup.t line 272

#   Failed test 'adjacent change gets autofixed, strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad2d72288)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad2d72288)) called at t/autofixup.t line 272

#   Failed test 'adjacent change gets autofixed, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3ac1860)) called at t/autofixup.t line 293

#   Failed test 'adjacent change doesn't get autofixed if strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad376cc60)) called at t/autofixup.t line 303

#   Failed test 'fixups are created for additions surrounded by topic commit lines when strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad2d722b8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad2d722b8)) called at t/autofixup.t line 342

#   Failed test 'removed file doesn't get autofixed, strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad2d722b8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad2d722b8)) called at t/autofixup.t line 342

#   Failed test 'removed file doesn't get autofixed, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad2d722b8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad2d722b8)) called at t/autofixup.t line 342

#   Failed test 'removed file doesn't get autofixed, strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be92b8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be92b8)) called at t/autofixup.t line 354

#   Failed test 're-added file doesn't get autofixed, strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be92b8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be92b8)) called at t/autofixup.t line 354

#   Failed test 're-added file doesn't get autofixed, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be92b8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be92b8)) called at t/autofixup.t line 354

#   Failed test 're-added file doesn't get autofixed, strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be9630)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be9630)) called at t/autofixup.t line 358

#   Failed test 're-added line gets autofixed into the commit blamed for the adjacent context, strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be9630)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be9630)) called at t/autofixup.t line 358

#   Failed test 're-added line gets autofixed into the commit blamed for the adjacent context, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be9630)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be9630)) called at t/autofixup.t line 358

#   Failed test 're-added line gets autofixed into the commit blamed for the adjacent context, strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be9450)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be9450)) called at t/autofixup.t line 387

#   Failed test 'removed lines get autofixed, strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be9450)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be9450)) called at t/autofixup.t line 387
t/autofixup.t .. 18/40
#   Failed test 'removed lines get autofixed, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be9450)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be9450)) called at t/autofixup.t line 387

#   Failed test 'removed lines get autofixed, strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 412

#   Failed test 'no fixups are created for upstream commits, strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 412

#   Failed test 'no fixups are created for upstream commits, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 412

#   Failed test 'no fixups are created for upstream commits, strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 421

#   Failed test 'fixups are created for hunks changing lines blamed by upstream if strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad376caf8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad376caf8)) called at t/autofixup.t line 445

#   Failed test 'no fixups are created for hunks changing lines blamed by upstream if strict > 0, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad376caf8)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad376caf8)) called at t/autofixup.t line 445

#   Failed test 'no fixups are created for hunks changing lines blamed by upstream if strict > 0, strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3bf3808)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3bf3808)) called at t/autofixup.t line 466

#   Failed test 'hunks blamed on a fixup! commit are assigned to that fixup's target, strict=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3bf3808)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3bf3808)) called at t/autofixup.t line 466

#   Failed test 'hunks blamed on a fixup! commit are assigned to that fixup's target, strict=1'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3bf3808)) called at t/autofixup.t line 49
#       main::test_autofixup_strict(HASH(0xaaaad3bf3808)) called at t/autofixup.t line 466

#   Failed test 'hunks blamed on a fixup! commit are assigned to that fixup's target, strict=2'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3acffc0)) called at t/autofixup.t line 482

#   Failed test 'removed line gets autofixed when context=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3bf3670)) called at t/autofixup.t line 501

#   Failed test 'added line is ignored when context=0'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3a5d640)) called at t/autofixup.t line 510

#   Failed test 'ADJACENCY assignment is used as a fallback for multiple context targets'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3ac1890)) called at t/autofixup.t line 540

#   Failed test 'Works when run in a subdir of the repo root'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad2d874f8)) called at t/autofixup.t line 556

#   Failed test 'file without newline at EOF gets autofixed'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3bf4048)) called at t/autofixup.t line 576

#   Failed test 'multiple hunks in the same file get autofixed'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3acfff0)) called at t/autofixup.t line 613

#   Failed test 'single-line change gets autofixed when mnemonic prefixes are enabled'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be9870)) called at t/autofixup.t line 632
t/autofixup.t .. 36/40
#   Failed test 'single-line change gets autofixed when diff.external is set'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 651

#   Failed test 'exit code is 1 when some hunks are assigned'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3bf37a8)) called at t/autofixup.t line 670

#   Failed test 'multiple hunks to the same commit get autofixed'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad2d874f8)) called at t/autofixup.t line 707

#   Failed test 'only staged hunks get autofixed'
#   at t/autofixup.t line 140.
error: gpg failed to sign the data
fatal: failed to write commit object
# 32768 at t/autofixup.t line 210.
#       main::run("git", "commit", "-m", "add README") called at t/autofixup.t line 184
#       main::init_repo() called at t/autofixup.t line 101
#       eval {...} called at t/autofixup.t line 99
#       main::test_autofixup(HASH(0xaaaad3be8cb8)) called at t/autofixup.t line 735

#   Failed test 'staged hunks that aren't autofixed remain in index'
#   at t/autofixup.t line 140.
# Looks like you failed 40 tests of 40.
t/autofixup.t .. Dubious, test returned 40 (wstat 10240, 0x2800)
Failed 40/40 subtests

Test Summary Report
-------------------
t/autofixup.t (Wstat: 10240 Tests: 40 Failed: 40)
  Failed tests:  1-40
  Non-zero exit status: 40
Files=1, Tests=40,  3 wallclock secs ( 0.13 usr  0.03 sys +  0.84 cusr  1.98 csys =  2.98 CPU)
Result: FAIL
Failed 1/1 test programs. 40/40 subtests failed.
make: *** [Makefile:854: test_dynamic] Error 40
  TORBIAK/App-Git-Autofixup-0.003001.tar.gz
  /usr/bin/make test -- NOT OK
//hint// to see the cpan-testers results for installing this module, try:
  reports TORBIAK/App-Git-Autofixup-0.003001.tar.gz

Handle quoted filenames in diffs

As @krobelus mentioned here, Git quotes filenames that use unusual characters. Looks like we need to match quoted filenames and expand any escapes. For example:

$ git -c core.quotePath=false show --raw -p
commit c1235ca87f96496455721139af7fe8ea19b119fe (HEAD -> main)
Author: Jordan Torbiak <[email protected]>
Date:   Sun Mar 28 18:08:50 2021 -0600

    wierd name

:000000 100644 0000000 45b983b A        "wierd\"name"

diff --git "a/wierd\"name" "b/wierd\"name"
new file mode 100644
index 0000000..45b983b
--- /dev/null
+++ "b/wierd\"name"
@@ -0,0 +1 @@
+hi

Time for minor release?

Hi,

after your last release, you fixed the documentation a little. Would it make sense to do a new release to include this change?

Thanks

Limiting to certain files and hunks

On magit/magit#3053 @torbiak said:

[this made] me think about how useful it'd be to limit git-autofixup to certain files or regions of files, although I didn't come to any conclusions.

For files it should be easy to do: git autofixup revision -- file1 file2 .... But if you do that, then you probably also want to do it for individual hunks or "regions".


For Magit to be able to use git-autofixup only on certain hunks it would be enough if you implemented some sort of apply subcommand.

In Magit a user can stage an individual hunk by press s while the cursor is inside that hunk, which causes something like git diff ... | ... limit to hunk in question ... | git apply ... to happen. If git-autofixup also allowed piping a potentially manipulated diff to it, that would be great.

Thanks for considering.

No arguments behaviour

Is there any reason to require a <revision> argument. I would expect the tool to default to the root without a limit.

Great tool BTW :)

Have `git blame` do less work

We need to know if a line is blamed on the topic branch or upstream, but if it is blamed on upstream we don't care which commit exactly, so we should be able to save git blame some work by telling it to stop searching once it gets to the given upstream commit.

@krobelus: I think I have this working in the blameless branch. My initial, very limited measurements show a significant speedup even for small repos. I'm going to do some benchmarking before merging into master, but I thought you'd be interested in checking it out. See the commit message for details, particularly about the -S option to git blame.

Does not seem to handle filenames with spaces

➜  repo git:(foo) ✗ git status                  
On branch foo                                            
Your branch is ahead of 'origin/foo' by 6 commits.       
  (use "git push" to publish your local commits)                                        
                                                                                        
Changes not staged for commit:                                                          
  (use "git add <file>..." to update what will be committed)                            
  (use "git restore <file>..." to discard changes in working directory)                 
        modified:   .gitignore                                                          
        modified:   README.md                                                           
        modified:   src/AppSettings/Entities/AppSetting.vb                              
        modified:   src/AppSettings/My Project/Application.myapp                        
        modified:   src/AppSettings/My Project/AssemblyInfo.vb                          
        modified:   src/AppSettings/My Project/Settings.settings                        

➜  repo git:(foo) ✗ git autofixup origin/foo
fatal: no such path src/AppSettings/My Project/Application.myapp         in HEAD                
git blame: non-zero exit code at /usr/local/bin/git-autofixup line 336.                         

➜  repo git:(foo) ✗ echo $?
128

➜  repo git:(foo) ✗ git autofixup --version
0.003001                                                                           

autofixup fails when run from a subdirectory

This morning I accidentally tried to run git autofixup from a subdirectory of my git repo instead of the root. It failed with the following error:

[~/git/q44586-prodscript/q45459] (master) $ git autofixup @{u}
fatal: cannot stat path 'q45459/HEAD': No such file or directory
git blame: non-zero exit code at /localhome/campbr9/perl5/bin/git-autofixup line 324.

It's a pretty small thing, but it would be nice if I didn't have to care where i was in the git repo when I run the command.

"corrupt patch" error re-adding a newline at the end of a file

@campbellr was adding back a newline at the end of a file that had been removed in a previous commit and received a "corrupt patch" error.

I'm guessing the patch is being represented as a list containing a single empty string, and joining that with newlines produces...an empty string, which is an invalid patch for git.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.