为什么Git GUI会一直叫我Jon Skeet?

wiz*_*zz4 1 git author git-gui attribution

作为一个笑话,我将笔记本电脑的用户帐户命名为Jon Skeet.我已经配置了我的每个存储库选项来打电话给我wizzwizz4,但是当我查看我的提交时,我看到了这个:

Author: Jon Skeet <jon@myLaptop>  2018-12-21 22:07:11
Committer: wizzwizz4 <wizzwizz4@users.noreply.github.com>  2018-12-21 22:12:07
Parent: 39c31f5aebe43cdddbe00432207e4bb2cc6a777e (Initial commit)
Branches: master
Follows: 
Precedes: 
Run Code Online (Sandbox Code Playgroud)

当我的存储库设置清楚地表明我的意图时,为什么它会继续这样做?我不希望Jon为我的代码获得荣誉!从命令行提交具有预期的结果.

tor*_*rek 5

有多种方法可以发生.在我们了解所有这些之前,我们需要提供适当的背景信息.值得强调的是一个关键项:任何现有提交中的数据都不能改变,甚至不能改变. 只要39c31f5aebe43cdddbe00432207e4bb2cc6a777e存储库中存在提交,它就会继续拥有相同的信息.(请注意,这是您显示的提交的父级.您没有显示提交本身的实际哈希ID,因此我无法使用该提交.)

在Git-GUI(git-gui.sh我从未使用过)的非常具体的情况下,它从源代码看起来好像有一个功能,使用"修改"读取HEAD提交的作者信息并复制它.当你选择"修改"(如上面和下面所说,是一个白色谎言)时,通常应该这样做,并且在不修改时不应该这样做.与命令行不同git commit,似乎没有Git-GUI旋钮进行修改而不保留作者.如果它意外地将作者保留应用于所有新提交,那只是一个错误.

更多信息请继续阅读.

背景

每个提交都有一些与之关联的元数据.原始提交对象中有两个相关的元数据行,称为作者提交者.这两个通常但不一定是相同的,正如Git本身的Git存储库中的各种提交可以看到的那样.例如:

$ git cat-file -p 5d826e972970a784bd7a7bdf587512510097b8c7
tree c790c47fe551d5ed812cfefdac243eb972c1fde3
parent b5796d9a3263b26a8ef32eeca76b3c1d62fcedc5
author Junio C Hamano <gitster pobox.com> 1544328981 +0900
committer Junio C Hamano <gitster pobox.com> 1544328981 +0900

Git 2.20

Signed-off-by: Junio C Hamano <gitster pobox.com>
Run Code Online (Sandbox Code Playgroud)

(我已经取代@ to possibly cut down on spam harvesting). But:

$ git cat-file -p 6fcbad87d476d7281832af843dd448c94673fbfc
tree aa05bc7af6e92f3db5d5d738adf0d0b1b3dd23b6
parent b00bf1c9a8dd5009d5102aef7af9e2b886b1e5ad
author Johannes Sixt <j6t kdbg.org> 1543858489 +0100
committer Junio C Hamano <gitster pobox.com> 1543891852 +0900

rebase docs: fix incorrect format of [... snip]
Run Code Online (Sandbox Code Playgroud)

Note that there are actually three parts to each of the two fields: full name, email address in <angle brackets>, and timestamp-with-zone-offset.

When you make a new commit using git commit,Git 通常将作者和提交者都设置为相同的三个字符串.但是许多Git命令将一些现有的提交复制到一个新的和改进的替换.根据定义,新提交具有新的和不同的哈希ID,但是用于代替旧的提交.对于这些情况,Git通常保留原始作者信息并将您(现在)设置为提交者.

作为参考,笔者保留提交-复制命令git commit与任一--amend-c/ -C选项; git cherry-pick; 和git rebase.该git am命令旨在将电子邮件修补程序转换为提交:它需要除了提交之外的其他内容作为其输入,因此我们可以说它是作者保留的,但是我们必须定义作者的意思.在这种情况下,git am通过解析邮箱格式的消息来猜测作者信息.

