为什么不使用git重置?

为什么不使用git重置?,git,azure-devops,Git,Azure Devops,git的Visual Studio团队服务文档: 包含不使用git reset的警告 不要在与他人共享的分支上使用重置。请改用“还原” 我的问题是为什么?Git reset不会更改历史记录,而revert会更改历史记录。 不在共享分支上使用git reset的建议是什么 Git重置不会更改历史记录 这在某种程度上是正确的,但在某种程度上也是严重错误的。在Git中,历史记录是提交的集合。因此,创建新提交的git revert将添加到历史记录中。同时,git reset是一个复杂的命令;我们在这里只

git的Visual Studio团队服务文档: 包含不使用git reset的警告

不要在与他人共享的分支上使用重置。请改用“还原”

我的问题是为什么?Git reset不会更改历史记录,而revert会更改历史记录。 不在共享分支上使用git reset的建议是什么

Git重置不会更改历史记录

这在某种程度上是正确的,但在某种程度上也是严重错误的。在Git中,历史记录是提交的集合。因此,创建新提交的git revert将添加到历史记录中。同时,git reset是一个复杂的命令;我们在这里只看它使用分支名称作为提交指针所采取的操作对存储库中实际存储的提交集没有直接影响。这意味着,正如您所说,git reset不会更改历史记录。但是

这里的微妙之处在于如何在GIt存储库中找到历史。如果我们查看单个提交,我们会发现它有:

保存的快照包含树对象哈希ID; 一组父对象,包括提交对象哈希ID的列表; 作者和提交人都是姓名电子邮件时间戳三元组;和 日志消息:提交者输入的任何内容。 第二项,父散列列表,是让我们构建历史的东西——提交DAG,提交的有向无环图。给定一个提交,我们会找到它的父级或父级。假设我们有一个包含三个提交的小型存储库,其散列ID由一些奇怪的奇迹aaaaaaa…、bbbbbbb…、和ccccccc…,以及:

CCCCCCCCCCC。。。有母公司BBBBBBBB。。。; bbbbbbbb。。。有母公司AAAAAAAA。。。; AAAAAAAA。。。没有父对象:它是根提交。 为了方便起见,让我们将哈希值缩短为一个大写字母。这意味着我们可以将图表绘制为:

A <-B <-C
但是:我们首先是如何找到C的?我们从C中找到了B,从B中找到了A,但我们是如何找到C的

Git对此的回答是,我们通过读取像master.1这样的分支名称来找到C。名称master存储哈希ID CCCCC。。。在里面

如果我们使用git reset将存储在master中的hash ID更改为bbb。。。取而代之的是,我们失去了C的ID。就好像C从来都不存在一样,现在的图形是:

A--B   <-- master
提交C已消失,从历史中删除

Git秘密保存它,将C的ID保存在master的reflog中,也保存在HEAD的reflog中。默认情况下,这个reflog条目会保留30天,尽管它是可配置的,不仅可以配置多长时间,还可以配置reflog是否存在。不过,一旦reflog条目过期,提交将不受保护,最终的git gc将在存储库中找到提交C,发现所有分支和其他此类名称都无法访问它,并从存储库中删除C,现在它真的消失了

因此git reset可以更改可访问的历史记录,并且最终在reflog到期后意味着某些历史记录—一个或多个提交—将完全消失

使用git revert将新提交添加到历史记录中,使当前分支名称指向新添加的提交。新提交通过其父ID指向上一个分支提示。因此,这不会破坏任何现有的历史,它只会添加新的历史—新的提交

Git通常是为添加新提交而构建的。Git使这变得简单方便。它不是为删除现有提交而构建的;一旦提交逃离了您自己的本地存储库,Git会让这变得非常痛苦和困难。在这之前,这仍然是相当容易的,因为回流通常也相当安全

1更准确地说,Git通过引用找到它们。分支名称是一种特殊的引用形式。标记名是另一个,远程跟踪名(如origin/master)是第三个。Git中有六个左右的内置的众所周知的引用名称空间:branchs refs/heads/*、tags refs/tags/*、远程跟踪名称也称为远程跟踪分支,但这不是一个好名称。这些名称在refs/remotes/*、notes refs/notes/*中表示Git notes、replacements refs/replace/*中表示Git replace,而refs/stash则表示隐藏


请注意,Mercurial在其他方面与Git有很多相似之处,对于如何找到分支提示提交,它有一个非常不同的答案。在Mercurial中,查找这些提交不需要任何名称。

Git reset不会更改历史记录,revert会更改历史记录。-也不会更改历史记录。您通常不希望更改公共提交或重置分支-签出分支的任何人都需要进行相同的更改以修复其存储库。重置分支上的更改公共提交,revert添加新提交以反转更改。@DavidBold,关键是,如果更改被推送到共享存储库,请小心使用git Reset。如果您正在重置的更改没有被推送,那么您可以全天使用git reset,而不会影响其他人。git reset会将头部重置为指定的提交,并在指定的提交之后放弃以后的提交
evert将保留所有原始提交,并创建一个新的提交,以恢复指定提交的更改。所以实际上git reset会改变历史,git revert不会。Notes和replace?我从没听说过这些。了解和学习很好。
A--B   <-- master