git reset - hard HEAD~1和git revert HEAD之间有什么相似之处和区别?

问题描述 投票:0回答:3

我试图绕过这个。

据我所知,“git reset --hard HEAD~1”将删除最后一次提交,并且“git log”中将不会显示该提交。

并且“git revert HEAD”将把我放在nano中,我可以在其中编辑提交消息,并且还将恢复保存为“git log”中的新提交

我对吗?

git head revert
3个回答
2
投票

实际上,git revert将生成一个新的提交,取消另一个给定提交的效果,重放其变更集的负面版本。特别是,git revert不会像mercurial那样做。

您可以将其视为取消“维基百科”:将某些内容视为修改,就像其他内容一样,并且可以过时。

然而,git reset会将分支指针带回给定位置。根据您指定的参数,--soft--mixed(默认)或--hard,git将分别仅修改分支指针,分支和索引的状态,或分支,索引和工作目录内容。因此,这完全摆脱了分支的尖端,但命令可以超越这个唯一的情况。

请注意,即使您使用git reset --hard或其他内容取消引用提交,此提交仍将保留在对象集合中,直到运行垃圾收集器并且仅在它足够老(通常为三个月)时才被丢弃。

所以请记住,如果你偶然做到了这一点,那么如果你不等太久,总会有办法恢复你的提交。


1
投票

你是对的......他们可能会根据工作树的样子给你相同的“最终结果”......但是项目的结果历史却截然不同......如果你问我,如果你只是注意到不需要最后一次提交,只需将其从历史记录中删除(git reset --hard)。除非有一个主要原因不这样做。有人说,一旦它发布,它就不应该被收回......我的看法是,任何经验丰富的git用户都知道如何使用--onto指定修改内容并指定要跳过的修订版,所以即使它已经发布,你应该只是删除它(让其他开发人员知道你做了什么)....但这只是我的假设/意见。


1
投票

What's the difference between Git Revert, Checkout and Reset?看到其他优秀(和重复)的问答但我们应该从更基本的东西开始。

Why do we use version control?

版本控制系统的目的是保存所有曾经完成的所有事情。好吧,除非它不是:有时目的是保存一些已经完成的事情,有些事情需要一段时间,有些事情需要很短的时间。

Git保存这些的方式是完整的快照,我们称之为提交,它还带有一些关于提交的额外信息,我们称之为元数据。元数据包括提交者的姓名和电子邮件地址,以便我们可以询问他们为什么提交,以及日志消息,这样他们就可以告诉我们他们为什么要这样做而不必打扰他们。 Git中的元数据还包括先前或父提交的概念。通过将父快照与此特定快照进行比较,Git可以告诉我们进行提交的人员发生了什么变化。

考虑到这一点,我们可以看看这三个Git动词(我也将投入git checkout):

git checkout is to obtain something done at some time

我们使用git checkout来获得一个特定的提交。提交是某人在某个时间制作的快照。据推测,快照对于某些目的来说是好的。无论我们的下一个目标是什么,我们都使用git checkout获取该快照,就像当时制作的快照一样。

在Git中,作为使用git checkout和分支名称的副作用,我们现在准备做新的工作。但我们也可以使用带有原始提交哈希的git checkout,之后新的提交......好吧,有点棘手。 (他们仍然可以,但是Git称之为独立的HEAD模式,你可能不想使用它,直到你对Git了解更多。)

例如,git checkout mastermaster上获取最新提交的原因是每次我们在master上进行新的提交时,Git会自动更新我们的名字master,这意味着它是最新的提交。最新的提交会记住它的父级,它曾经是最新的。第二次一次提交会记住它的父级,这也是一次性提交不存在时的最新版本,依此类推。

这意味着名称master真的只是找到最后一次提交,我们从中发现每个提交:

... <-F <-G <-H   <--master

其中每个大写字母代表一个提交哈希ID。我们说每个提交指向其父级,master指向最新的提交。

git revert is to back out a bad commit

鉴于每个提交记录其父级,并且Git因此可以告诉我们提交该提交的人改变了什么,我们总是可以让Git撤消其他人的改变(甚至是我们自己的改变)。我们选择一个提交,将其视为一个变化 - 这是Git在我们使用git log -pgit show时向我们展示的方式 - 并发现,嘿,这种变化是错误的。应该撤销或“恢复”这一变化.1


1这里的动词还原是一个糟糕的选择。 most common English language definition几乎总是跟随辅助词,如同回复,它意味着返回到前状态。但退出一些变化并不一定会让我们回到原来的状态!如果我们退出最近的更改,我们只会返回到之前的状态。

其他版本控制系统使用动词退出,这是更好的。在任何情况下,当我们使用这个动词时,Git会进行一次新的提交,保存一个新的快照,就像我们之前的结账一样,除了它有一个人的更改退出。好吧,就是说,除非存在合并冲突,否则Git会进行此提交,但我们会忽略这种可能性。


git reset is ... well, muddled, but we can use it to throw away commits

Git的重置动词非常复杂。在一种特定的形式中,它最多可以做三件事。与其他形式一样,它做其他事情。你问过的那个,git reset --hard HEAD~1,告诉Git:

  1. 使当前分支名称,无论是什么,指向当前提交的父级。
  2. 擦除当前索引 - 我们在这里没有描述,但索引,暂存区域,甚至缓存实际上只是Git中同一事物的三个名称 - 并从步骤1中选择的提交填充它。
  3. 在重置之前删除与索引一起使用的所有工作树文件,并将它们替换为从步骤1中选择的提交中提取的副本,并在步骤2中复制到索引中。

所以如果我们有:

... <-F <-G <-H   <--master

我们改名为master,指向G,将提交H推开:

            H
           /
... <-F <-G   <-- master

散列为H的提交现在实际上已经丢失,好像它从未被制作过一样。它仍然在存储库中,它变得很难找到。及时,如果我们不采取任何其他步骤来保护它,提交H将真的消失。

Remember our purpose for commits

我们想要提交,以便他们保存所有曾经做过的所有事情。但有时候,我们所做的事情,也许,使提交H - 是一个错误:

...--F--G--H--I--J--K--L   <-- master

如果我们前一段时间制作了H并且它都是这样嵌入的,那​​么很难删除,因为每次提交都被完全冻结,所以为了删除H,我们必须将I复制到一个新的不同的提交I',其中G作为其父级,然后将J复制到以I为父级的新提交,依此类推:

          H--I--J--K
         /
...--F--G--I'-J'-K'  <-- master

这里更容易恢复H,添加一个新的提交,撤消我们在H中改变的任何内容。提交I通过K保持不变 - 可能略有破碎,但这就是他们一直以来的方式 - 现在我们有一个新的提交L撤消我们在H所做的事情:

...--F--G--H--I--J--K--L   <-- master

但如果H是最近的,我们可以完全使用git reset --hard删除它。我们会忘记我们犯了这个错误。没有必要告诉其他人。

© www.soinside.com 2019 - 2024. All rights reserved.