This repository was archived by the owner on Dec 10, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Collapse file tree
Files
Search this repository
/
Copy path02-squash.pl
More file actions
More file actions
Latest commit
73 lines (63 loc) · 2.18 KB
/
02-squash.pl
File metadata and controls
73 lines (63 loc) · 2.18 KB
You must be signed in to make or propose changes
More edit options
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/usr/bin/env perl
#
# Generate a git rebase todo from a git log to squash commits by the specific
# authors into one (or as few as possible) per file, per author, per day.
#
use strict;
use warnings;
# Groups of commits to squash. Each element is a `[pick, fixup...]` group that
# will become a single squashed commit.
my @squash_groups;
# Metadata for the last group seen for each title.
my %last_seen;
# Read a git log line by line.
while (<>) {
# Strip the newline.
chomp;
# Extract fields.
my ($hash, $datetime, $day, $author, $message) =
/^pick ([0-9a-f]{7}) # "((\d{4}-\d{2}-\d{2})T\d{2}:\d{2}:\d{2}\+09:00)", "(.+?)", "(.*)"$/
or die "line $.: $_";
# Extract title. Fallback to hash if no match.
my ($title) = $message =~ /^(?:Created|Updated) (.+) \(markdown\)$/;
$title ||= $hash;
# Check if this commit can be squashed into the last group for the title.
my $seen = $last_seen{$title};
if (
$seen
and $seen->{day} eq $day
and $seen->{author} eq $author
and $author =~ /^(?:yuuki|bear)$/
) {
# Squashable: append to the existing group.
s/^pick/fixup/;
push @{ $squash_groups[ $seen->{index} ] }, { line => $_, datetime => $datetime };
}
else {
# Create a new group.
push @squash_groups, [ { line => $_, datetime => $datetime } ];
$last_seen{$title} = {
index => $#squash_groups,
day => $day,
author => $author,
};
}
}
# Sort groups by their last commit's date.
@squash_groups = sort { $a->[-1]{datetime} cmp $b->[-1]{datetime} } @squash_groups;
# Output groups.
for my $group (@squash_groups) {
for my $i (0 .. $#{$group}) {
my $commit = $group->[$i];
print $commit->{line}, "\n";
# After the last fixup in the group, amend the author and committer
# dates to that fixup's date.
if ($commit->{line} =~ /^fixup/ and $i == $#{$group}) {
printf(
"exec GIT_COMMITTER_DATE='%s' git commit --amend --date='%s' --allow-empty --no-edit\n",
$commit->{datetime},
$commit->{datetime},
);
}
}
}