Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbf429ce

Browse files
committed
Improve git_changelog as per discussion with Robert Haas.
1. Resurrect the behavior where old commits on master will have Branch:labels for branches sprouted after the commit was made. I'm stilldubious about this mode, but if you want it, say --post-date or -p.2. Annotate the Branch: labels with the release or branch in which thecommit was publicly released. For example, on a release branch you couldseeBranch: REL8_3_STABLE Release: REL8_3_2 [92c3a8004] 2008-03-29 00:15:37 +0000showing that the fix was released in 8.3.2. Commits on master willusually instead have notes likeBranch: master Release: REL8_4_BR [6fc9d42] 2008-03-29 00:15:28 +0000showing that this commit is ancestral to release branches 8.4 and later.If no Release: marker appears, the commit hasn't yet made it into anyrelease.3. Add support for release branches older than 7.4.4. The implementation is improved by running git log on each branch onlyback to where the branch sprouts from master. This saves a good dealof time (about 50% of the runtime when generating the complete history).We generate the post-date-mode tags via a direct understanding thatthey should be applied to master commits made before the branch sprouted,rather than backing into them via matching (which isn't any tooreliable when people used identical log messages for successive commits).
1 parente440e12 commitbf429ce

File tree

1 file changed

+119
-21
lines changed

1 file changed

+119
-21
lines changed

‎src/tools/git_changelog

Lines changed: 119 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@
55
#
66
# Display all commits on active branches, merging together commits from
77
# different branches that occur close together in time and with identical
8-
# log messages.
8+
# log messages. Commits are annotated with branch and release info thus:
9+
# Branch: REL8_3_STABLE Release: REL8_3_2 [92c3a8004] 2008-03-29 00:15:37 +0000
10+
# This shows that the commit on REL8_3_STABLE was released in 8.3.2.
11+
# Commits on master will usually instead have notes like
12+
# Branch: master Release: REL8_4_BR [6fc9d4272] 2008-03-29 00:15:28 +0000
13+
# showing that this commit is ancestral to release branches 8.4 and later.
14+
# If no Release: marker appears, the commit hasn't yet made it into any
15+
# release.
916
#
1017
# Most of the time, matchable commits occur in the same order on all branches,
1118
# and we print them out in that order. However, if commit A occurs before
@@ -26,36 +33,84 @@ require Time::Local;
2633
require Getopt::Long;
2734
require IPC::Open2;
2835

29-
# Adjust this list when the set of active branches changes.
36+
# Adjust this list when the set of interesting branches changes.
37+
# (We could get this from "git branches", but not worth the trouble.)
38+
# NB: master must be first!
3039
my@BRANCHES =qw(master REL9_0_STABLE REL8_4_STABLE REL8_3_STABLE
31-
REL8_2_STABLE REL8_1_STABLE REL8_0_STABLE REL7_4_STABLE);
40+
REL8_2_STABLE REL8_1_STABLE REL8_0_STABLE REL7_4_STABLE REL7_3_STABLE
41+
REL7_2_STABLE REL7_1_STABLE REL7_0_PATCHES REL6_5_PATCHES REL6_4);
3242

3343
# Might want to make this parameter user-settable.
3444
my$timestamp_slop = 600;
3545

46+
my$post_date = 0;
3647
my$since;
37-
Getopt::Long::GetOptions('since=s'=> \$since) || usage();
48+
Getopt::Long::GetOptions('post-date'=> \$post_date,
49+
'since=s'=> \$since) || usage();
3850
usage()if@ARGV;
3951

4052
my@git =qw(git log --date=iso);
4153
push@git,'--since=' .$sinceifdefined$since;
4254

55+
# Collect the release tag data
56+
my%rel_tags;
57+
58+
{
59+
my$cmd ="git for-each-ref refs/tags";
60+
my$pid = IPC::Open2::open2(my$git_out,my$git_in,$cmd)
61+
||die"can't run$cmd:$!";
62+
while (my$line = <$git_out>) {
63+
if ($line =~m|^([a-f0-9]+)\s+commit\s+refs/tags/(\S+)|) {
64+
my$commit =$1;
65+
my$tag =$2;
66+
if ($tag =~/^REL\d+_\d+$/ ||
67+
$tag =~/^REL\d+_\d+_\d+$/) {
68+
$rel_tags{$commit} =$tag;
69+
}
70+
}
71+
}
72+
waitpid($pid, 0);
73+
my$child_exit_status =$? >> 8;
74+
die"$cmd failed"if$child_exit_status != 0;
75+
}
76+
77+
# Collect the commit data
4378
my%all_commits;
4479
my%all_commits_by_branch;
80+
# This remembers where each branch sprouted from master. Note the values
81+
# will be wrong if --since terminates the log listing before the branch
82+
# sprouts; but in that case it doesn't matter since we also won't reach
83+
# the part of master where it would matter.
84+
my%sprout_tags;
4585

