根据.mailmap文件重写git历史记录

时间:2014-12-03 15:13:31

标签: git git-filter-branch

git是否提供了一种方法自动根据.mailmap文件中指定的替换重写git存储库历史记录(详见git help shortlog)?< / p>

cd repository.git
somecommand /path/to/.mailmap # <-- ???

2 个答案:

答案 0 :(得分:6)

没有简短的git命令。我需要使用git filter-branch --commit-filter <command> [...] <command>使用GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL更改GIT_COMMITTER_NAMEGIT_COMMITTER_EMAILgit check-mailmap-c mailmap.file=/path/to/.mailmap变量1}}或-c mailmap.blob=SOMEREV:path/to/.mailmap,例如,要使用主分支中的.mailmap文件,可以使用

git filter-branch --commit-filter '
    R=`echo "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" | git -c mailmap.blob=master:.mailmap check-mailmap --stdin`
    GIT_AUTHOR_NAME="${R% <*@*>}"
    R="${R##* <}"
    GIT_AUTHOR_EMAIL="${R%>}"
    R=`echo "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" | git -c mailmap.blob=master:.mailmap check-mailmap --stdin`
    GIT_COMMITTER_NAME="${R% <*@*>}"
    R="${R##* <}"
    GIT_COMMITTER_EMAIL="${R%>}"
    git commit-tree "$@"
' HEAD

这当然适用于具有POSIX shell的系统。

请注意,这不会在提交消息中重写任何Signed-off-by:或类似的行。

答案 1 :(得分:0)

我今天需要这个,但是与另一个--commit-filter结合使用(以获得根据How do I get a list of old->new rewritten commit SHAs from 'git filter-branch'?的旧到新提交ID的映射文件)。

我最终以@BooK出色的comment作为起点,所以让我们将其转化为正确的答案。


git filter branch提供了--env-filter选项,可以在提交之前更改元信息,而--commit-filter会在提交期间更改它们。承诺。这意味着我们可以将信息修复和实际提交分为两个单独的过滤器脚本

“缺点”是env-filter需要export变量,因此它们会一直保留到提交阶段。

@jotik's answer的环境过滤器版本如下:

# make sure we have a copy of the mailmap that won't be affected by other parts of the filter-branch
cp .mailmap /tmp/mailmap

git filter-branch \
    --your-other-filters-here
    --env-filter '
    # fix author
    # apply mailmap to "current" person tagline, store in temp $R
    R=$(echo "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" | git -c mailmap.file=/tmp/mailmap check-mailmap --stdin)
    # extract mailmapped, pieces from $R using shell variable replacements
    export GIT_AUTHOR_NAME="${R% <*@*>}"
    R="${R##* <}"
    export GIT_AUTHOR_EMAIL="${R%>}"

    # repeat for committer
    R=$(echo "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" | git -c mailmap.file=/tmp/mailmap check-mailmap --stdin)
    export GIT_COMMITTER_NAME="${R% <*@*>}"
    R="${R##* <}"
    export GIT_COMMITTER_EMAIL="${R%>}"
'  -- --all

此后可选进行清理:

git rm .mailmap
git commit -m "delete mailmap after fixing history, no longer needed."