Fix some more bugs in git_changelog.

1. Don't forget the last (oldest) commit on the oldest branch.

2. When considering which commit to print next, if two alternatives have
the same "distortion" score (which is actually the normal case, since
generally the "distortion" is 0), then choose the later timestamp to
print first.  I don't know where Robert got the idea to ignore timestamps
and sort by branch age, but it wasn't a good idea: the resulting ordering
of commits was just plain bizarre anywhere that some branches had many
fewer commits than others, which is the typical situation for us.
This commit is contained in:
Tom Lane 2010-09-26 00:21:51 -04:00
parent 901a5a786f
commit 30d2e10058
1 changed files with 19 additions and 18 deletions

View File

@ -5,24 +5,19 @@
#
# Display all commits on active branches, merging together commits from
# different branches that occur close together in time and with identical
# log messages. Most of the time, such commits occur in the same order
# on all branches, and we print them out in that order. However, if commit
# A occurs before commit B on branch X and commit B occurs before commit A
# on branch Y, then there's no ordering which is consistent with both
# branches.
# log messages.
#
# Most of the time, matchable commits occur in the same order on all branches,
# and we print them out in that order. However, if commit A occurs before
# commit B on branch X and commit B occurs before commit A on branch Y, then
# there's no ordering which is consistent with both branches.
#
# When we encounter a situation where there's no single "best" commit to
# print next, we print the one that involves the least distortion of the
# commit order, summed across all branches. In the event of a further tie,
# the commit from the newer branch prints first. It is best not to sort
# based on timestamp, because git timestamps aren't necessarily in order
# (since the timestamp is provided by the committer's machine), even though
# for the portion of the history we imported from CVS, we expect that they
# will be.
#
# Even though we don't use timestamps to order commits, they are used to
# identify which commits happened at about the same time, for the purpose
# of matching up commits from different branches.
# commit order, summed across all branches. In the event of a tie on the
# distortion measure (which is actually the common case: normally, the
# distortion is zero), we choose the commit with latest timestamp. If
# that's a tie too, the commit from the newer branch prints first.
#
use strict;
@ -48,12 +43,12 @@ push @git, '--since=' . $since if defined $since;
my %all_commits;
my %all_commits_by_branch;
my %commit;
for my $branch (@BRANCHES) {
my $commitnum = 0;
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+(.*)/) {
push_commit(\%commit) if %commit;
@ -74,6 +69,7 @@ for my $branch (@BRANCHES) {
$commit{'message'} .= $line;
}
}
push_commit(\%commit) if %commit;
waitpid($pid, 0);
my $child_exit_status = $? >> 8;
die "@git origin/$branch failed" if $child_exit_status != 0;
@ -87,6 +83,7 @@ for my $branch (@BRANCHES) {
while (1) {
my $best_branch;
my $best_inversions;
my $best_timestamp;
for my $branch (@BRANCHES) {
my $leader = $all_commits_by_branch{$branch}->[$position{$branch}];
next if !defined $leader;
@ -97,9 +94,13 @@ while (1) {
- $position{$branch2};
}
}
if (!defined $best_inversions || $inversions < $best_inversions) {
if (!defined $best_inversions ||
$inversions < $best_inversions ||
($inversions == $best_inversions &&
$leader->{'timestamp'} > $best_timestamp)) {
$best_branch = $branch;
$best_inversions = $inversions;
$best_timestamp = $leader->{'timestamp'};
}
}
last if !defined $best_branch;