开个玩笑,我将笔记本电脑的用户帐户命名为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:
当我的存储库设置明确说明我的意图时,为什么会继续这样做?我不想让乔恩(Jon)相信我的 代码!从命令行提交具有预期的结果。
答案 0 :(得分:5)
可能有多种发生方式。在深入探讨这些问题之前,我们需要涵盖适当的背景信息。还需要强调一个关键项:任何现有提交中的数据都不能更改,甚至不能更改。只要您的存储库中存在提交39c31f5aebe43cdddbe00432207e4bb2cc6a777e
,它就将继续具有相同的信息。 (请注意,这是您显示的提交的 parent 。您没有显示提交本身的实际哈希ID,因此我无法使用该ID。)
在非常特殊的Git-GUI(我从未使用过的git-gui.sh
情况下,它从source看起来好像有一个功能,其中使用“修改”来读取{{1 }}提交作者信息并进行复制。通常,当您选择“修改”(如上和以下所述,是一个白色谎言)时,应该这样做,而当不进行修改时,则不应这样做。与命令行HEAD
不同,在不保留作者的情况下,似乎没有Git-GUI旋钮可以进行修改。如果偶然将作者保留的内容应用于所有新的提交,那只是一个错误。
有关更多信息,请继续阅读。
每个提交都有一些与之关联的元数据。原始提交对象中有两个相关的元数据行,分别称为 author 和 committer 。从Git自身在Git存储库中的各种提交中可以看出,这两个通常(但不一定)是相同的。例如:
git commit
(我将$ 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>
替换为@
可能会减少垃圾邮件的收集)。但是:
请注意,两个字段中的每个字段实际上由三部分组成:全名,<尖括号>中的电子邮件地址和time-stamp-with-zone-offset。
使用$ 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]
进行新提交时,Git 通常将author和committer都设置为相同的三个字符串。但是许多Git命令将一些现有提交复制到新的和改进的替代品中。根据定义,新提交具有一个新的且不同的哈希ID,但应代替使用旧的ID。对于这些情况,Git通常会保留原始的 author 信息,并将您(现在)设置为 committer 。
作为参考,保存作者的提交复制命令是git commit
,带有git commit
或--amend
/ -c
选项; -C
;和git cherry-pick
。 git rebase
命令旨在将通过电子邮件发送的修补程序转换为提交:它除了输入 commit 外还需要其他输入,因此我们可以说它是作者保留的,但是随后我们必须定义什么我们是指 author 。在这种情况下,git am
通过解析邮箱格式的消息来猜测作者信息。
只有一个基础的Git命令git am
,其他命令已使用或已内置在其中。实际上,这将构建包含以上元数据的提交对象。可以采用各种指令来分别设置每个字段。如果未设置某些字段,则git commit-tree
可以从某处获取默认值。
由于作者和提交者分别由六个部分(名称,电子邮件地址和时间戳)组成,因此有六个地方可以获取特定的指令,而很多地方(这次没有六个地方)可以获取默认指令。首先,让我们列举一下主要的六个。
git commit-tree
从{em>环境变量中获取这六个项目,而不是采用命令行选项,如the documentation中所述:
git commit-tree
如果您设置了这些变量的任何一个或全部,则将设置将用于所有后续新提交的值(直到您取消设置变量或与此相关的会话环境到期,则未设置变量。)
如果没有,那么文档继续说:
如果未设置(某些)环境变量,则 信息来自配置项user.name和 user.email,或者(如果不存在)环境变量EMAIL,或者,如果 未设置,系统用户名和用于传出的主机名 邮件(取自
GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE
,然后退回到完全合格的邮件 该文件不存在时的主机名)。
这是一个谎言,因为实际的代码路径取决于编译时选项,因此不同的Git安装可以具有不同的自定义默认值。但是总体的总体思路是正确的:如果您尚未使用各个环境变量覆盖一个或两个,那么Git将首先对作者和提交者使用/etc/mailname
和user.name
设置。
当然,默认时间戳只是您自己计算机上当前时间的主意。相对较新的user.email
设置告诉现代Git不要在user.useConfigOnly
和/或user.name
进行猜测。在旧版本的Git中,Git不会猜测:如果未设置它们,user.email
和git commit-tree
只会失败并显示一条错误消息,表明它不知道您是谁。
git commit
前端命令还使用git commit
和--author
作为参数。这些参数可以指定在新提交中使用的用户名,电子邮件地址和/或时间戳。 --date
通过在提交操作期间设置git commit
变量来有效地实现这些目的。
将GIT_AUTHOR_*
前端与git commit
标志一起使用时-尽管它的名字,实际上并没有更改提交;它只是使新的人使用代替当前的人,而这意味着所有的含义— --amend
标志告诉前端不要保留原始提交的作者信息。
如果 new 提交获得了错误的作者,而获得了正确的提交者,则必须是以下两种情况之一:
您正在使用--reset-author
。停止!
您的环境中已设置--author
和GIT_AUTHOR_NAME
。停止设置它们!
如果您有一些现有的提交,并且您正尝试通过GIT_AUTHOR_EMAIL
替换为新的和改进的提交,但是它保留了其作者设置,只需添加git commit --amend
。当然,这只能从命令行使用。如果您使用的是其他产品,请查看是否有类似的选择。
如果某些现有提交的作者有误,您将被困在那。您可以将现有的不太好的提交复制到新的和改进的提交中,并尝试说服拥有该相同存储库副本(克隆)的其他所有人来使用新的和改进的提交而不是旧的。 的难易程度显然取决于其他用户的顽固程度以及提交的位置。
使用--reset-author
可以很容易地将位于分支顶端而不是其他分支上的提交替换掉。再次提交历史记录更加困难:您可以使用交互式变基或者git commit --amend
,或者在特别难看的情况下使用git replace
来替换它们(有时结合使用这些技术)。对较早提交的任何“更改”必然会通过设计在其所有后代中逐渐蔓延, 1 ,因此这种更改可能会造成破坏。但是,如果它正在“改变”(实际上是在取代)没有其他人见过的历史,那就足够安全了。
1 “错误”提交的直接子级包含错误提交的父哈希ID。因此,要让孩子们参考替代品,我们也必须替换孩子们。这意味着我们必须替换其他们的子级,依此类推,一直到每个受影响分支的尖端提交。