Git Revert,Checkout和Reset之间有什么区别?

时间:2011-12-02 13:37:49

标签: git git-checkout git-reset git-revert

我正在尝试学习如何将文件和项目恢复或回滚到先前状态,并且不了解git revertcheckoutreset之间的区别。为什么有3个不同的命令看似相同的目的,什么时候应该选择其中一个呢?

7 个答案:

答案 0 :(得分:393)

这三个命令的用途完全不同。他们甚至没有相似之处。

git revert

此命令创建一个新提交,撤消先前提交的更改。此命令将新的历史记录添加到项目中(它不会修改现有历史记录)。

git checkout

此命令检出存储库中的内容并将其放入工作树中。它还可以具有其他效果,具体取决于命令的调用方式。例如,它还可以更改您当前正在处理的分支。此命令不会对历史记录进行任何更改。

git reset

这个命令有点复杂。它实际上做了几件不同的事情,具体取决于它是如何被调用的。它修改了索引(所谓的“临时区域”)。或者它改变了当前指向分支头的提交。此命令可能会更改现有历史记录(通过更改分支引用的提交)。

使用这些命令

如果在项目的历史记录中某处进行了提交,并且您后来认为提交错误且不应该完成,则git revert是该工作的工具。它将撤消错误提交引入的更改,在历史记录中记录“撤消”。

如果您已在工作树中修改了文件,但尚未提交更改,则可以使用git checkout签出文件的新存储库副本。

如果您已提交,但尚未与其他任何人共享,并且您认为自己不想要它,那么您可以使用git reset重写历史记录,使其看起来好像从未做了那个提交。

这些只是一些可能的使用场景。在某些情况下还有其他命令可用,而上述三个命令也有其他用途。

答案 1 :(得分:27)

  • git revert用于撤消先前的提交。在git中,您无法更改或删除先前的提交。 (实际上你可以,但它可能会导致问题。)因此,revert不是编辑先前的提交,而是引入了一个新的提交,它反转了之前的提交。
  • git reset用于撤消尚未进行调整的工作目录中的更改。
  • git checkout用于将文件从其他提交复制到当前工作树。它不会自动提交文件。

答案 2 :(得分:18)

  • git checkout修改您的工作树
  • git reset修改您所指向的分支的引用,
  • git revert添加撤消更改的提交。

答案 3 :(得分:17)

让我们说你有提交:

C
B
A

git revert B,将创建撤消B中的更改的提交。

git revert A,会创建一个撤消A中的更改的提交,但不会触及B

中的更改

请注意,如果B中的更改取决于A中的更改,则无法恢复A

git reset --soft A,将更改提交历史记录和存储库;登台和工作目录仍处于C状态。

git reset --mixed A,将更改提交历史记录,存储库和暂存;工作目录仍处于C状态。

git reset --hard A,将更改提交历史记录,存储库,登台和工作目录;你将完全回到A状态。

答案 4 :(得分:6)

重置 - 在提交级别,重置是一种将分支的提示移动到另一个提交的方法。这可以用于从当前分支中删除提交。

还原 - 通过创建新提交来还原撤消提交。这是撤消更改的安全方法,因为它无法重写提交历史记录。 将此与git reset进行对比,这会改变现有的提交历史记录。因此,应使用git revert撤消公共分支上的更改,并且应保留git reset以撤消对专用分支的更改。

您可以查看此链接 - Reset, Checkout and Revert

答案 5 :(得分:4)

如果您破坏了树但未提交代码,则可以使用git reset,如果您只想恢复一个文件,则可以使用git checkout

如果您打破了树并提交了代码,则可以使用git revert HEAD

http://book.git-scm.com/4_undoing_in_git_-_reset,_checkout_and_revert.html

答案 6 :(得分:0)

我会尝试在问题中添加 git restore 来回答

假设您有以下提交历史记录:

D
C
B
A

git revert

进行反向提交git revert commit-hash 不会更改您的提交历史记录,而是进行新的提交,以还原作为提交一部分提交的更改

git revert B,将创建一个撤销 B 中的更改的提交。 Git 历史记录将是

reverse-B
D
C
B
A

如果提交 C 依赖于提交 B git revert B 将导致合并冲突

建议:git revert 旨在恢复公开提交。所有其他撤消更改的方法都有可能改变提交历史,这可能会导致项目的其他参与者出现问题。 git revert 是在不干预提交历史的情况下撤消更改的方法

git restore

git restore 帮助您将文件从 commit/staging-area 移动到 worktree/staging-area

命令是 git restore [--source=commit-hash] [--worktree] [--staged] [--] 文件

  • --worktree 表示恢复到工作树
  • --staged 表示恢复到--staged。
  • 同时指定 --staged 和 --worktree 以从 --source 恢复到工作树和暂存区
  • 当指定 --source 时,恢复总是来自源
  • 当未指定 --source 并提供 --staged 时,恢复来自 HEAD
  • 当 --source 和 --staged 都没有指定时,恢复是从暂存区到工作树

建议 - 使用 git restore 将文件从

  • 将 blob 提交到暂存区和/或工作树。
  • 暂存区到工作树

git checkout commit-hash

请注意,虽然 git checkout 的文件级实现可以帮助您将文件从提交拉入暂存区或工作树,但我们不会讨论它,因为现在这是 {{ 1}} 命令,它的设计目的是使 git restore 命令保持一致。

  • git checkout - 头部被移动到指向提交哈希。总是让你处于一种超然的头脑状态。
  • git checkout commit-hash - Head 被移动到指向指定的分支,现在不是处于分离状态

建议:使用git checkout branch查看树周围的各种提交并在分支之间切换

git checkout

  • 您处于分离的头部状态 - git reset commit-hash 会将 git reset 移动到指定的 HEAD。就像commit-hash
  • 您没有处于分离的头部状态 - git checkout commit-hash 会将整个 git reset 移动到指定的 (HEAD -> branch)。如果这导致 commit-hash 没有分支在前面,那么这些提交将从 git 历史记录中删除

commits 也有三个选项 git reset--soft--mixed。将 --hard 移动到不同的提交后,您的工作树和索引(暂存区)应该是什么样子?

  • HEAD - 工作树和索引都与您移动到的新提交中的文件相匹配
  • --hard(默认)- 工作树保持您运行 --mixed 之前的状态,并且索引与您移动到的新提交中的文件相匹配
  • git reset - Worktree 和 Index 都保持您运行前的状态 --soft

git reset 大多数情况下可以使用 git resetgit checkoutgit branch -D 的组合进行复制,除了没有简单的方法来控制工作树的内容和stagin-area 也是如此,除非你不使用 git reset

建议:你是否做了一些不应该做的提交并且没有将更改推送到公共存储库?最好就好像这些提交从未存在过一样吗?使用git restore。如果您已将更改推送到公共存储库,那么如前所述,您希望使用 git reset