git reset

git-reset

命名

git-reset - 将当前 HEAD 重置为指定状态

概要

git reset [-q] [<tree-ish>] [--] <paths>…​ git reset (--patch | -p) [<tree-ish>] [--] [<paths>…​] git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]

描述

在第一种和第二种形式中,将 <tree-ish> 中的条目复制到索引中。在第三种形式中,将当前分支头(HEAD)设置为 <commit> ,可选地修改索引和工作树以匹配。<tree-ish> / <commit> 默认为所有形式的 HEAD 。

git reset -q -- <paths>…​

该表单将所有 <paths> 的索引条目重置为它们在 <tree-ish> 的状态。(它不会影响工作树或当前分支。)

这意味着这git reset <paths>与git add <paths>是相反的。

在运行git reset <paths>以更新索引条目之后,可以使用 git-checkout [1] 将索引中的内容检查到工作树。或者,使用 git-checkout [1] 并指定提交,您可以一次将提交中的路径内容复制到索引和工作树中。

git reset (--patch | -p) <tree-ish> <paths>…​

在索引和 <tree-ish> 之间的差异中交互选择 hunk(默认为 HEAD )。选定的区块与指数相反。

这意味着这git reset -pgit add -p是相反的,也就是说,你可以用它来选择性地重置人群。请参阅 git-add [1] 的“交互模式”部分了解如何操作该--patch模式。

git reset <mode>

此表单将当前分支头重置为 <commit> ,并可能更新索引(将其重置为 <commit> 的树),并根据 <mode> 更新工作树。如果省略 <mode> ,则默认为“--mixed”。<mode> 必须是以下之一:

--soft

根本不触摸索引文件或工作树(但将头重置为 <commit> ,就像所有模式一样)。这git status将使所有更改的文件“变更被提交”,就像它会这样。

--mixed

重置索引而不是工作树(即,保存更改的文件但未标记为提交)并报告尚未更新的内容。这是默认操作。

如果-N指定,则删除的路径将标记为 intent-to-add(请参阅 git-add [1] )。

--hard

重置索引和工作树。放弃自 <commit> 以来对工作树中跟踪文件的任何更改。

--merge

重置索引并更新工作树中 <commit> 和 HEAD 之间不同的文件,但保留索引和工作树之间不同的文件(即没有添加更改的文件)。如果 <commit> 和索引之间的文件有不同的变化,则重置会中止。

换句话说,--merge 可以做一些类似的事情git read-tree -u -m <commit>,但是会传递未合并的索引条目。

--keep

重置索引条目并更新工作树中 <commit> 和 HEAD 之间不同的文件。如果 <commit> 和 HEAD 之间的文件有本地更改,则重置会中止。

如果你想撤消一个分支以外的提交,git-revert [1] 是你的朋友。

选项

-q --quiet

只报告错误。

例子

撤消添加

$ edit (1) $ git add frotz.c filfre.c $ mailx (2) $ git reset (3) $ git pull git://info.example.com/ nitfol (4)

  • 您正在愉快地处理某些事情,并发现这些文件中的更改顺利进行。当你运行 “git diff” 时,你不想看到它们,因为你打算在其他文件上工作,而使用这些文件进行更改会让人分心。

撤消提交并重做

$ git commit ... $ git reset --soft HEAD^ (1) $ edit (2) $ git commit -a -c ORIG_HEAD (3)

  • 当你记住你刚才提交的内容不完整,或者你拼错了你的提交信息,或者两者兼而有之时,通常会这样做。像在“重置”之前那样使树工作。

另请参阅 git-commit [ - ] 的 --amend 选项。

撤消提交,使其成为主题分支

$ git branch topic/wip (1) $ git reset --hard HEAD~3 (2) $ git checkout topic/wip (3)

  • 你已经做了一些提交,但意识到他们在 “master” 分支还为时尚早。您想要继续在主题分支中打磨它们,因此请从当前 HEAD 创建 “主题/ wip” 分支。

撤消永久提交

$ git commit ... $ git reset --hard HEAD~3 (1)

  • 最后三个提交( HEAD ,HEAD ^ 和 HEAD〜2 )很差,你不想再看到它们。难道不是如果你已经给了这些提交给别人做。(有关这样做的含义,请参阅 git-rebase [1] 中的“从上游重新启动恢复”一节。)

撤消合并或拉

$ git pull (1) Auto-merging nitfol CONFLICT (content): Merge conflict in nitfol Automatic merge failed; fix conflicts and then commit the result. $ git reset --hard (2) $ git pull . topic/branch (3) Updating from 41223... to 13134... Fast-forward $ git reset --hard ORIG_HEAD (4)

  • 尝试从上游更新导致很多冲突; 你现在还没有准备好花很多时间合并,所以你稍后决定这么做。

撤消一个合并或拉一个不完美的工作树内

$ git pull (1) Auto-merging nitfol Merge made by recursive. nitfol | 20 +++++---- ... $ git reset --merge ORIG_HEAD (2)

  • 即使你可能在你的工作树上进行了局部修改,当你知道另一个分支中的变化与它们没有重叠时,你也可以安全地说出 “git pull” 。

