封面.jpg
關(guān)于 git 的基本理解剔氏, 在第一篇git文章已介紹搬男。 上一篇文章主要講解了git的提交操作锅锨, 本篇在上篇基礎(chǔ)上著重寫git代碼的逆向操作:代碼回退靠娱。網(wǎng)上關(guān)于git回退的文章比較多柬脸, 本文是個人理解實踐的匯總, 不當、不全之處請評論區(qū)指出宾巍。
首先,回顧下git代碼存在的5個區(qū)域渔伯, 分別是 工作區(qū)間顶霞、工作現(xiàn)場、緩存區(qū)(或叫暫存區(qū))锣吼、本地倉庫(或叫當前分支)选浑、遠程倉庫(或叫遠程分支);如下圖:
1.png
1.緩存區(qū)代碼覆蓋工作區(qū)代碼
場景: 緩存區(qū)存有上次改動代碼玄叠,即之前有執(zhí)行:
git add
```
當前**工作區(qū)間**代碼想廢棄古徒, 可將**緩存區(qū)**中代碼覆蓋之:
![3.png](http://upload-images.jianshu.io/upload_images/615809-b6283ed165397d5f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**對應(yīng)指令:**
```
// 將緩存區(qū)某一文件代碼 覆蓋本地工作區(qū):
git checkout -- testReset.txt
// 將匹配的文件覆蓋:
git checkout -- *.txt
// 將所有文件覆蓋:
git checkout -- .
```
# 2.本地倉庫代碼覆蓋緩存區(qū)代碼
場景:發(fā)現(xiàn)之前add的文件不需要了,又不想**工作區(qū)間**重新改回去读恃。
![4.jpeg](http://upload-images.jianshu.io/upload_images/615809-530852aee221207b.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**對應(yīng)指令:**
```
// 將本地倉庫某一文件覆蓋緩存區(qū):
git reset HEAD testReset.txt
// 將匹配的文件覆蓋緩存區(qū):
git reset HEAD *.txt
// 將所有文件覆蓋緩存區(qū):
git reset HEAD .
```
注意: 改變的是**緩存區(qū)**代碼隧膘, **工作區(qū)間**代碼不變(編輯器代碼不會改變)
# 3.本地倉庫代碼覆蓋工作區(qū)代碼(常用)
上述兩場景在實際開發(fā)中沒那么常用,接下來 **本地倉庫** 代碼 覆蓋 **工作區(qū)間 **代碼 則經(jīng)常會用到寺惫。
場景: 當前 **工作區(qū)間** 代碼混亂(一般更新或合并分支后) 疹吃, 廢棄當前改動;
![5.png](http://upload-images.jianshu.io/upload_images/615809-06b2d06489ebb0cb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**對應(yīng)指令:**
```
// 將本地倉庫某一文件代碼 覆蓋本地工作區(qū):
git checkout head testReset.txt
// 將本地倉庫所有文件代碼 覆蓋本地工作區(qū):(謹慎操作):
git checkout head .
```
我們知道**本地倉庫**中有一個commit 列表西雀, 記錄了所有commit的記錄萨驶, 查看commit列表指令:
```
// 查看commit id, 查看提交記錄(git commit的記錄)
git log
git log --pretty=oneline
// 查看以往提交歷史(包括 撤銷回退 記錄)
git reflog
```
![6.png](http://upload-images.jianshu.io/upload_images/615809-5536c973563a7f39.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
根據(jù)commit列表艇肴, **工作區(qū)間**代碼能實現(xiàn)更靈活的回退:
```
// 本地工作區(qū)間代碼 回退到上一次版本腔呜、上上次、前10個版本
git reset --hard HEAD^
git reset --hard HEAD^^
git reset --hard HEAD~10
// 本地工作區(qū)間代碼 回退到指定版本(“d362816”為commit id)
git reset --hard d362816
```
# 4.遠程倉庫代碼覆蓋本地倉庫代碼(清除 未push 的commit)
場景: 有時候合并分支再悼、切換分支育谬、更新代碼會導(dǎo)致提交絮亂的問題(沒使用--rebase方式),具體體現(xiàn)在自動生成了commit且**工作區(qū)間** 代碼很多沖突帮哈。使**工作區(qū)間**代碼跟線上代碼一致且刪除新生成的commit膛檀。
![7.png](http://upload-images.jianshu.io/upload_images/615809-8f87fdd8461d2232.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**對應(yīng)指令:**
```
// 本地工作區(qū)間代碼回退到遠程版本
git reset –-hard origin/master
```
寫到了git reset指令, 就不得不說下它與 git revert 的區(qū)別:
> 1. git revert是用一次新的commit來回滾之前的commit娘侍,git reset是直接刪除指定的commit咖刃。
> 2. 在回滾這一操作上看,效果差不多憾筏。但是在日后繼續(xù)merge以前的老版本時有區(qū)別嚎杨。因為git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch時氧腰,導(dǎo)致這部分改變不會再次出現(xiàn)枫浙,但是git reset是直接把某些commit在某個branch上刪除刨肃,因而和老的branch再次merge時,這些被回滾的commit應(yīng)該還會被引入箩帚。
> 3. git reset 是把HEAD向后移動了一下真友,而git revert是HEAD繼續(xù)前進,只是新的commit的內(nèi)容和要revert的內(nèi)容正好相反紧帕,能夠抵消要被revert的內(nèi)容盔然。
git reset 與 git revert區(qū)別圖:
![8.png](http://upload-images.jianshu.io/upload_images/615809-6a56dbb1295896a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![9.png](http://upload-images.jianshu.io/upload_images/615809-cc57f6657b49ce6d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
# 5.遠程倉庫代碼回滾(線上代碼回滾)
場景: 提交了一個commit(該提交包含很多文件), 發(fā)現(xiàn)有問題是嗜, 需要回滾愈案, 將線上分支(master)回滾到上一次commit;
網(wǎng)上有刪除分支進行線上代碼回滾的教程, 那種操作其實很危險鹅搪, 因為一般線上的分支是master分支站绪, 而這個分支不允許刪除。
合理一些的是使用 git reset或git revert方式進行回滾丽柿;
**git reset方式圖解:**
![10.png](http://upload-images.jianshu.io/upload_images/615809-a569b67b955fed97.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**git revert方式圖解:**
![11.png](http://upload-images.jianshu.io/upload_images/615809-05f9b43a8565df67.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
我們可以使用git revert將新的commit替換掉;(不用git reset而用git revert的原因是保留commit方便后續(xù)代碼恢復(fù))
**對應(yīng)指令:**
```
// 替換掉上次提交的代碼文件(上次的commit記錄會保留)
git revert HEAD
git commit -m "回滾上次commit"
git push origin master
```
參考資料:
[時光機穿梭 - 廖雪峰的官方網(wǎng)站](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013743858312764dca7ad6d0754f76aa562e3789478044000)
[GitHub - wteam-xq/testGit: git學(xué)習恢准、博文測試工程](https://github.com/wteam-xq/testGit)
[Git HowTo: revert a commit already pushed to a remote repository](http://christoph.ruegg.name/blog/git-howto-revert-a-commit-already-pushed-to-a-remote-reposit.html)
相關(guān)文章:
[Git 圖解(1):代碼區(qū)域總結(jié)](http://www.reibang.com/p/898e766d22e1)
[Git 圖解(3):分支操作](http://www.reibang.com/p/342a9f8db004)