`
Josh_Persistence
  • 浏览: 1651188 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类

Git Reset

    博客分类:
  • Git
阅读更多
一、基本篇

 

在git的一般使用中,如果发现错误的将不想staging的文件add进入index之后,想回退取消,则可以使用命令:git reset HEAD <file>...,同时git add完毕之后,git也会做相应的提示,比如:

 

引用

 

# Changes to be committed: 
#   (use "git reset HEAD <file>..." to unstage) 
#new file:   Test.scala 

 

git reset [--hard|soft|mixed|merge|keep] [<commit>HEAD]:将当前的分支重设(reset)到指定的<commit>或者HEAD(默认,如果不显示指定commit,默认是HEAD,即最新的一次提交),并且根据[mode]有可能更新index和working directory。mode的取值可以是hard、soft、mixed、merged、keep。下面来详细说明每种模式的意义和效果。

 

A). --hard:重设(reset) index和working directory,自从<commit>以来在working directory中的任何改变都被丢弃,并把HEAD指向<commit>。 

 

具体一个例子,假设有三个commit, git st:
commit3: add test3.c
commit2: add test2.c
commit1: add test1.c
执行git reset --hard HEAD~1后,
显示:HEAD is now at commit2,运行git log
commit2: add test2.c
commit1: add test1.c
运行git st, 没有任何变化

 

B)--soft:index 和working directory中的内容不作任何改变,仅仅把HEAD指向<commit>。这个模式的效果是,执行完毕后,自 从<commit>以来的所有改变都会显示在git status的"Changes to be committed"中。 

 

具体一个例子,假设有三个commit, git st:
commit3: add test3.c
commit2: add test2.c
commit1: add test1.c
执行git reset --soft(默认) HEAD~1后,运行git log
commit2: add test2.c
commit1: add test1.c
运行git status, 则test3.c处于暂存区,处于准备提交状态。即此时git commit就会提交它。

 

  在使用git进行协作开发时,我们经常需要将自己的修改生成patch发给被人,但是在修改代码的过程中我们进行了很多次的提交,如何生成从最初的代码状态到最终代码状态的patch呢?下面要介绍的功能是应对这中情况。
现假设我们git软件仓库中的分支情况如下:
a-->b-->c
也就是说我们的代码从状态a修改到状态b,进行 一次提交,然后再修改到状态c,进行一次提交。这时我们已经肯定由a到c的修改是正确的,不再需要状态b了,并且要把从a到c的变化生成一个patch发 送给别人。如果直接打包的话会生成两个path,那么如何生成一个patch呢,这时就需要git-reset命令。
首先给状态a创建一个tag,假设名称为A,然后执行
git-reset --soft A
这样我们的软件仓库就变为
a
状态b和状态c都已经被删除了,但是当前的代码并没有被改变,还是状态c的代码,这时我们做一次提交,软件仓库变成下面的样子:
a-->d
状态d和状态c所对应的代码是完全相同的,只是名字不同。现在就可以生成一个patch打包发给别人了

 

C)--mixed:仅reset index,但是不reset working directory。这个模式是默认模式,即当不显示告知git reset模式时,会使用mixed模式。这个模式的效果是,working directory中文件的修改都会被保留,不会丢弃,但是也不会被标记成"Changes to be committed",但是会打出什么还未被更新的报告。报告如下: 

 

引用

 

Unstaged changes after reset: 

 

M Test.Scala 

 

M test.txt

 

 

 

D)--merge--keep用的不多,在下面的例子中说明。 

 

二、常用示例

 

下面列出一些git reset的典型的应用场景: 

 

A) 回滚add操纵 

 

引用

 

$ edit                                     (1) 

 

$ git add frotz.c filfre.c 

 

$ mailx                                    (2) 

 

$ git reset                                (3) 

 

$ git pull git://info.example.com/ nitfol  (4) 

 

 

 

(1) 编辑文件frotz.c, filfre.c,做了些更改,并把更改添加到了index 

 

(2) 查看邮件,发现某人要你pull,有一些改变需要你merge下来 

 

(3) 然而,你已经把index搞乱了,因为index同HEAD commit不匹配了,但是你知道,即将pull的东西不会影响已经修改的frotz.c和filfre.c,因此你可以revert这两个文件的改变。 revert后,那些改变应该依旧在working directory中,因此执行git reset。 

 

(4) 然后,执行了pull之后,自动merge,frotz.c和filfre.c这些改变依然在working directory中。 

 

 

 

B) 回滚最近一次commit 

 

引用

 

$ git commit ... 

 

$ git reset --soft HEAD^      (1) 

 

$ edit                        (2) 

 

$ git commit -a -c ORIG_HEAD  (3) 

 

 

 

(1) 当提交了之后,你又发现代码没有提交完整,或者你想重新编辑一下提交的comment,执行git reset --soft HEAD^,让working tree还跟reset之前一样,不作任何改变。 

 

HEAD^指向HEAD之前最近的一次commit。 

 

(2) 对working tree下的文件做修改 

 

(3) 然后使用reset之前那次commit的注释、作者、日期等信息重新提交。注意,当执行git reset命令时,git会把老的HEAD拷贝到文件.git/ORIG_HEAD中,在命令中可以使用ORIG_HEAD引用这个commit。 commit 命令中 -a 参数的意思是告诉git,自动把所有修改的和删除的文件都放进stage area,未被git跟踪的新建的文件不受影响。commit命令中-c <commit> 或者 -C <commit>意思是拿已经提交的commit对象中的信息(作者,提交者,注释,时间戳等)提交,那么这条commit命令的意思就非常 清晰了,把所有更改的文件加入stage area,并使用上次的提交信息重新提交。 

 

 

 

C) 回滚最近几次commit,并把这几次commit放到叫做topic的branch上去。 

 

引用

 

$ git branch topic/wip     (1) 

 

$ git reset --hard HEAD~3  (2) 

 

$ git checkout topic/wip   (3)

 

 

 

(1) 你已经提交了一些commit,但是此时发现这些commit还不够成熟,不能进入master分支,但你希望在新的branch上润色这些commit改动。因此执行了git branch命令在当前的HEAD上建立了新的叫做 topic/wip的分支。 

 

(2) 然后回滚master branch上的最近三次提交。HEAD~3指向当前HEAD-3个commit的commit,git reset --hard HEAD~3即删除最近的三个commit(删除HEAD, HEAD^, HEAD~2),将HEAD指向HEAD~3。 

 

 

 

D) 永久删除最后几个commit 

 

引用

 

$ git commit ... 

 

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

 

 

 

(1) 最后三个commit(即HEAD, HEAD^和HEAD~2)提交有问题,你想永久删除这三个commit。 

 

 

 

E) 回滚merge和pull操作 

 

引用

 

$ 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)

 

 

 

(1) 从origin拉下来一些更新,但是产生了很多冲突,你暂时没有这么多时间去解决这些冲突,因此你决定稍候有空的时候再重新pull。 

 

(2) 由于pull操作产生了冲突,因此所有pull下来的改变尚未提交,仍然再stage area中,这种情况下git reset --hard 与 git reset --hard HEAD意思相同,即都是清除index和working tree中被搞乱的东西。 

 

(3) 将topic/branch合并到当前的branch,这次没有产生冲突,并且合并后的更改自动提交。 

 

(4) 但是此时你又发现将topic/branch合并过来为时尚早,因此决定退滚merge,执行git reset --hard ORIG_HEAD回滚刚才的pull/merge操作。说明:前面讲过,执行git reset时,git会把reset之前的HEAD放入.git/ORIG_HEAD文件中,命令行中使用ORIG_HEAD引用这个commit。同样 的,执行pull和merge操作时,git都会把执行操作前的HEAD放入ORIG_HEAD中,以防回滚操作。 

 

 

 

F) 在被污染的working tree中回滚merge或者pull 

 

引用

 

$ git pull                         (1) 

 

Auto-merging nitfol 

 

Merge made by recursive. 

 

nitfol                |   20 +++++---- 

 

... 

 

$ git reset --merge ORIG_HEAD      (2)

 

 

 

(1) 即便你已经在本地更改了一些你的working tree,你也可安全的git pull,前提是你知道将要pull的内容不会覆盖你的working tree中的内容。 

 

(2) git pull完后,你发现这次pull下来的修改不满意,想要回滚到pull之前的状态,从前面的介绍知道,我们可以执行git reset --hard ORIG_HEAD,但是这个命令有个副作用就是清空你的working tree,即丢弃你的本地未add的那些改变。为了避免丢弃working tree中的内容,可以使用git reset --merge ORIG_HEAD,注意其中的--hard 换成了 --merge,这样就可以避免在回滚时清除working tree。 

 

 

 

G) 被中断的工作流程 

 

在实际开发中经常出现这样的情形:你正在开发一个大的feature,此时来了一个紧急的bug需要修复,但是目前在working tree中的内容还没有成型,还不足以commit,但是你又必须切换的另外的branch去fix bug。请看下面的例子 

 

引用

 

$ 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)

 

 

 

(1) 这次属于临时提交,因此随便添加一个临时注释即可。 

 

(2) 这次reset删除了WIP commit,并且把working tree设置成提交WIP快照之前的状态。 

 

(3) 此时,在index中依然遗留着“snapshot WIP”提交时所做的uncommit changes,git reset将会清理index成为尚未提交"snapshot WIP"时的状态便于接下来继续工作。 

 

 

 

(H) Reset单独的一个文件 

 

假设你已经添加了一个文件进入index,但是而后又不打算把这个文件提交,此时可以使用git reset把这个文件从index中去除。 

 

引用

 

$ git reset -- frotz.c                      (1) 

 

$ git commit -m "Commit files in index"     (2) 

 

$ git add frotz.c                           (3)

 

 

 

(1) 把文件frotz.c从index中去除, 

 

(2) 把index中的文件提交 

 

(3) 再次把frotz.c加入index 

 

 

 

(I) 保留working tree并丢弃一些之前的commit 

 

假设你正在编辑一些文件,并且已经提交,接着继续工作,但是现在你发现当前在working tree中的内容应该属于另一个branch,与这之前的commit没有什么关系。此时,你可以开启一个新的branch,并且保留着working tree中的内容。 

 

引用

 

$ git tag start 

 

$ git checkout -b branch1 

 

$ edit 

 

$ git commit ...                            (1) 

 

$ edit 

 

$ git checkout -b branch2                   (2) 

 

$ git reset --keep start                    (3)

 

 

 

(1) 这次是把在branch1中的改变提交了。 

 

(2) 此时发现,之前的提交不属于这个branch,此时你新建了branch2,并切换到了branch2上。 

(3) 此时你可以用reset --keep把在start之后的commit清除掉,但是保持working tree不变。

分享到:
评论

相关推荐

    前端大厂最新面试题-git reset_ git revert.docx

    Git Reset vs Git Revert Git Reset 和 Git Revert 是两个常用的 Git 命令,用于撤销或回退版本,但它们的用法和实现有所不同。本文将详细介绍 Git Reset 和 Git Revert 的理解、区别和使用场景。 一、Git Reset ...

    git reset 的三个参数.pdf

    在Git中,`git reset` 是一个非常重要的命令,它用于撤销或重置Git的工作区、暂存区和历史记录。在这个场景下,我们主要讨论`git reset`的三个参数:`--soft`、`--mixed` 和 `--hard`,以及它们在不同情况下的具体...

    详解git reset 加不加 --hard的区别

    Git是分布式版本控制系统,它提供了丰富的命令来管理代码版本,其中`git reset`是一个非常重要的命令,用于撤销或重置Git的工作区、暂存区和提交历史。在本文中,我们将详细探讨`git reset`命令在加不加`--hard`选项...

    详解IDEA Git Reset 选项说明

    IDEA Git Reset 是集成开发环境 IntelliJ IDEA 中用于管理 Git 版本控制功能的一个重要工具。它允许用户通过图形界面来执行 Git Reset 命令,以改变当前分支的HEAD指针位置以及暂存区和工作目录的状态。在使用 IDEA ...

    详解git reset --hard 和 git reset --soft区别

    本文将详细讲解`git reset --hard`和`git reset --soft`的区别,以及它们的具体用法。 `git reset`命令主要用于将HEAD指针移动到指定的提交上,它可以改变历史记录,但要注意这可能会导致未保存的工作丢失。`--hard...

    git revert和git reset的区别详解

    ### Git Revert与Git Reset详解 #### 一、引言 在版本控制工具Git中,`git revert`和`git reset`是两个非常重要的命令,它们可以帮助开发人员撤销之前的操作,但二者的实现机制和使用场景有所不同。本文将详细介绍...

    git 删除分支和回滚的实例详解

    git reset --hard commit-id :回滚到commit-id,讲commit-id之后提交的commit都去除 git reset --hard HEAD~3:将最近3次的提交回滚 【远程代码库回滚】: 这个是重点要说的内容,过程比本地回滚要复杂 应用场景:...

    图文详解 Git代码管理 工作原理

    git reset – files #用来撤销最后一次git add files,你也可以用git reset撤销所有暂存区域文件 git checkout – files #把文件从暂存区域复制到工作目录,用来丢弃本地修改 你可以用 git reset -p,git ...

    git使用教程

    - 文件重置:`git reset -- files` 或 `git reset -p`,类似`git checkout`但更新索引。 - **Merge**: - 合并分支:`git merge branch`,将指定分支的改动合并到当前分支。如果另一个分支是当前提交的祖先,则...

    git 常用的一些命令

    在 Git 中,可以使用 git reset HEAD . 命令撤销所有已经添加的文件。如果只想撤销某个文件或文件夹,可以使用 git reset HEAD filename 命令。 2. Git 文件差异命令 使用 git diff 命令可以查看当前内容的修改,...

    Git常用的33个命令

    git reset [文件名]:将暂存区的文件取消暂存,或者切换到指定版本git reset --hard [版本号] git commit -m "描述信息" [文件名]:将暂存区的文件修改提交到版本库 git log:查看日志 远程仓库命令: git remote:...

    git 基本命令整合

    git 基本命令整合 Git基本常用命令如下:  git init 把当前的目录变成可以管理的git仓库,生成隐藏.git文件。  git add 文件/(* 目录内所有文件) 将... git reset --hard HEAD git文件版本号 回退到上一个版本

    Git 的基本操作

    - `git reset --hard` 丢弃所有未提交的更改,回到最近的提交状态 - `git reset --hard 哈希&gt;` 回到指定的历史版本 - `git reset [path]` 将指定文件或目录从暂存区移除 - `git reset` 会将所有暂存的文件取消暂...

    Git 命令速查表

    命令`git reset --clean -n -f`可以显示将要从工作目录删除的文件列表,而`git reset --clean`则会执行删除操作。如果要替代最近一次提交,可以使用`git commit --amend`命令。 在重写历史方面,`git rebase`命令...

    45 个 Git 经典操作场景,抓紧收藏学习!.docx

    1. 将暂存的内容变成未暂存:`git reset HEAD^`,然后`git stash`,最后`git stash pop --index 0` 2. 将未暂存的内容暂存起来:`git add .`,然后`git stash` 3. 将暂存的内容移动到一个新分支:`git checkout -b ...

    git常用命令.docx

    * `git reset --hard HEAD`:清空工作目录中的所有未提交的内容 * `git reset --hard commitid`:本地代码回到指定的 commitid * `git reset HEAD`:恢复本地提交 * `git reset 文件路径`:撤销 add 时多添加的文件 ...

    git-指令及其使用1

    通过本文,我们可以了解到 Git 中常用的指令及其使用,包括 git init、git status、git add、git commit、git diff、git log、git reset 和 git reflog 等命令。掌握这些命令可以帮助我们更好地使用 Git 进行版本...

    Git使用手册.pdf

    对于回退版本,Git提供了`git reset --hard HEAD^`来回到上一个版本,如果需要回到更早的版本,可以使用`git reset --hard HEAD~n`,其中n代表版本数。如果忘记版本号,`git reflog`可以列出所有操作记录。 Git还...

    完全学会GIT+GITHUB+GIT+SERVER的24堂课

    在误操作时,Git提供了一些恢复工具,如`git reset --hard`、`git checkout`和`git reflog`,帮助找回丢失的更改。 **10. 代码同步** 开发者常使用`git pull`和`git push`同步本地和远程仓库。`git pull`合并远程...

Global site tag (gtag.js) - Google Analytics