my $pid =
      IPC::Open2::open2(my $git_out, my $git_in, @git, "origin/$branch")
          || die "can't run @git origin/$branch: $!";
-   my $commitnum = 0;
    my %commit;
    while (my $line = <$git_out>) {
        if ($line =~ /^commit\s+(.*)/) {
                'branch' => $branch,
                'commit' => $1,
                'message' => '',
-               'commitnum' => $commitnum++,
            );
        }
        elsif ($line =~ /^Author:\s+(.*)/) {
    my $ht = hash_commit($c);
    my $ts = parse_datetime($c->{'date'});
    my $cc;
+   # Note that this code will never merge two commits on the same branch,
+   # even if they have the same hash (author/message) and nearby
+   # timestamps.  This means that there could be multiple potential
+   # matches when we come to add a commit from another branch.  Prefer
+   # the closest-in-time one.
    for my $candidate (@{$all_commits{$ht}}) {
-       if (abs($ts - $candidate->{'timestamp'}) < $timestamp_slop
-           && !exists $candidate->{'branch_position'}{$c->{'branch'}})
+       my $diff = abs($ts - $candidate->{'timestamp'});
+       if ($diff < $timestamp_slop &&
+           !exists $candidate->{'branch_position'}{$c->{'branch'}})
        {
+           if (!defined $cc ||
+           $diff < abs($ts - $cc->{'timestamp'})) {
            $cc = $candidate;
-           last;
+           }
        }
    }
    if (!defined $cc) {
        $cc = {
            'header' => sprintf("Author: %s\n", $c->{'author'}),
            'message' => $c->{'message'},
+           'commit' => $c->{'commit'},
            'timestamp' => $ts
        };
        push @{$all_commits{$ht}}, $cc;
+   } elsif ($cc->{'commit'} eq $c->{'commit'}) {
+       # If this is exactly the same commit we saw before on another
+       # branch, ignore it.  Hence, a commit that's reachable from more
+       # than one branch head will be reported only for the first
+       # head it's reachable from.  This will give the desired results
+       # so long as @BRANCHES is ordered with master first.
+       return;
    }
    $cc->{'header'} .= sprintf "Branch: %s [%s] %s\n",
        $c->{'branch'}, substr($c->{'commit'}, 0, 9), $c->{'date'};