Git(一) 版本回滚
前言
Git在日常开发中是我们经常要用到的,所以我想在这里把自己平时工作用到的和平时容易遗忘的在这里做一个小小的总结,本文参考廖雪峰老师的git教程。
情景一:需求确认后,实现到80%
产品经理:'那个,小无,今天和总经理商量了一下,这个这个要改成那个那个,巴拉巴拉...'
小无:'确认需求改成这样对吗,修改需求是要增加开发成本的'
产品经理:'总经理认为这样实现会有更亮的点吸引客户'
小无:'好吧好吧,心理状况(总经理都搬出来了,还能说啥,改呗 - -!)先上传一下吧 git add . git commit -m '07/09 xiaowu 版本A1.0' git push origin master "
两周后...
产品经理: '小无,需求实现的怎么样了'
小无:'差不多快完事了,还有一小部分'
产品经理:'关于这块的需求,我又和其他同事讨论了一下,并且和总经理汇报了一下我们的讨论结果,还是想要使用方案A(最开始确认的需求),并且总经理综合的考虑了一下,也决定使用方案A,你看怎么弄一下'
小无:'心里无数个XXX踏过,深呼三口气,我这边需要再三确认一下,这次改完之后还会变吗'
产品经理:'这得看后续的情况'
小无:'...'
小无:'幸好上次修改需求前上传了一次git,感谢Linus写的git,感谢廖雪峰老师写的简单易懂的git教程,感谢上帝,感谢...不感谢啥了'
小无:"当前版本还是要保存一下的,避免..., git add. git commit -m '07/23 xiaowu 版本B2.0' git push origin master"
打代码(解决上述情况)
Number One :
$ git log // 查看最近到最远到提交日志
commit d00417b82faaa0f117f9fd1ba2abc55221a42018 (HEAD -> master, origin/master, origin/HEAD)
Author: xiaowuxiao <moumou@163.com>
Date: Tue Jul 23 15:38:40 2035 +0800
07/23 xiaowu 版本B2.0
commit a13f341b0ad909ee9e32b1f44dd42b9e889dd493
Author: xiaowuxiao <moumou@163.com>
Date: Tue Jul 15 11:23:11 2035 +0800
07/15 xiaowu 修改退出的问题
commit dae6a69b925148e38d7ad5b716ed056877c5f713
Author: xiaowuxiao <moumou@163.com>
Date: Tue Jul 9 18:26:36 2035 +0800
07/09 xiaowu 版本A1.0
// 看过廖雪峰老师教程的应该知道上述的“8ff3e681c709100906de9e0284d3459f98c2e263”这一长串是commit id (版本号)
如果感觉上述的信息有点多,可以加上 --pretty=oneline参数
$ git log --pretty=oneline
9c3c5a11743552f8919626676073abca90a29a65 (HEAD -> master,origin/master, origin/HEAD) 07/15 xiaowu 修改退出的问题
9c3c5a11743552f8919626676073abca90a29a65 07/15 xiaowu 修改退出的问题
dae6a69b925148e38d7ad5b716ed056877c5f713 07/09 xiaowu 版本A1.0
Number Two :
准备回退,首先我们必须要知道当前版本是多少,git中用HEAD表示当前版本,也就是d00417b...,那么上一个版本就是HEAD^, 上上一个版本HEAD^^,如果往上100个版本,那么就写成HEAD~100
现在我们要把版本后退到上上个版本,可以使用git reset命令
$ git reset --hard HEAD^^
HEAD is now at dae6a6 07/09 xiaowu 版本A1.0
现在我们用git log再看看现在版本库的状态:
$ git log
commit dae6a69b925148e38d7ad5b716ed056877c5f713 (HEAD -> master,origin/master, origin/HEAD)
Author: xiaowuxiao <moumou@163.com>
Date: Tue Jul 9 18:26:36 2035 +0800
07/09 xiaowu 版本A1.0
commit 9c3c5a11743552f8919626676073abca90a29a65
Author: xiaowuxiao <moumou@163.com>
Date: Tue Jul 2 14:25:08 2035 +0800
07/02 xiaowu 提取参数
现在我们已经看不到前两个版本了,如果过了一小会儿,产品经理又来说要改成版本B,是不是很抓狂,但是在git里面只要命令窗口没有关,我们就可以找到版本B的commit id 是 d00417b82,就可以指定回到未来的某个版本:
$ git reset --hard d00417b82
HEAD is now at d00417b82 07/23 xiaowu 版本B2.0
git 的版本回退速度非常快,git在内部有个指向当前版本的HEAD指针,当回退版本的时候,Git仅仅是把HEAD从指向07/23 xiaowu 版本B2.0:
┌────┐
│HEAD│
└────┘
│
└──> ○ 07/23 xiaowu 版本B2.0
│
○ 07/15 xiaowu 修改退出的问题
│
○ 07/09 xiaowu 版本A1.0
改为指向 07/09 xiaowu 版本A1.0
┌────┐
│HEAD│
└────┘
│
│ ○ 07/23 xiaowu 版本B2.0
│ │
○ 07/15 xiaowu 修改退出的问题
│ │
└──> ○ 07/09 xiaowu 版本A1.0
Warning:工作区的文件也对应更新,当我们要把工作区的代码push到远程库的时候,会遇到这样的问题:
On branch master Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded. (use "git pull" to update your local branch)
nothing to commit, working tree clean
造成这样问题的原因:
假设一开始你的本地和远程都是:
a -> b -> c
你想把HEAD回退到b,那么在本地就变成了:
a -> b
如果没有远程库的情况,下一步可以这么操作:
a -> b -> d
但是在有远程库的情况下,git push会失败,因为远程库是 a->b->c,但是工作区是 a->b->d:
针对这个问题参考廖雪峰老师有两种解决办法:
- 第一种:push的时候用 --force 强制把远程库变成a -> b -> d 但是一般公司不支持这样做,风险比较大
git push -f origin [branchName]
- 第二种:做一个反向操作,把自己本地变成a -> b -> c -> d,注意b和d文件快照内容一模一样,但是commit id肯定不同,再push上去远程也会变成 a -> b -> c -> d
简单地说就是你无法容易地抹去远程库的提交信息,所以本地提交怎么都行,push前想好了
针对第二种方法我现在还不是很理解,也在努力去尝试着理解
第二天
如果产品经理是第二天过来找你让你回退到版本B,这会儿你的命令窗口已经关闭了,该怎么办,是不是想分分钟把产品经理拖出去(。ì _ í。),不过幸好我们用的是git,当我们需要用$ git reset --hard HEAD^ 回退到版本B时,我们必须找到版本B的commit id。git的一个命令git reflog记录输入的每一个命令
$ git reflog
d00417b (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: commit: 07/23 xiaowu 版本B2.0
a13f341 HEAD@{1}: commit: xiaowu 修改退出的问题
ddae6a69 HEAD@{3}: commit: 07/09 xiaowu 版本A1.0
9c3c5a1 HEAD@{4}: commit: 07/08 wxm 提取参数
从上述我们可以看到版本B的commit id d00417b 现在就可以开森(无力)的回退到这个版本了,暂时写到这里,后续有补充...