代码之家  ›  专栏  ›  技术社区  ›  Bite code

用简单的英语,“git reset”是做什么的?

  •  615
  • Bite code  · 技术社区  · 15 年前

    我见过 interesting posts 解释关于 git reset .

    不幸的是,我读得越多,就越觉得我不完全理解它。我来自svn背景,git是一个全新的范例。我很容易变化无常,但git技术性更强。

    我想 Git复位 接近 hg revert ,但似乎有差异。

    那么到底是什么 Git复位 怎么办?请详细说明:

    • 选项 --hard , --soft --merge ;
    • 你用的奇怪符号 HEAD HEAD^ HEAD~1 ;
    • 具体的用例和工作流程;
    • 对工作副本的影响 以及你的全球压力水平。
    7 回复  |  直到 6 年前
        1
  •  917
  •   Cascabel    9 年前

    一般来说, git reset 其功能是获取当前分支并将其重置为指向其他位置,并可能将索引和工作树一起带来。更具体地说,如果您的主分支(当前已签出)是这样的:

    - A - B - C (HEAD, master)
    

    你知道你想让师父指向B,而不是C,你会用 git reset B 把它移到那里:

    - A - B (HEAD, master)      # - C is still here, but there's no branch pointing to it anymore
    

    题外话:这和结账不同。如果你跑 git checkout B ,你会得到这个:

    - A - B (HEAD) - C (master)
    

    你最终陷入了一种独立的精神状态。 HEAD ,工作树,索引全部匹配 B ,但主枝落在 C . 如果你做出新的承诺 D 在这一点上,你会得到这个,这可能不是你想要的:

    - A - B - C (master)
           \
            D (HEAD)
    

    请记住,reset不会进行提交,它只是更新一个分支(指向提交的指针)以指向另一个提交。剩下的只是索引和工作树的细节。

    用例

    我涵盖了 Git复位 在我对下一节中各种选项的描述中。它确实可以用于各种各样的事情;常见的线程是,所有这些都涉及重置分支、索引和/或工作树,以指向/匹配给定的提交。

    要小心的事情

    • --hard 会让你真的失去工作。它修改你的工作树。

    • git reset [options] commit 可能会导致你失去承诺。在上面的玩具例子中,我们失去了承诺 C . 它还在回购协议中,你可以通过查看 git reflog show HEAD git reflog show master ,但实际上再也无法从任何分支访问它。

    • Git会在30天后永久删除此类提交,但在此之前,您可以通过再次指向一个分支来恢复C( git checkout C; git branch <new branch name> )

    论据

    套用手册页,最常见的用法是 git reset [<commit>] [paths...] ,它将从给定提交将给定路径重置为其状态。如果未提供路径,则重置整个树,如果未提供提交,则将其视为head(当前提交)。这是g it命令中的一个常见模式(例如checkout、diff、log,尽管确切的语义有所不同),所以这并不奇怪。

    例如, git reset other-branch path/to/foo 将path/to/foo中的所有内容重置为其他分支中的状态, git reset -- . 将当前目录重置为其head中的状态,然后 Git复位 将所有内容重置为其头部状态。

    主工作树和索引选项

    有四个主要选项可以控制重置期间工作树和索引的变化。

    记住,索引是git的“暂存区”——当你说 git add 准备作出承诺。

    • --硬 使所有内容都与您重置的提交相匹配。这可能是最容易理解的。所有的本地更改都会被破坏。一个主要用途是取消您的工作,但不转换承诺: git reset --hard 方法 git reset --hard HEAD ,即不要更改分支,而是删除所有本地更改。另一种方法是简单地将一个分支从一个地方移动到另一个地方,并保持索引/工作树同步。 这真的会让你失去工作,因为它会修改你的工作树。 在你做任何事之前,一定要把当地的工作丢掉 reset --hard .

    • --mixed 是默认值,即。 Git复位 方法 git reset --mixed . 它重置索引,但不重置工作树。这意味着您的所有文件都是完整的,但是原始提交和您重置的提交之间的任何差异都将显示为具有git状态的本地修改(或未跟踪的文件)。当你意识到你犯了一些错误,但是你想保留你已经做的所有工作,这样你就可以修复它并重新提交。为了提交,您必须再次将文件添加到索引中( git add ... )

    • --soft 不碰索引 工作树。你所有的文件都完好无损 ——混合 ,但所有更改都显示为 changes to be committed 具有git状态(即签入以准备提交)。当你意识到你做了一些不好的承诺,但是工作都是好的,你所需要做的就是用不同的方式重新提交它。索引是未触及的,因此如果需要,可以立即提交-结果提交将具有与重置前相同的所有内容。

    • --merge 最近添加的,旨在帮助您中止失败的合并。这是必要的,因为 git merge 实际上,只要这些修改位于不受合并影响的文件中,您就可以尝试与脏工作树(具有本地修改的)合并。 git reset --merge 重置索引(如 ——混合 -所有更改都显示为本地修改),并重置受合并影响的文件,但保留其他更改。这将有望使一切恢复到糟糕的合并之前的状态。你通常会把它当作 Git重置--合并 (意义 git reset --merge HEAD )因为您只想重置合并,而不是实际移动分支。( 尚未更新,因为合并失败)

      更具体地说,假设您修改了文件A和B,并试图合并到修改了文件C和D的分支中。由于某种原因,合并失败,您决定中止合并。你用 Git重置--合并 . 这让C和D回到了他们的处境 ,但将修改留给a和b,因为它们不是尝试合并的一部分。

    想知道更多吗?

    我确实认为 man git reset 这一点非常好——也许你确实需要了解Git的工作方式,以便让他们真正了解Git。特别是,如果您花时间仔细阅读它们,这些表详细说明了索引和工作树中文件的状态,对于所有各种选项和情况都非常有用。(但是的,它们非常密集——它们以非常简洁的形式传达了大量上述信息。)

    奇怪的符号

    “奇怪的符号”( HEAD^ HEAD~1 )您提到的只是指定提交的简写,而不必使用 3ebe3f6 . 它被完全记录在 "specifying revisions" section 关于git rev parse的手册页,有很多示例和相关语法。插入符号和颚化符实际上是指 different things :

    • HEAD~ 是短的 头颅~ 1 表示提交的第一个父级。 HEAD~2 表示提交的第一个父级的第一个父级。想想 HEAD~n 如“n先于head”或“head的第n代祖先”。
    • 头^ (或) HEAD^1 )也意味着提交的第一个父级。 HEAD^2 意思是承诺 第二 起源。请记住,正常的合并提交有两个父级-第一个父级是合并到提交,第二个父级是合并的提交。一般来说,合并实际上可以有任意多个父级(章鱼合并)。
    • 这个 ^ ~ 运算符可以串在一起,如 HEAD~3^2 ,第三代祖先的第二代父母 , HEAD^^2 ,的第一个父级的第二个父级 甚至 HEAD^^^ ,相当于 HEAD~3 .

    caret and tilde

        2
  •  75
  •   John Feminella    15 年前

    记住这一点 git 你有:

    • 这个 HEAD 指针 ,它告诉你你在做什么
    • 这个 工作树 ,它表示系统上文件的状态。
    • 这个 分级区 (也称为 指数 ,哪些“阶段”会发生更改,以便以后可以一起提交

    请详细说明:

    --hard , --soft --merge ;

    按照危险程度的增加顺序:

    • --软 移动 但不要碰舞台区域或工作树。
    • --mixed 移动 更新暂存区域,但不更新工作树。
    • --合并 移动 ,重置暂存区域,并尝试将工作树中的所有更改移动到新的工作树中。
    • --硬 移动 调整暂存区域和工作树以适应新的 ,扔掉所有东西。

    具体的用例和工作流;

    • 使用 --软 当你想转移到另一个任务中,并且在不“失去你的位置”的情况下修补事情时。你很少需要这个。

    ——

    # git reset --soft example
    touch foo                            // Add a file, make some changes.
    git add foo                          // 
    git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
    git reset --soft HEAD^               // Go back one commit and fix things.
    git commit -m "good commit"          // There, now it's right.
    

    ——

    • 使用 ——混合 (这是默认设置)当您希望查看另一个提交的外观时,但不希望丢失已做的任何更改。

    • 使用 --合并 当你想移动到一个新的地点,但把你已经做的修改合并到工作树中。

    • 使用 --硬 把一切都抹去,重新开始新的承诺。

        3
  •  34
  •   suspectus    7 年前

    岗位 Reset Demystified 在博客中 Pro Git 给出一个非常 没有头脑 解释 git reset git checkout .

    在那篇文章的顶部进行了所有有益的讨论之后,作者将规则简化为以下三个简单步骤:

    基本上就是这样。这个 reset 命令将按特定顺序覆盖这三棵树,并在命令时停止。

    1. 移动分支头指向的任何位置(如果 --soft )
    2. 然后,使索引看起来像那样(在此停止,除非 --hard )
    3. 然后,使工作目录看起来像那样

    还有 --merge --keep 选择,但我宁愿让事情现在更简单-那将是另一篇文章。

        4
  •  23
  •   love    11 年前

    当您向git提交某些内容时,您首先必须准备(添加到索引中)您的更改。这意味着您必须在git将这些文件视为提交的一部分之前,git添加要包含在此提交中的所有文件。我们先来看看git回购的图像: enter image description here

    所以,现在很简单。我们必须在工作目录中工作,创建文件、目录和所有内容。这些更改是未跟踪的更改。要跟踪它们,我们需要使用 Git添加 命令。一旦它们被添加到git索引中。我们现在可以提交这些更改,如果我们想将其推送到git存储库。

    但是突然我们发现,在提交时,我们有一个额外的文件,我们添加在索引中,不需要推送git存储库。这意味着我们不希望那个文件在索引中。 现在的问题是如何从git索引中删除该文件,因为我们使用 Git添加 把它们放在索引中是合乎逻辑的 移除文件 ?错了! 移除文件 只需删除文件并将删除添加到索引中。现在该怎么办:

    用途:

    Git复位

    它会清除索引,保持工作目录不变。(简单地说,就是拆开所有东西)。

    它可以与许多选项一起使用。 有三个主要选项可用于 Git重置:--硬,--软和-混合 . 当重置时,除了头指针之外,这些还会影响get的重置。

    第一, --硬 重置所有内容。如果你一直在跟踪那个分支,那么你当前的目录将完全相同。工作目录和索引将更改为该提交。这是我最常使用的版本。 Git重置--硬 有点像 奇异值恢复 .

    接下来,完全相反, 软性软体 ,不会重置工作树或索引。它只移动头部指针。这将使您的当前状态保留与您要在目录中就地切换到的提交不同的任何更改,并为提交而暂存。如果您在本地进行提交,但没有将提交推送到git服务器,那么您可以重置为上一次提交,并用一条好的提交消息重新提交。

    最后, --混合 重置索引,但不重置工作树。所以这些变化仍然存在,但还没有过时,需要添加git或 git提交-a . 有时,如果我们提交的内容比git commit-a要多,我们可以使用git reset退出提交——mixed,添加我们想要提交的内容,然后提交这些内容。

    git revert和git reset的区别 -


    简单地说, Git复位 是一个命令 “修正未改正的错误” GIT回复 是一个命令 “修正犯下的错误” .

    这意味着如果我们在某些更改中犯了一些错误,并将其提交到git repo,那么 GIT回复 是解决办法。如果我们在推送/交付之前发现了相同的错误,我们可以使用 Git复位 来解决这个问题。

    我希望它能帮助你摆脱困惑。

        5
  •  6
  •   Snowcrash    10 年前

    DR

    git reset 将登台重置为上次提交。使用 --hard 还要将工作目录中的文件重置为上次提交。

    较长版本

    但这显然过于简单,因此有许多相当冗长的答案。我读起来更有意义 Git复位 在撤消更改的上下文中。例如,请参见:

    如果git revert是一种安全的撤销更改的方法,那么可以考虑git 重置为危险方法。当您使用git reset(和 提交不再被任何ref或reflog引用。 无法检索原始副本–这是永久撤消。必须小心 使用此工具时,请将其作为可能会丢失工作的唯一git命令之一。

    https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

    而这

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

    https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations

        6
  •  2
  •   timhc22    10 年前

    请注意,这是一个简单的解释,旨在作为第一步,寻求了解这个复杂的功能。

    对于希望在执行以下每个命令后将其项目状态可视化的视觉学习者来说,可能会有所帮助:


    对于使用彩色终端的用户 (Git配置--全局颜色.ui自动):

    git reset --soft A 你会看到B和C的东西都是绿色的(已经准备好了)

    git reset --mixed A (或) git reset A )你会看到B和C的东西是红色的(未老化的,准备就绪的(绿色),然后提交)

    git reset --hard A 你将不再在任何地方看到b和c的变化(就好像它们从未存在过一样)


    或者对于那些使用像“tower”或“sourcetree”这样的gui程序的用户

    Git重置——软A 你会在“暂存文件”区域看到B和C的东西准备提交

    Git重置--混合 (或) 重置A )在“未分页文件”区域中,您将看到B和C的内容准备移动到暂存文件,然后提交

    Git重置——硬A 你将不再在任何地方看到b和c的变化(就好像它们从未存在过一样)

        7
  •  1
  •   Neuron MonoThreaded    6 年前

    签出将头部指向特定的提交。

    重置指向特定提交处的分支。(分支是指向提交的指针。)

    顺便说一下,如果您的头没有指向分支也指向的提交,那么您的头是分离的。 (结果是错的。请参阅评论…)