]> granicus.if.org Git - postgresql/commitdiff
Fix some more bugs in git_changelog.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 26 Sep 2010 04:21:51 +0000 (00:21 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 26 Sep 2010 04:21:51 +0000 (00:21 -0400)
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.

src/tools/git_changelog

index 3424cb72bd0e4df845ee11f66a512cfa68b0d5cd..766f66a4da79cc9ecdffc46c2c3f3d56bfc88130 100755 (executable)
@@ -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;