-
Oswald Buddenhagen authored
Change-Id: I670423c6001e2a504df8be80b42ee88566ad3baa Reviewed-by:
Oswald Buddenhagen <oswald.buddenhagen@digia.com>
e2f973a8
git-rewrite-author 3.20 KiB
#!/usr/bin/env perl
# Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
# Contact: http://www.qt-project.org/legal
#
# You may use this file under the terms of the 3-clause BSD license.
# See the file LICENSE from this package for details.
#
use strict;
use warnings;
use Getopt::Long;
sub usage {
print STDERR
q{Usage: git rewrite-author --from <from> --to <to> [ -f | --force ]
[--] [<rev-list options>...]
Replace author and committer field in some commits.
EXAMPLE:
You've accidentally made some commits like this:
Author: bjones <bjones@localhost.localdomain>
... where it should have been:
Author: Bob Jones <bob.jones@example.com>
The first bad commit is a1b2c3d4...
Fix it up by:
$ git rewrite-author --from "bjones <bjones@localhost.localdomain>" \
--to "Bob Jones <bob.jones@example.com>" a1b2c3d4^..HEAD
If you omit a range of commits, this command will scan _all_ commits
leading up to HEAD, which will take a long time for repositories with
a large history.
WARNING: this script will change the SHA1 of every commit including
and following the first rewritten commit. You can't do this for commits
you've already pushed unless you really know what you're doing!
};
}
sub parse_author
{
my $author = shift;
if ($author =~ /^(.*?) <([^>]+)>$/) {
return ($1, $2);
}
else {
die "Could not parse `$author'; expected something like \"Some Name <some.address\@example.com>\"";
}
}
# Return a string single-quoted for use in shell
sub sh_squote
{
my $out = shift;
$out =~ s/'/'"'"'/g;
return "'$out'";
}
# Return fragment of shell code to rewrite a specific env var
sub rewrite_env
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
{
my %opts = @_;
my $env = $opts{env};
my $from = sh_squote($opts{from});
my $to = sh_squote($opts{to});
my $cmd = <<EOF
if [ "\$$env" = $from ]; then
$env=$to;
export $env;
if [ \$REWROTE = 0 ]; then
echo;
echo Hit for \$GIT_COMMIT:;
REWROTE=1;
fi;
echo " $env:" $from '->' $to;
fi
EOF
;
$cmd =~ s/\n */ /sg;
return $cmd;
}
my $from;
my $to;
my $force;
if (!GetOptions(
"from=s" => \$from,
"to=s" => \$to,
"force" => \$force,
)) {
usage;
exit 2;
}
if (!$from || !$to) {
print STDERR "Need `--from' and `--to' arguments\n";
usage;
exit 2;
}
my ($from_name, $from_address) = parse_author($from);
my ($to_name, $to_address) = parse_author($to);
my $env_filter_command = "REWROTE=0; ".
rewrite_env(
env => 'GIT_AUTHOR_NAME',
from => $from_name,
to => $to_name,
)
. "; " .
rewrite_env(
env => 'GIT_COMMITTER_NAME',
from => $from_name,
to => $to_name,
)
. "; " .
rewrite_env(
env => 'GIT_AUTHOR_EMAIL',
from => $from_address,
to => $to_address,
)
. "; " .
rewrite_env(
env => 'GIT_COMMITTER_EMAIL',
from => $from_address,
to => $to_address,
)
141142143144145146147148149150151
;
my @git_filter_branch = ("git", "filter-branch", "--env-filter", $env_filter_command);
if ($force) {
push @git_filter_branch, "--force";
}
push @git_filter_branch, @ARGV;
exec @git_filter_branch;