gitrebasesquashgit-squash

How to make sure fixup commits are not merged into master branch


I use git commit --fixup (or --squash) a lot, especially during code reviews. Obviously these commits should eventually disappear after a git rebase --autosquash but it worries me that I might forget to rebase and merge these commits into master.

How can I ensure that either I cannot merge these into certain branches, or at least that certain branches cannot be pushed with these commits in them?


Solution

  • You could at least block any pushes containing fixup! with the pre-push hook below.

    #! /usr/bin/perl
    
    use strict;
    use warnings;
    
    use constant Z40 => '0' x 40;
    
    my($remote,$url) = @ARGV;
    
    my $abort_push = 0;
    while (<STDIN>) {
      # <local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF
      my($lref,$lsha,$rref,$rsha) = split;
    
      if ($lsha eq Z40) {} # ignore deletes
      else {
        my $commit_range =
          $rsha eq Z40
            ? $lsha            # new branch: check all commits
            : "$rsha..$lsha";  # existing: check new commits since $rsha
        my @cmd = (qw/ git rev-list --pretty=oneline --grep ^fixup! /, $commit_range);
    
        open my $fh, "-|", @cmd or die "$0: failed to start git rev-list: $!";
        my @fixup_commits;
        while (<$fh>) { push @fixup_commits, "  - $_" }
        close $fh;
    
        if (@fixup_commits) {
          my $s = @fixup_commits == 1 ? "" : "s";
          warn "Remove fixup$s from $lref:\n", @fixup_commits;
          $abort_push = 1;
        }
      }
    }
    
    die "Push aborted.\n" if $abort_push;
    

    So for example with a history of

    $ git lola
    * 4a732d4 (HEAD -> feature/foo) fixup! fsdkfj
    | * 478075c (master) w00t
    | * 1d572d3 fixup! sdlkf
    | * f9a55ee fixup! yo
    |/  
    * ea708b0 (origin/master) three
    * d4276a2 two
    * 6426569 hello
    

    Attempting to push gives

    $ git push origin master feature/foo
    Remove fixups from refs/heads/master:
      - 1d572d32f963d6218ed3b92f69d58a8ec790d7ea fixup! sdlkf
      - f9a55ee14f28f9496e2aea1bc400ca65ae150f4b fixup! yo
    Remove fixup from refs/heads/feature/foo:
      - 4a732d4601012246986037437ac0c0bab39dd0a9 fixup! fsdkfj
    Push aborted.
    error: failed to push some refs to [...]
    

    Note that git lola is a non-standard but highly useful alias. Add the following to your global .gitconfig.

    [alias]
            lol = log --graph --decorate --pretty=oneline --abbrev-commit
            lola = log --graph --decorate --pretty=oneline --abbrev-commit --all