git reset和git revert的区别是什么?
首先
这是船井总研数字部门的OSW。由于需求暂搁,我进行了根据我们业务使用的远程代码库的一个分支进行还原的操作。在操作过程中,由于git revet和git reset混乱不清,我将进行整理。
結論 – 从中国的本土角度出发进行翻译,只需要提供一种选项 :
总结
这两者在恢复提交状态上是相同的,但根据下面的描述似乎有如下的区别。(用途是我的主观看法)
如果重置(reset)的话,版本记录会回到该时刻,因此从回滚的时刻开始,后续的版本记录将不再可见。而还原(revert)会将存储库状态回滚到该时刻,但是版本记录保持不变,并且会添加一个新的“回滚”提交。
在上述的情况下,如果尝试将进行过回滚(reset)的存储库进行推送,由于它变得比远程存储库更旧,所以必须使用-f选项进行强制执行才能进行推送。另一方面,撤销(revert)会保留提交历史记录,并将一个新的“回滚”提交堆叠在上面,因此可以直接推送到远程+α状态。
忽略push的问题,通过reset后加入一个空提交并在提交消息中补充revert的信息是可行的,但是由于已重置的提交历史会消失,因此将要回滚的所有操作的提交都进行全面描述可能会很困难。
重置(reset)似乎是在本地存储库出错时使用的解决方法。在创建成果物的过程中,“撤销不必要的操作”这样的提交(revert)在历史记录中保留下来是没有意义的,而且如果推送(push)了之后,远程存储库的提交历史可能会变得混乱不堪。
学习环境 –
-
- Windows 11 (WSL2 Ubuntu)
-
- VSCode 1.76.2
- Git 2.34.1
验证环境
为了简化对话,我会在本地仓库中创建下面的README,并对其进行修改和验证。
文件会逐渐加入差异,但基本上只会添加或删除标题。
- 作成するREADME
## A
A
A
## B
B
B
## C
C
C

基礎知識
在指定提交历史时,会使用HEAD、@以及加上”~”、”^”等符号,这些符号的含义在这篇文章中详细解释。
然而,根据合并的情况,似乎使用”~”和”^”会有不同的行为。
首先,git reset是什么
我认为根据不同的选项,重置的操作方式会有所变化,不过这篇文章非常易懂。
首先,git revert是什么意思?
revert的意思似乎是回復到原來的習慣或狀態。
返回原来的习惯、状态等。
在git中,回滚(revert)是将存储库恢复到特定提交状态,并叠加一个指示已回滚操作的提交。
在这种情况下,与重置不同,提交历史仍然保留,新的更改会在其上面叠加。(在Git中,恢复操作被称为”打消”。)
试着还原最近的提交
首先,我们尝试撤销在验证环境中创建的存储库中添加”标题C”的最新提交。
然后,标题C被删除(保留添加标题C的提交记录),并添加了一个表明进行revert的提交记录。

$ git revert @
# コミットメッセージを編集し、保存して完了
- revert後のREADME
## A
A
A
## B
B
B

尝试还原连续的提交
下面是一个可能的中文翻译版本:
接下来我们将尝试撤销连续的提交。由于之前已经撤销过一次,所以我们将恢复到在验证环境中创建的状态,回到撤销之前的状态。
# コミットのハッシュ値を確認
$ git log --oneline
f20946b (HEAD -> revert) Revert "追加: 見出しC"
37cbc2e (master) 追加: 見出しC
11acd6f 追加: 見出しB
4ea1d6d 追加: 見出しA
c9c6945 initial commit
# revert前の「37cbc2e」に戻す
$ git reset --hard 37cbc2e

我們將回復連續的提交。在這裡,我們將回復標題C、B。
如果要撤销连续的提交,可以使用”…”将当前提交与要撤销的提交连接起来,并相对描述。因为会撤销到指定右边提交的前一个提交,所以会恢复到指定右边提交的状态。
# 現在のコミットから4個前のコミットまでをrevertする
$ git revert @...@~5
# 4個分のコミットメッセージを編集、保存して完了
实际上运行命令后,会打开修改四次提交消息的界面,像上面的示例一样。如果数量过多会很麻烦,所以可以通过指定–no-edit来跳过编辑消息的步骤。
$ git revert --no-edit @...@~2

不要在回退后自动提交
如果以默认设置运行revert,则仅会添加一个表示”revert所涉及的提交”的提交。通过指定-n选项,即使进行了revert操作,也不会自动提交。
首先将环境恢复到验证之前的状态。
$ git reset --hard 37cbc2e
$ git revert -n @...@~2
$ git status
On branch revert
You are currently reverting commit 11acd6f.
(all conflicts fixed: run "git revert --continue")
(use "git revert --skip" to skip this patch)
(use "git revert --abort" to cancel the revert operation)
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: README.md

若指定了“-n”,首先会通过revert将提交的状态恢复。这时,工作内容将会恢复并处于已添加的状态(git add)。因此,“已回滚”的多个提交不会自动堆叠,但可以手动提交它们以将这些多个提交合并为一个。
为了避免日后不清楚是否有还原过的提交,建议至少存在一个还原过的提交,以便能够明确地知道该事项的进行情况。
撤销特定的提交
也可以通过指定特定的哈希值进行还原。但是需要注意的是,被还原的文件不仅仅是特定提交的更改被撤销了,而是完全回到了那个时间点的状态。
另外,通过还原操作所提交的提交将只包括“指定的提交”。
我会在已创建的README文件中添加D、E和F标题,并检查下一个状态。
## A
A
A
## E
E
E
## F
F
F
## D
D
D
## B
B
B
## C
C
C

$ git revert --no-edit 11acd6f

确认从标题B到标题F的所有内容都已被取消。它似乎与指定范围相同,但由于只有一个提交记录,如果想要明确地保留撤销历史,可能需要指定范围。
最后
在尝试之前,我认为撤销特定提交只会撤销“特定工作内容”,但后来发现并不是这样。
我认为通过这次学习,我们应该能够相当程度地减少“做糟糕了orz”的频率。幸运的是,事情还没有出现,因此即使发生了什么事,我们也可以冷静地处理。