问题
Is it possible to mass-rename 2 or more email addresses with a single pass of git filter-branch
?
I tried adapting the code from this answer by just duplicating the if..fi clause
:
git filter-branch --commit-filter '
if [ "$GIT_COMMITTER_NAME" = "<Old Name 1>" ];
then
GIT_COMMITTER_NAME="<New Name 1>";
GIT_AUTHOR_NAME="<New Name 1>";
GIT_COMMITTER_EMAIL="<New Email 1>";
GIT_AUTHOR_EMAIL="<New Email 1>";
git commit-tree "$@";
else
git commit-tree "$@";
fi
if [ "$GIT_COMMITTER_NAME" = "<Old Name 2>" ];
then
GIT_COMMITTER_NAME="<New Name 2>";
GIT_AUTHOR_NAME="<New Name 2>";
GIT_COMMITTER_EMAIL="<New Email 2>";
GIT_AUTHOR_EMAIL="<New Email 2>";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
But it gave me errors during the filter-branch that looked like this:
error: duplicate parent bc8f9924c33558a275b8f694969529cf56232c80 ignored
And then the branch history was all tangled up:
回答1:
You want just one git commit-tree
command, after setting all the environment variables as desired. For instance, your commit filter might read something like this:
git filter-branch -f --commit-filter '
if [ "$GIT_COMMITTER_NAME" = "<Old Name 1>" ]; then
GIT_COMMITTER_NAME="<New Name 1>";
GIT_AUTHOR_NAME="<New Name 1>";
GIT_COMMITTER_EMAIL="<New Email 1>";
GIT_AUTHOR_EMAIL="<New Email 1>";
fi;
if [ "$GIT_COMMITTER_NAME" = "<Old Name 2>" ]; then
GIT_COMMITTER_NAME="<New Name 2>";
GIT_AUTHOR_NAME="<New Name 2>";
GIT_COMMITTER_EMAIL="<New Email 2>";
GIT_AUTHOR_EMAIL="<New Email 2>";
fi;
git commit-tree "$@"
'
(although if the number of name changes to make gets higher I'd probably run through a mapping file instead of a long series of easy-to-typo if ... then
s, and it might make more sense to map author and committer separately).
Remember that filter-branch
simply copies all the commits you tell it to copy (by using git commit-tree
to make the new copy), while building a map of <old-sha1,new-sha1> pairs. This is why making two commits is not good: one existing (old) SHA-1 now has to map to two new copies, which is simply not allowed in terms of what filter-branch
does with the commit graph. (Multiple old SHA-1s can map to a single new SHA-1, if you choose to omit some commits during the copying process. That is, the new graph can be bijective or surjective, but filter-branch doesn't really believe in injective, as it's going to try to map the old references to the new graph.)
来源:https://stackoverflow.com/questions/33866185/rename-multiple-names-and-emails-in-a-single-pass-of-git-filter-branch