中断的工作流程

假设当你处于一个大的变化中时,你被紧急修复请求中断。工作树中的文件没有任何形状可供提交,但需要到另一个分支进行快速修补。

$ git checkout feature ;# you were working in "feature" branch and $ work work work ;# got interrupted $ git commit -a -m "snapshot WIP" (1) $ git checkout master $ fix fix fix $ git commit ;# commit with real log $ git checkout feature $ git reset --soft HEAD^ ;# go back to WIP state (2) $ git reset (3)

  • 这个提交会被吹走,所以丢弃的日志消息是 OK 的。

另见 git-stash [1] 。

重置索引中的单个文件

假设你已经添加了一个文件到你的索引,但稍后决定你不想将它添加到你的提交。您可以从索引中删除文件,同时使用 git reset 保留更改。

$ git reset -- frotz.c (1) $ git commit -m "Commit files in index" (2) $ git add frotz.c (3)

  • 这将文件从索引中删除,同时保留在工作目录中。

在改变工作树的同时放弃一些以前的提交

假设你正在处理一些事情,然后你继续工作,然后你继续工作多一点,但是现在你认为你工作树中的内容应该在另一个分支中,这与你以前承诺的事情没有任何关系。您可以启动一个新分支并重置它,同时将更改保留在工作树中。

$ git tag start $ git checkout -b branch1 $ edit $ git commit ... (1) $ edit $ git checkout -b branch2 (2) $ git reset --keep start (3)

  • 这会在 branch1 中提交您的第一批编辑。

将提交拆分为一系列提交

假设您已经创建了大量逻辑上单独的更改并将它们一起提交。然后,稍后您决定将每个逻辑块与其自己的提交关联起来可能会更好。您可以使用 git reset 在不改变本地文件内容的情况下回退历史记录,然后使用预先填充提交消息git add -p来交互式地选择要包含到每个提交中的哪些区块git commit -c

$ git reset -N HEAD^ (1) $ git add -p (2) $ git diff --cached (3) $ git commit -c HEAD@{1} (4) ... (5) $ git add ... (6) $ git diff --cached (7) $ git commit ... (8)

  • 首先,将历史记录重置为一次提交,以便删除原始提交,但保留所有更改的工作树。-N 确保任何添加了 HEAD 的新文件仍被标记,以便 git add -p 可以找到它们。

讨论

下表显示了运行时发生的情况:

git reset --option target

target根据文件的状态使用不同的重置选项将 HEAD 重置为另一个提交()。

在这些表中,A ,B ,C 和 D 是文件的一些不同状态。例如,第一个表的第一行意味着如果文件处于工作树状态A ,索引状态 B ,HEAD 状态 C 和目标状态 D ,则 “git reset - 软目标“ 将使文件在状态A的工作树中和状态B的索引中。它将 HEAD(即,当前分支的顶端,如果你在一个上)重置(即移动)到 ”目标“(其中状态为 D 的文件)。

working index HEAD target working index HEAD ---------------------------------------------------- A B C D --soft A B D --mixed A D D --hard D D D --merge (disallowed) --keep (disallowed)

working index HEAD target working index HEAD ---------------------------------------------------- A B C C --soft A B C --mixed A C C --hard C C C --merge (disallowed) --keep A C C

working index HEAD target working index HEAD ---------------------------------------------------- B B C D --soft B B D --mixed B D D --hard D D D --merge D D D --keep (disallowed)

working index HEAD target working index HEAD ---------------------------------------------------- B B C C --soft B B C --mixed B C C --hard C C C --merge C C C --keep B C C

working index HEAD target working index HEAD ---------------------------------------------------- B C C D --soft B C D --mixed B D D --hard D D D --merge (disallowed) --keep (disallowed)

working index HEAD target working index HEAD ---------------------------------------------------- B C C C --soft B C C --mixed B C C --hard C C C --merge B C C --keep B C C

“复位 - 合并”意味着在重置冲突合并时使用。任何合并操作都可以保证合并中涉及的工作树文件在启动之前不会对索引进行本地更改,并且可以将结果写入工作树。所以如果我们看到索引和目标之间以及索引和工作树之间存在某种差异,那么这意味着我们不会从一个在发生冲突后失败的状态中重置。这就是为什么我们在这种情况下不允许 - 合并选项。

在保留对工作树的修改的同时,删除当前分支中的某些最后提交时,将使用 “reset --keep” 。如果我们要删除的提交更改与我们想要保留的工作树更改之间可能存在冲突,则不允许重置。这就是为什么如果工作树和 HEAD 之间以及 HEAD 和目标之间都存在变化,则不允许它。为了安全起见,当没有合并的条目时它也被禁止。

下表显示了在没有合并条目时发生的情况:

working index HEAD target working index HEAD ---------------------------------------------------- X U A B --soft (disallowed) --mixed X B B --hard B B B --merge B B B --keep (disallowed)

working index HEAD target working index HEAD ---------------------------------------------------- X U A A --soft (disallowed) --mixed X A A --hard A A A --merge A A A --keep (disallowed)

X 表示任何状态,U 表示未合并的索引。