git reset(回退add操做)

Git的通常使用中,若是发现错误的将不想提交的文件add进入index以后,想回退取消,则可使用命令:git reset HEAD <file>...,同时git add完毕以后,git也会作相应的提示,好比:git

引用安全

 

# Changes to be committed: spa

#   (use "git reset HEAD<file>..." to unstage) .net

命令行

# new file:   Test.Scala scala

 

git reset [--hard|soft|mixed|merge|keep] [<commit>HEAD]:将当前的分支重设(reset)到指定的<commit>或者HEAD(默认,若是不显示指定commit,默认是HEAD,即最新的一次提交),而且根据[mode]有可能更新indexworking directory对象

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

A) 回滚add操纵 开发

引用get

$ 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搞乱了,由于indexHEAD commit不匹配了,可是你知道,即将pull的东西不会影响已经修改的frotz.cfilfre.c,所以你能够revert这两个文件的改变。revert后,那些改变应该依旧在working directory中,所以执行git reset 

(4) 而后,执行了pull以后,自动mergefrotz.cfilfre.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引用这个commitcommit命令中 -a 参数的意思是告诉git,自动把全部修改的和删除的文件都放进stage area,未被git跟踪的新建的文件不受影响。commit命令中-c <commit> 或者 -C <commit>意思是拿已经提交的commit对象中的信息(做者,提交者,注释,时间戳等)提交,那么这条commit命令的意思就很是清晰了,把全部更改的文件加入stage area,并使用上次的提交信息从新提交。 

 

C) 回滚最近几回commit,并把这几回commit放到叫作topicbranch上去。 

引用

$ 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-3commitcommitgit 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) 回滚mergepull操做 

引用

$ git pull                        (1) 

Auto-merging nitfol 

CONFLICT (content): Merge conflict innitfol 

Automatic merge failed; fix conflicts andthen 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意思相同,即都是清除indexworking 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。一样的,执行pullmerge操做时,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,可是你又必须切换的另外的branchfix bug。请看下面的例子 

引用

$ git checkout feature ;# you were workingin "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 WIPstate  (2) 

$ git reset                                     (3)

 

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

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

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

 

(H) Reset单独的一个文件 

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

引用

$ git reset -- frotz.c                     (1) 

$ git commit -m "Commit files inindex"     (2) 

$ git add frotz.c                          (3)

 

(1) 把文件frotz.cindex中去除, 

(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 不变。
相关文章
相关标签/搜索