git reset

reset命令有3种方式:

1:git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,回退commit和index信息

2:git reset –soft:回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可

3:git reset –hard:彻底回退到某个版本,本地的源码也会变为上一个版本的内容

HEAD 最近一个提交
    HEAD^ 上一次提交

    HEAD^ ^ 上一次的 上一次的提交(倒数第三次)

    HEAD^^^ 倒数 第四次的 提交

----------------------

    HEAD~0 最近一个提交
    HEAD~1 上一次提交

    HEAD^2 上一次的 上一次的提交(倒数第三次)

    HEAD^3 倒数 第四次的 提交


===============

    <commit_id> 每次commit的SHA1值. 可以用git log 看到,也可以在页面上commit标签页里找到.

git reset [--hard|soft|mixed|merge|keep] [<commit>或HEAD]:将当前的分支重设(reset)到指定的<commit>或者HEAD(默认,如果不显示指定commit,默认是HEAD,即最新的一次提交),并且根据[mode]有可能更新index和working directory。
下面列出一些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 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意思相同,即都是清除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 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 changes,git 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.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不变。

1
2
3
4
5
6
7
8
9
10
11
12
#回退所有内容到上一个版本 
git reset HEAD^ 
#回退a.py这个文件的版本到上一个版本 
git reset HEAD^ a.py 
#向前回退到第 3 个版本 
git reset –soft HEAD~ 3 
#将本地的状态回退到和远程的一样 
git reset –hard origin/master 
#回退到某个版本 
git reset 057d 
#回退到上一次提交的状态,按照某一次的commit完全反向的进行一次commit 
git revert HEAD 

如果我们某次修改了某些内容,并且已经commit到本地仓库,而且已经push到远程仓库了

这种情况下,我们想把本地和远程仓库都回退到某个版本,该怎么做呢?

前面讲到的git reset只是在本地仓库中回退版本,而远程仓库的版本不会变化

这样,即时本地reset了,但如果再git pull,那么,远程仓库的内容又会和本地之前版本的内容进行merge

这并不是我们想要的东西,这时可以有2种办法来解决这个问题:

1:直接在远程server的仓库目录下,执行git reset –soft 10efa来回退。注意:在远程不能使用mixed或hard参数

2:在本地直接把远程的master分支给删除,然后再把reset后的分支内容给push上去,如下:

复制代码
#新建old_master分支做备份  
git branch old_master  
#push到远程  
git push origin old_master:old_master  
#本地仓库回退到某个版本  
git reset –hard bae168  
#删除远程的master分支  
git push origin :master  
#重新创建master分支  
git push origin master  
复制代码

在删除远程master分支时,可能会有问题,见下:

 

复制代码
$ git push origin :master  
error: By default, deleting the current branch is denied, because the next  
error: 'git clone' won't result in any file checked out, causing confusion.  
error:  
error: You can set 'receive.denyDeleteCurrent' configuration variable to  
error: 'warn' or 'ignore' in the remote repository to allow deleting the  
error: current branch, with or without a warning message.  
error:  
error: To squelch this message, you can set it to 'refuse'.  
error: refusing to delete the current branch: refs/heads/master  
To git@xx.sohu.com:gitosis_test  
 ! [remote rejected] master (deletion of the current branch prohibited)  
error: failed to push some refs to 'git@xx.sohu.com:gitosis_test'  
复制代码

 

这时需要在远程仓库目录下,设置git的receive.denyDeleteCurrent参数

git receive.denyDeleteCurrent warn  

然后,就可以删除远程的master分支了

虽然说有以上2种方法可以回退远程分支的版本,但这2种方式,都挺危险的,需要谨慎操作……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值