Rename multiple names and emails in a single pass of git-filter-branch

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:

  • How can I tell which remote “parent” branch my branch is based on?
  • How can I define an alias for a Git subcommand (e.g. for `list` in `git stash list`)?
  • Unable to push to remote GIT repository — “ does not appear to be a git repository”
  • Branch associated with 'Default Task' in IntelliJ
  • Git review systems
  • What's the difference between git reset --hard and git reset --merge
  • 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:

    enter image description here

  • Can I share the same eclipse project on a SVN & a GIT repository simultaneously?
  • How do I remove an author from a git repository?
  • Does git reuse blobs?
  • Why Git fail to connect to local repository with Jenkins (bad config file)?
  • Show system files / Show git ignore in osx
  • Setting Up Environments with SaltStack
  • One Solution collect form web for “Rename multiple names and emails in a single pass of git-filter-branch”

    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 ... thens, 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.)

    Git Baby is a git and github fan, let's start git clone.