【问题标题】:What's the difference between Git Revert, Checkout and Reset?Git Revert、Checkout 和 Reset 有什么区别?
【发布时间】:2012-01-11 13:59:46
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    这三个命令的用途完全不同。它们甚至一点都不相似。

    git revert

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

    git checkout

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

    git reset

    这个命令有点复杂。根据调用方式,它实际上做了几件不同的事情。它修改索引(所谓的“暂存区”)。或者它会更改分支头当前指向的提交。此命令可能会更改现有历史记录(通过更改分支引用的提交)。

    使用这些命令

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

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

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

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

    【讨论】:

    • 所以这三个命令可以用来撤销一些工作,这意味着它们并没有那么“完全不同”。相同的概念,不同的上下文。
    • @BrunoSantos:烛台、铅管、匕首和绳索都可以用来杀人,但这并不意味着这些东西特别相似。
    • @Dan Mounlding - 实际上,git resetgit checkout 可以做同样的事情。说它们“甚至一点都不相似”不仅仅是夸大其词:它甚至都不是真的。这两个命令可以做很多不同的事情,其中​​一些完全重叠。示例:git reset --hardgit checkout -- . 将执行完全相同的操作。从逻辑上讲,git reset --hard <path>git checkout <path> 也应该做同样的事情——但是 git 会阻止你这样做。混淆这两个命令非常容易。
    • @DanGordon 我知道我们在这里可能只是意见不同。不过,我觉得我应该提供一些解释。你不能像git checkout <path> 那样做git reset --hard <path>,因为这两个命令做的事情完全不同。 git reset 告诉 Git 将 HEAD 移动到不同的提交。另一方面,git checkout 根本不要求 Git 对 HEAD 做任何事情。它只留下 HEAD 并仅签出一个文件。是的,您可以以具有相似效果的方式制作它们。但他们实际上的却完全不同。
    【解决方案2】:

    假设你有提交:

    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的状态。

    【讨论】:

    • 如此直观的答案.. 结帐怎么样
    • 请注意,如果 B 中的更改依赖于 A 中的更改,则无法恢复 A - 这是什么意思?请解释
    • 谢谢,我现在明白了还原和重置之间的主要区别。有许多相互矛盾的定义,它们被标记为正确,它们不是或至少是误导性的。这真的很不幸,因为这是版本控制的一个非常重要的部分,并且也可能真的损害一个人的项目/回购。
    【解决方案3】:
    • git revert 用于撤消先前的提交。在 git 中,您不能更改或删除较早的提交。 (实际上可以,但它可能会导致问题。)因此,revert 不是编辑之前的提交,而是引入了一个新的提交来反转之前的提交。
    • git reset 用于撤消工作目录中尚未提交的更改。
    • git checkout 用于将文件从其他提交复制到您当前的工作树。它不会自动提交文件。

    【讨论】:

    • 我相信你对“git reset”的看法是错误的。 “git reset”将您的 HEAD 重置为以前的提交之一,它不会重置您的工作目录。工作目录由“git checkout [filename]”“重置”
    • git reset --soft 仅重置 HEAD,git reset --hard 重置 HEAD 和您的工作目录。
    • git reset --mixed (默认): uncommit + unstage changes
    【解决方案4】:
    • git checkout 修改你的工作树,
    • git reset 修改你所在分支的引用,
    • git revert 添加撤销更改的提交。

    【讨论】:

    • git reset 不只是修改分支指向的提交,它还用于从索引中取消暂存文件,并且可以使用git reset --mixed修改工作副本(默认)。
    • git reset --soft:取消提交更改,更改暂存(索引)。 git reset --mixed(默认):取消提交+取消阶段更改,更改保留在工作树中。 git reset --hard: uncommit + unstage + delete 更改,什么都没有了。
    【解决方案5】:

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

    还原 - 还原通过创建新提交来撤消提交。这是撤消更改的安全方法,因为它没有机会重写提交历史记录。 将此与 git reset 进行对比,后者确实会改变现有的提交历史。出于这个原因,应该使用 git revert 来撤消公共分支上的更改,而 git reset 应该保留用于撤消私有分支上的更改。

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

    【讨论】:

      【解决方案6】:

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

      如果你破坏了树并提交了代码,你可以使用git revert HEAD

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

      【讨论】:

        【解决方案7】:

        我将尝试添加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 表示恢复到worktree
        • --staged 表示恢复到--staged。
        • 同时指定 --staged 和 --worktree 以从 --source 还原到工作树和暂存区域
        • 当指定 --source 时,总是从源恢复
        • 当未指定 --source 并且给出 --staged 时,恢复来自 HEAD
        • 如果既没有指定 --source 也没有指定 --staged 则从暂存区恢复到工作树

        建议 - 使用 git restore 将文件从

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

        git checkout commit-hash

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

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

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

        git reset commit-hash

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

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

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

        git reset 在大多数情况下可以使用git checkoutgit branch -Dgit restore 的组合来复制,除了没有简单的方法来控制工作树和暂存区的内容,除非你不要使用 git reset

        建议:您是否进行了一些不应该进行的提交并且没有将更改推送到公共 repo?最好只是让这些提交从未存在过?使用git reset。如果您已将更改推送到公共仓库,那么如前所述,您想使用git revert

        【讨论】:

          猜你喜欢
          • 2015-01-17
          • 2011-04-08
          • 2017-12-10
          • 2011-09-06
          • 2011-10-18
          • 2012-01-01
          • 1970-01-01
          • 2021-07-04
          相关资源
          最近更新 更多