如何在提交时使用钩子更改作者电子邮件

5

问题已经说得很清楚了。

我希望通过使用自己的别名来混淆提交中用户真实电子邮件地址,从而为我的用户提供一些隐私保护。是否有一个钩子可以帮助我做到这一点?

3个回答

7

您可以让他们在本地版本库中更改 user.email 属性即可。

git config user.email email@server.com

1
如果他们希望隐藏他们的电子邮件,就让他们自己进行混淆。 - Cascabel

6
无论发生什么事情,如果您更改了某个提交中的任何内容——甚至是用户名和/或电子邮件中的单个字符——您都会得到一个新的、不同的提交。(这是因为提交 ID 由提交内容的加密校验和组成。所以,如果您能够破解密码学,就可以得出两个不同的提交,它们将具有相同的 ID。但那样您就完全破坏了 git,并且可能还获得了图灵奖或诺贝尔奖。:-) )
你在另一个答案的评论中链接的“工作钩子”可能是你最好的选择。这个问题归结为一件事:你不能对已发布的提交进行任何更改(否则会给那些使用该发布物的人带来问题),但是只要“知道自己在做什么”,你可以对私有提交进行任何更改。使用git commit --amend --author "$user <$email>" -C HEAD,在每个提交进入您的副本时,可以保证您用一个新的、稍微不同的未发布提交替换一个未发布提交。(我假设您已经将此放在后提交钩子中。)
我不确定您不满意的是哪部分,也许是[ -n "$richo_git_rewrite" ] && exit 0吗?这是一种合理聪明的检测递归的方法。另一种方法是跳过递归检测,而是将提交中现有的用户和电子邮件与所需的用户和电子邮件进行比较。
以下是一个执行此操作的脚本(除了我使用的环境变量SWITCHY=true来进行测试):
#! /bin/sh
# first, pick which git config variables to get
if ${SWITCHY-false}; then
    config=user.work
else
    config=user
fi
# next, find out if they're set
can_rewrite=false
target_author=$(git config --get $config.name) &&
    target_email=$(git config --get $config.email) &&
    can_rewrite=true
# If they ARE set, we can "rewrite" (replace) the commit;
# if not, we can't.  Just because we can, though, does not
# mean we should.  Find out if the current author and email
# differ from the desired ones.
if $can_rewrite; then
    current_author=$(git log --pretty=format:%an HEAD -n 1)
    current_email=$(git log --pretty=format:%ae HEAD -n 1)
    if [ "$current_author" != "$target_author" -o \
          "$current_email" != "$target_email" ]; then
        # may want --allow-empty here, if you're allowing empty commits
        # at all, otherwise empty ones don't get the rewrite done
        git commit --amend --author "$target_author <$target_email>" -C HEAD
    fi
fi

注意:您需要在“hooks/post-merge”中设置相同的钩子,以获取具有更新名称和电子邮件的修订合并。当然,您可以简化钩子(不需要实际的can_rewrite变量,只需使用“&&”进行两个git config get操作,并继续使用另一个“&&”)。还有,除了用户与用户工作之外,可能还有更多的用户与用户ModeA vs用户ModeB等,您可以根据喜欢的任何测试(环境变量,命令的存在或缺失等)来驱动它。好的,根据评论,这是一个预提交钩子。不幸的是,它无法与“git merge”一起使用(预提交钩子运行并抱怨,然后合并提交进入)。
#! /bin/sh
fatal()
{
    echo "$@" 1>&2
    exit 1
}
# pick which git config variables to get
if ${SWITCHY-false}; then
    config=user.work
else
    config=user
fi
# tn, te = target author name/email
# an, ae = what git will use for author name/email
tn=$(git config --get $config.name) || exit 0
te=$(git config --get $config.email) || exit 0

an=${GIT_AUTHOR_NAME-$(git config --get user.name)} ||
    fatal "no author name set"
ae=${GIT_AUTHOR_EMAIL-$(git config --get user.email)} ||
    fatal "no author email set"
[ "$an" = "$tn" -a "$ae" = "$te" ] ||
    fatal "git will use author $an <$ae>
but you want them as $tn <$te>
fix your environment variables and try again"

您可以将这个预提交挂钩与后合并的重写提交挂钩( :-) )相结合。我没有尝试过冲突的提交,但预提交挂钩可能会捕获需要您自己提交的冲突合并。
值得注意的是,这个预提交挂钩不会查看工作树或索引,因此它没有通常的"检查工作树但提交索引"缺陷。

我的问题与“提交、测试是否需要重写、重写”的模式有关。我希望一开始就将提交正确的用户写出来,我的工作流涉及大量的变基,我敢打赌,现在我所拥有的东西迟早会咬我一口。经过进一步调查后,我认为我将不得不在 git 中实现它,并乞求合并到下一个版本中。谢谢! - richo
你不能完全这样做,但如果你愿意,你可以有一个pre-commit hook来检查"git将设置什么"是否是"我想要设置的"。让过滤器抓取$GIT_AUTHOR_NAME$GIT_AUTHOR_EMAIL,如果它们没有设置,则使用git config get,然后将它们(类似于我的示例post-commit hook)与"desired"值进行比较。如果它们不匹配,则退出1,停止提交。(当然,将其放在几乎所有的pre-everything上。) - torek
我没有考虑过那个选项,如果它是错误的,就退出。谢谢! - richo
嗯...我尝试通过在pre-commit钩子中使用“git config user.name”设置user.name,但这对于当前提交无效。下一个提交的名称将改变。我猜GIT在一开始读取配置,然后运行pre-commit钩子,然后执行其他操作。设置环境变量GIT_AUTHOR_NAME也没有什么用。 - lumbric
@lumbric:这就是为什么原始的hack会创建一个新的提交(请参见https://gist.github.com/richo/1d7b0437ebdaa9834b61)。是的,在钩子中设置环境变量不会有任何作用,因为环境变量是“向下”传递的(从父进程到子进程),而且永远不会向上传递:如果Git将钩子作为子进程运行,则子进程无法影响父Git进程。 - torek

1

http://progit.org/book/ch6-4.html 解释了如何重写历史记录。在底部附近,有这个命令

git filter-branch --commit-filter '
    if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
    then
            GIT_AUTHOR_NAME="Scott Chacon";
            GIT_AUTHOR_EMAIL="schacon@example.com";
            git commit-tree "$@";
    else
            git commit-tree "$@";
    fi' HEAD

这个命令会将所有提交者从 schacon@localhost 改为 schacon@example.com

注意:这将改变所有从最早的电子邮件更改开始的提交 ID。


我其实不想重写历史(特别是因为我喜欢白天推送)。在提交时,我只想有一个钩子来检查一些环境并做出决定,将哪个作者放在那里。 - richo
你将要重写历史,因为你想要更改作者的提交已经在你的过去。filter-branch命令只更改原始电子邮件的提交,因此您不会更改已经更正的历史部分。 - plaugg
重点是,如果我在自己的时间里编写它们,那么它们就不是“糟糕”的提交。按电子邮件过滤不是正确的方法。我有一个工作钩子,但我对它不满意。 - richo
此外,关键是在完美的世界中,当我提交它们时,它们会被更改。目前,在我工作时设置GIT_AUTHOR_NAME、GIT_AUTHOR_EMAIL是一个权宜之计,但可以让我应付过去。 - richo
我要如何只修改即将推送的提交? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接