每个领域的机制

有一个基础Git命令,git commit-tree其他命令要么使用,要么内置于其中.这实际上构建了提交对象,其中包含上述元数据.可以采用各种指令单独设置每个字段.如果设置某个字段,则git commit-tree可以从某处获取默认值.

由于每个作者和提交者有六个部分名称,电子邮件地址和时间戳 - 有六个地方可以获得特定的指令,而且很多地方 - 这次不是六个! - 获得默认值.首先,让我们列举小学六年级.

而不是采用命令行选项,git commit-tree环境变量中获取这六个项目,如文档所述:

GIT_AUTHOR_NAME
GIT_AUTHOR_EMAIL
GIT_AUTHOR_DATE
GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL
GIT_COMMITTER_DATE
Run Code Online (Sandbox Code Playgroud)

如果您设置了这些变量中的任何一个或所有变量,那么它将设置将进入所有后续新提交的值(直到您取消设置变量或使用此环境的会话到期,取消设置变量).

如果没有,那么文档继续说:

如果未设置(某些)这些环境变量,则从配置项user.name和user.email获取信息,如果不存在,则获取环境变量EMAIL,或者,如果未设置,则系统用户用于传出邮件的名称和主机名(/etc/mailname当该文件不存在时,从完全限定的主机名获取并回退到完全限定的主机名).

这有点白色谎言,因为实际的代码路径取决于编译时选项,因此不同的Git安装可以有不同的自定义默认值.但总的总体思路是正确的:Git会使用user.nameuser.email设置第一,对于作者和提交者,如果你还没有覆盖的一个或两个与各种环境变量.

当然,默认时间戳只是您自己的计算机对当前时间的想法.相对较新的user.useConfigOnly设置告诉现代的Git不要猜测user.name和/或user.email.在旧版本的Git中,Git没有猜测:如果没有设置,git commit-tree并且git commit只是失败并显示错误消息,说它不知道你是谁.

git commit前端命令也需要--author--date作为参数.这些参数可以指定在新提交中使用的用户名,电子邮件地址和/或时间戳; git commit通过在提交操作的持续时间内设置GIT_AUTHOR_*变量来有效地实现这些.

当使用git commit带有--amend标志的前端时- 尽管它的名字,它实际上并没有改变提交; 它只是使用一个新的而不是当前的一个,所有这意味着 - --reset-author标志告诉前端不要保留原始提交的作者信息.

结论

如果新的提交正在获取错误的作者,而在获得正确的提交者时,必须满足以下两种情况之一:

  • 你正在使用--author.停止!

  • 您拥有GIT_AUTHOR_NAMEGIT_AUTHOR_EMAIL设置在您的环境中.停止设置它们!

如果您有一些现有的提交,并且您尝试使用新的改进的提交替换git commit --amend,但它保留其作者设置,只需添加--reset-author.当然,这仅适用于命令行.如果您正在使用其他内容,请查明它是否具有类似选项.

如果某些现有的提交有错误的作者,那么你就会坚持下去.您可以将现有的,不那么好的提交复制到新的和改进的提交中,并尝试说服其他拥有此相同存储库副本的人 - 克隆 - 来获取并使用新的和改进的提交而不是旧的.有多难将明显依赖于其他用户如何顽固的,而且在提交的.

提交在他们的分支的顶端,并且不在任何其他分支上,很容易更换,使用git commit --amend.历史上更进一步的回忆更加困难:你可以使用交互式rebase,或者git replace,或者,在特别丑陋的情况下git filter-branch,将它们交换掉(有时结合这些技术).对旧版提交的任何"改变"都必然会通过设计来影响其所有后代,1因此这种改变可能具有很大的破坏性.然而,如果它正在"改变" - 替换,真正的历史,没有人见过,它足够安全.


1 "错误"提交的直接子项包含错误提交的父哈希ID.因此,为了让孩子们参考替代品,我们也必须更换孩子.这意味着我们必须更换他们的孩子,依此类推,一直到每个受影响的分支的提示提交.