4686
formy$branch (@BRANCHES) {
47-
my$pid =
48-
IPC::Open2::open2(my$git_out,my$git_in,@git,"origin/$branch")
49-
||die"can't run@git origin/$branch:$!";
87+
my@cmd =@git;
88+
if ($brancheq"master") {
89+
push@cmd,"origin/$branch";
90+
}else {
91+
push@cmd,"--parents";
92+
push@cmd,"master..origin/$branch";
93+
}
94+
my$pid = IPC::Open2::open2(my$git_out,my$git_in,@cmd)
95+
||die"can't run@cmd:$!";
96+
my$last_tag =undef;
97+
my$last_parent;
5098
my%commit;
5199
while (my$line = <$git_out>) {
52-
if ($line =~/^commit\s+(.*)/) {
100+
if ($line =~/^commit\s+(\S+)/) {
53101
push_commit(\%commit)if%commit;
102+
$last_tag =$rel_tags{$1}ifdefined$rel_tags{$1};
54103
%commit = (
55104
'branch'=>$branch,
56105
'commit'=>$1,
106+
'last_tag'=>$last_tag,
57107
'message'=>'',
58108
);
109+
if ($line =~/^commit\s+\S+\s+(\S+)/) {
110+
$last_parent =$1;
111+
}else {
112+
$last_parent =undef;
113+
}
59114
}
60115
elsif ($line =~/^Author:\s+(.*)/) {
61116
$commit{'author'} =$1;
@@ -68,9 +123,43 @@ for my $branch (@BRANCHES) {
68123
}
69124
}
70125
push_commit(\%commit)if%commit;
126+
$sprout_tags{$last_parent} =$branchifdefined$last_parent;
71127
waitpid($pid, 0);
72128
my$child_exit_status =$? >> 8;
73-
die"@git origin/$branch failed"if$child_exit_status != 0;
129+
die"@cmd failed"if$child_exit_status != 0;
130+
}
131+
132+
# Run through the master branch and apply tags. We already tagged the other
133+
# branches, but master needs a separate pass after we've acquired the
134+
# sprout_tags data. Also, in post-date mode we need to add phony entries
135+
# for branches that sprouted after a particular master commit was made.
136+
{
137+
my$last_tag =undef;
138+
my%sprouted_branches;
139+
formy$cc (@{$all_commits_by_branch{'master'}}) {
140+
my$commit =$cc->{'commit'};
141+
my$c =$cc->{'commits'}->[0];
142+
$last_tag =$rel_tags{$commit}ifdefined$rel_tags{$commit};
143+
if (defined$sprout_tags{$commit}) {
144+
$last_tag =$sprout_tags{$commit};
145+
# normalize branch names for making sprout tags
146+
$last_tag =~s/^(REL\d+_\d+).*/$1_BR/;
147+
}
148+
$c->{'last_tag'} =$last_tag;
149+
if ($post_date) {
150+
if (defined$sprout_tags{$commit}) {
151+
$sprouted_branches{$sprout_tags{$commit}} = 1;
152+
}
153+
# insert new commits between master and any other commits
154+
my@new_commits = (shift @{$cc->{'commits'}} );
155+
formy$branch (reversesortkeys%sprouted_branches) {
156+
my$ccopy = {%{$c}};
157+
$ccopy->{'branch'} =$branch;
158+
push@new_commits,$ccopy;
159+
}
160+
$cc->{'commits'} = [@new_commits, @{$cc->{'commits'}} ];
161+
}
162+
}
74163
}
75164

76165
my%position;
@@ -104,7 +193,14 @@ while (1) {
104193
lastif !defined$best_branch;
105194
my$winner =
106195
$all_commits_by_branch{$best_branch}->[$position{$best_branch}];
107-
print$winner->{'header'};
196+
printf"Author:%s\n",$winner->{'author'};
197+
foreachmy$c (@{$winner->{'commits'}}) {
198+
printf"Branch:%s",$c->{'branch'};
199+
if (defined$c->{'last_tag'}) {
200+
printf" Release:%s",$c->{'last_tag'};
201+
}
202+
printf" [%s]%s\n",substr($c->{'commit'}, 0, 9),$c->{'date'};
203+
}
108204
print"Commit-Order-Inversions:$best_inversions\n"
109205
if$best_inversions != 0;
110206
print"\n";
@@ -143,22 +239,22 @@ sub push_commit {
143239
}
144240
if (!defined$cc) {
145241
$cc = {
146-
'header'=>sprintf("Author:%s\n",$c->{'author'}),
242+
'author'=>$c->{'author'},
147243
'message'=>$c->{'message'},
148244
'commit'=>$c->{'commit'},
245+
'commits'=> [],
149246
'timestamp'=>$ts
150247
};
151248
push @{$all_commits{$ht}},$cc;
152-
}elsif ($cc->{'commit'}eq$c->{'commit'}) {
153-
# If this is exactly the same commit we saw before on another
154-
# branch, ignore it. Hence, a commit that's reachable from more
155-
# than one branch head will be reported only for the first
156-
# head it's reachable from. This will give the desired results
157-
# so long as @BRANCHES is ordered with master first.
158-
return;
159249
}
160-
$cc->{'header'} .=sprintf"Branch:%s [%s]%s\n",
161-
$c->{'branch'},substr($c->{'commit'}, 0, 9),$c->{'date'};
250+
# stash only the fields we'll need later
251+
my$smallc = {
252+
'branch'=>$c->{'branch'},
253+
'commit'=>$c->{'commit'},
254+
'date'=>$c->{'date'},
255+
'last_tag'=>$c->{'last_tag'}
256+
};
257+
push @{$cc->{'commits'}},$smallc;
162258
push @{$all_commits_by_branch{$c->{'branch'}}},$cc;
163259
$cc->{'branch_position'}{$c->{'branch'}} =
164260
-1+@{$all_commits_by_branch{$c->{'branch'}}};
@@ -180,7 +276,9 @@ sub parse_datetime {
180276

181277
subusage {
182278
printSTDERR<<EOM;
183-
Usage: git_changelog [--since=SINCE]
279+
Usage: git_changelog [--post-date/-p] [--since=SINCE]
280+
--post-date Show branches made after a commit occurred
281+
--since Print only commits dated since SINCE
184282
EOM
185283
exit 1;
186284
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp