Git版本回退
Git中,每次commit提交都会生成一个历史纪录。使用 git log 查看commit历史:1
2
3
4
5
6
7
8
9
10$ git log --oneline
ec88247 modifyed bar.html,foo.txt add new.txt
47384c8 modify bar.html in clone again
31e1f6f modify foo.txt in original again
8747b24 Merge branch 'master' of /home/mrbird/projects/first-project
27b76ec modify foo.txt in original
796e40d modify bar.html in clone
8e1b132 modify foo.txt,add 'hello msg'
94418b1 add bar.html,modify foo.txt,delete bar.txt
c2e4810 add foo.txt bar.txt
每个记录都有一个与之对应的commit id,所以可以使用命令 git reset –hard commit-id 来回退到相应的版本。除此之卡,在Git中,使用HEAD来代表当前版本,如需回退到前一个版本,可以使用命令git reset --hard HEAD^,前两个版本则用HEAD~2表示,以此类推。
当前版本id为ec88247…比如,现要回退到commit_id为47384c8…的版本,可以使用如下命令:1
2$ git reset --hard 47384c8
HEAD is now at 47384c8again modify bar.html in clone
或者1
2$ git reset --hard HEAD~1
HEAD is now at 47384c8 modify bar.html in clone again
再次查看commit历史1
2
3
4
5
6
7
8
9$ git log --oneline
47384c8 modify bar.html in clone again
31e1f6f modify foo.txt in original again
8747b24 Merge branch 'master' of /home/mrbird/projects/first-project
27b76ec modify foo.txt in original
796e40d modify bar.html in clone
8e1b132 modify foo.txt,add 'hello msg'
94418b1 add bar.html,modify foo.txt,delete bar.txt
c2e4810 add foo.txt bar.txt
可发现,commit_id为ec88247…的记录已经不见了,如果要回退到这个版本,又忘记了与之对应的commit_id该怎么办呢。这时候可以使用 git reflog 命令来查看操作历史:1
2
3
4$ git reflog
47384c8 HEAD@{0}: reset: moving to 47384c8
ec88247 HEAD@{1}: reset: moving to ec88247
...
可看到,回退到commit_id为47384c8…的上一个版本的commit_id为ec88247…,所以,使用如下命令即可回到一开始回退前的版本:1
2$ git reset --hard ec88247
HEAD is now at ec88247 modifyed bar.html,foo.txt add new.txt
Git回退的三种类型: git reset
Git版本回退:reset和revert的区别和使用场景
(1):未使用git add缓存代码
git checkout – filepathname 进行放弃文档修改。
git checkout . 放弃所有的文档修改。
该命令不会删除掉刚新建的文档。
(2):没有push(本地分支版本回退)
这种情况发生在你的本地代码仓库,可能你add ,commit 以后发现代码有点问题,准备取消提交,用到下面命令。1
2
3
4
5//找到需要回退的版本commit id
git reflog
// 回退版本
git reset [--soft | --mixed | --hard
git reset HEAD
(3):已经push(公共远程分支版本)
对于已经把代码push到线上仓库,你回退本地代码其实也想同时回退线上代码,回滚到某个指定的版本,线上,线下代码保持一致。你要用到下面的命令。1
2
3git revert HEAD //撤销最近一次提交
git revert HEAD~1 //撤销上上次的提交,注意: 数字从0开始。
git revert commit_id //撤销commit_id这次提交
git revert用于反转提交,执行evert命令时要求工作树必须是干净的.
git revert用一个新提交来消除一个历史提交所做的任何修改.
revert 之后你的本地代码会回滚到指定的历史版本,这时你再 git push 既可以把线上的代码更新.(这里不会像reset造成冲突的问题)。
revert 使用,需要先找到你想回滚版本唯一的commit标识代码,可以用 git log 或者在adgit搭建的web环境历史提交记录里查看。通常是前几位即可。
特别注意:不要使用下面方式来回滚公共远程分支版本(使用reset+push -f命令)。因为同事的本地分支并没有主动回退。(如果是一个人开发的,可以这样做)1
2
3
4//找到回退的版本
git reflog
git reset --hard HEAD~1(commit_id)
git push -frevert是撤销一次提交,所以后面的commit id是你需要回滚到的版本的前一次提交。
使用revert HEAD是撤销最近的一次提交,如果你最近一次提交是用revert命令产生的,那么你再执行一次,就相当于撤销了上次的撤销操作,换句话说,你连续执行两次revert HEAD命令,就跟没执行是一样的。
使用revert HEAD~1 表示撤销最近2次提交,这个数字是从0开始的,如果你之前撤销过产生了commi id,那么也会计算在内的。
如果使用 revert 撤销的不是最近一次提交,那么一定会有代码冲突,需要你合并代码,合并代码只需要把当前的代码全部去掉,保留之前版本的代码就可以了。
(4):区别
git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commitgit reset只是在本地仓库中回退版本,而远程仓库版本不会变化。这样,即使本地reset,但是如果在git pull,
那么远程仓库内容又会和本地之前版本内容进行merge。
上面我们说的如果你已经push到线上代码库, reset 删除指定commit以后,你git push可能导致一大堆冲突。但是revert 并不会。
如果在日后现有分支和历史分支需要合并的时候,reset 恢复部分的代码依然会出现在历史分支里。但是revert 方向提交的commit 并不会出现在历史分支里。
reset 是在正常的commit历史中,删除了指定的commit,这时 HEAD 是向后移动了,而 revert 是在正常的commit历史中再commit一次,只不过是反向提交,他的 HEAD 是一直向前的。
(4):实例
下面来看一个revert的使用例子
创建A.txt 内容为AAAA。然后添加到git1
2
3git add .
git commit -m "A.txt"
12
修改A.txt 添加内容”BBBB”。然后添加到git1
2
3git add .
git commit -m "A.txt add BBBB"
12
此时A.txt文档内容如下1
2
3AAAA
BBBB
12
此时的提交记录:1
2
3
4
5
6
7
8
9
10
11
12
13
14git log
---
commit 329515ee5d367bda3effa3e8f0c958e98e93ce31
Author: *****
Date: Tue Mar 6 19:25:39 +0800
A.txt add BBBB
commit fe0d9b1d7ed0176f542a52835b1923584a4ba060
Author: *****
Date: Tue Mar 6 19:24:34 +0800
A.txt
12345678910111213
现在我要撤回内容BBBB,如下1
2git revert 329515
1
现在A.txt里的文档内容变为:1
2AAAA
1
再次查看提交记录:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22git log
---
commit 23880e1f7649b7dca14cfda7553b2ff2e6088d6e
Author: *****
Date: Tue Mar 6 19:29:35 +0800
Revert "A.txt add BBBB"
This reverts commit 329515ee5d367bda3effa3e8f0c958e98e93ce31.
commit 329515ee5d367bda3effa3e8f0c958e98e93ce31
Author: *****
Date: Tue Mar 6 19:25:39 +0800
A.txt add BBBB
commit fe0d9b1d7ed0176f542a52835b1923584a4ba060
Author: *****
Date: Tue Mar 6 19:24:34 +0800
A.txt
12345678910111213141516171819
可以看到我们撤回了提交的内容同时增加了一条commit记录。
如果撤回到之前版本出现冲突怎么办?我们先回到329515版本1
2git reset --hard 329515
1
恢复后在往里面添加内容“CCCC”并提交。
此时A.txt文档内容为:1
2
3
4AAAA
BBBB
CCCC
123
此时的提交记录:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20git log
---
commit f1258438d3b63e78bb747c510f9af3e56be5b3b0
Author: *****
Date: Tue Mar 6 19:39:20 +0800
A.txt add CCCC
commit 329515ee5d367bda3effa3e8f0c958e98e93ce31
Author: *****
Date: Tue Mar 6 19:25:39 +0800
A.txt add BBBB
commit fe0d9b1d7ed0176f542a52835b1923584a4ba060
Author: *****
Date: Tue Mar 6 19:24:34 +0800
A.txt
12345678910111213141516171819
然后我们撤回329515的修改1
2git revert 329515
1
这个时候git提示你有冲突要解决。我们打开A.txt保留parent … 329515这个版本的内容(git add A.txt),即”AAAA”。并执行以下命令1
2git revert --continue
1
这个时候git会继续撤回,如果发现冲突会继续提示。此时的提交日志为1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26commit 78979e45add34a0f009263e49cc1c6c48a0f93d4
Author: *****
Date: Tue Mar 6 19:46:40 +0800
Revert "A.txt add BBBB"
This reverts commit 329515ee5d367bda3effa3e8f0c958e98e93ce31.
commit f1258438d3b63e78bb747c510f9af3e56be5b3b0
Author: *****
Date: Tue Mar 6 19:39:20 +0800
A.txt add CCCC
commit 329515ee5d367bda3effa3e8f0c958e98e93ce31
Author: *****
Date: Tue Mar 6 19:25:39 +0800
A.txt add BBBB
commit fe0d9b1d7ed0176f542a52835b1923584a4ba060
Author: *****
Date: Tue Mar 6 19:24:34 +0800
A.txt
1234567891011121314151617181922232425
如果不想解决冲突的话可以取消撤回:git revert --abort。
(5):revert合并代码,解决冲突
使用revert命令,如果不是撤销的最近一次提交,那么一定会有冲突,如下所示:1
2
3
4
5
6<<<<<<< HEAD
全部清空
第一次提交
=======
全部清空
>>>>>>> parent of c24cde7... 全部清空
解决冲突很简单,因为我们只想回到某次提交,因此需要把当前最新的代码去掉即可,也就是HEAD标记的代码:1
2
3
4<<<<<<<
HEAD全部清空
第一次提交
=======
把上面部分代码去掉就可以了,然后再提交一次代码就可以解决冲突了。
(6):继续扩展,简单扩展的回滚方法
看到这里也许你已经觉得学会了远程仓库版本回滚方法了,但是实践中总是会遇到很多不按套路来的问题,考虑下面一种情况:
这个时候,可以使用简单粗暴的办法,直接从那个错误的提交的前一次拉取一份代码放到其他目录,然后将master代码全部删除,把那份新代码方进去,然后提交,果然简单粗暴啊,虽然这种方法不入流,但是,实践中发现很好使啊,所以,实践是检验真理的唯一标准。遇到问题还是要灵活应对。
(7): 撤销文档三种情况
场景1:当你改乱了工作区某个文档的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。
场景2:当你不但改乱了工作区某个文档的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD ,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。