沒想到,Git居然有后悔藥!
你知道Git版本控制系統中都有哪些“后悔藥”嗎?
本文通過案例講解
git reset 、 git revert 、 git checkout在版本控制中的作用;
場景
小明同學作為新人加入到一個新的專案組中做開發,在專案的迭代開發中,小明勤勤懇懇的寫代碼,直到有一次...
小明:完了,完蛋了
洋仔:怎么了,一驚一乍的
小明:我把錯誤代碼用git commit后還push到線上代碼庫了! 這可怎么辦!
洋仔:莫慌,git有“后悔藥”!

洋仔:容我給你慢慢道來, 但是我們要先知道一些git的基礎知識,你才能更好的理解git命令的作用
預備知識
git將專案的存盤分為4部分,每部分有自己作用,
見下圖:

Workspace:作業區(當前用戶操作修改的區域)Index / Stage:暫存區 (add后的區域)Repository:倉庫區或本地倉庫(commit后的區域)Remote:遠程倉庫(push后的區域)
整體程序可以簡述為:
- 作業區–>
add–>暫存區–>commit–>本地倉庫區–>push–>遠程倉庫區 - 遠程倉庫區–>
fetch–>使用refs\remotes下對應分支檔案記錄遠程分支末端commit_id 和 本地倉庫區 -->merge–>作業區 - 遠程倉庫區–>
pull–>使用refs\remotes下對應分支檔案記錄遠程分支末端commit_id and 本地倉庫區 and 作業區
具體的git的組成部分和概念命令,請移步下述兩個博客:
Git技術干貨!作業中Git的使用實踐和常用命令合集!
Git - 使用git不知道內部實作機制怎么行
假設專案存在這么一個提交記錄:
$ git log
commit commit_id4 (HEAD -> master)
Author: test
Date: Thu Aug 20 16:28:45 2020 +0800
第三次修改README檔案
commit commit_id3 (HEAD -> master)
Author: test
Date: Thu Aug 20 16:28:45 2020 +0800
第二次修改README檔案
commit commit_id2
Author: test
Date: Thu Aug 20 16:28:19 2020 +0800
第一次修改README檔案
commit commit_id1
Author: test
Date: Thu Aug 20 16:26:59 2020 +080
初始化專案
提交順序為:commit_id1 --> commit_id2 --> commit_id3 --> commit_id4
注意:在git中每次的commit都有一個commit id唯一標識當前的提交!
下面,我們先來解決小明的這個問題,使用git reset即可完美解決~
問題解決
洋仔:小明,你的這個就可以用git reset 這個命令來完美的搞定,下面我們看一下如何解決
1、獲取當前提交的commit id
命令:git log
獲取到當前專案分支下的所有commit記錄;
假設上述小明提交錯誤的commit id為commit id:commit_id4這一次提交;
他的上一次提交就是commit id:commit_id3 ,我們要將修改回滾到commit_id3的時刻!
小明:我想要把我剛才 commit的修改保留下來,我修改的代碼不能給我洗掉掉呀!
洋仔:沒問題
2、將某個commit id前的commit清除,并保留修改的代碼
命令:git reset <commit_id> 當前場景下就是:git reset commit_id3
將指定commit_id后的所有提交,都去除,并保留修改的代碼在本地的區域,也就是Workspace中
小明:啊哈,這樣的話我就可以把錯誤代碼修改后再提交了; 但是我已經push到線上倉庫的資料怎么辦呢?
洋仔:別急,有辦法~
3、修改代碼完成后,將修改好的代碼add到暫存區,并提交到本地倉庫中
命令:git add <file_name> and git commit 當前場景下:git add . and git commit
將最新修改后的代碼commit
則提交后的提交記錄假設如下: 可以看到,我們錯誤提交的commit_id4提交記錄消失,取而代之的是我們更新代碼后提交的記錄commit_id5; 這樣就完成了本地的代碼修改和更新
$ git log
commit commit_id5 (HEAD -> master)
Author: test
Date: Thu Aug 20 16:28:45 2020 +0800
第三次修改README檔案-更新錯誤后提交
commit commit_id3 (HEAD -> master)
Author: test
Date: Thu Aug 20 16:28:45 2020 +0800
第二次修改README檔案
commit commit_id2
Author: test
Date: Thu Aug 20 16:28:19 2020 +0800
第一次修改README檔案
commit commit_id1
Author: test
Date: Thu Aug 20 16:26:59 2020 +080
初始化專案
4、將本地修改同步到遠程倉庫
命令:git push origin HEAD --force
將本地修改強行同步到遠程倉庫,使得遠程倉庫和本地倉庫保持一致!
整體流程如下:
git log
git reset commit_id3
修改代碼
git add .
git commit -m '第三次修改README檔案-更新錯誤后提交'
git push origin HEAD --force
洋仔:好了,小明,你的問題完美解決了
小明:哦吼,但是我還有一個問題: 如果我想要不保留回滾commit的修改,直接洗掉掉修改!該怎么處理呢?
洋仔:簡單~ 我們整體看一下 git reset 命令
后悔藥-git reset
在進行下面的講解是,還是先假設有這么一個提交鏈:
commit_id1 --> commit_id2 --> commit_id3 --> commit_id4
git reset commit_id2:
reset是將HEAD重新定位到commit_id2上,對于commit_id3 和 commit_id4 和本地當前的修改,對于不同的引數param,會有不同的處理;
reset命令有三種處理模式:
- --soft:保留commit修改,將修改存盤到index中;也就是說git add后的區域
- --mixed:保留commit修改,將修改存盤到本地作業區域中;也就是說git add前的區域
- --hard:洗掉commit修改,慎用!
git reset --soft
回滾commit_id前的所有提交,不洗掉修改:
git reset --soft commit_id
重設head,不動index,所以效果是commit_id之后的commit修改全部在index中
將id3 和 id4的修改放到index區(暫存區),也就是add后檔案存放的區域,本地當前的修改保留
git reset --mixed
回滾commit_id前的所有提交,不洗掉修改:
git reset commit_id 等同于 git reset --mixed commit_id
與 下述的 git reset --hard commit_id效果不同
重設head 和 index,不重設work tree,效果就是commit_id之前的修改,全部在work tree中,為還未add的狀態
將id3 和 id4 的所有修改放到本地作業區中,本地當前的修改保留
git reset --hard
回滾commit_id前的所有提交,將修改全部洗掉:
git reset --hard commit_id
重設head、index、work tree,也就是說將當前專案的狀態恢復到commit_id的狀態,其余的全部洗掉(包含commit_id后的提交和本地還未提交的修改)
慎用!!
后悔藥-git revert
小明:原來git reset這么強大呀! 但是我這還有個問題:
如果想要只操作修改中間的一個commit,不對其他的commit產生影響; 也就是類似于我們只修改commit_id2,而對commit_id3 和 commit_id4無影響,該怎么處理呢?
洋仔:(這么多問題,幸虧我懂,要不這次就丟大了,,) 簡單! git revert 命令!
適用場景: 在專案開發中,突然發現在前幾次的提交中,有一次提交中包含一個bug; 當然我們可以進行一個新的修改,然后再提交一次; 但是,不優雅哈哈; 我們可以直接重做有bug的commit~
為什么不直接去再添加一個commit呢? git revert是用于“反做”某一個版本,以達到撤銷該版本的修改的目的,
比如,我們commit了三個版本(版本一、版本二、 版本三),突然發現版本二不行(如:有bug),想要撤銷版本二,但又不想影響撤銷版本三的提交,就可以用 git revert 命令來反做版本二,生成新的版本四,這個版本四里會保留版本三的東西,但撤銷了版本二的東西;
在revert命令中常用的就兩個:
- git revert -e <commit_id>:重做指定commit的提交資訊
- git revert -n <commit_id>:重做執行commit的代碼修改
git revert -e
重做commit_id的提交資訊,生成為一個新的new_commit_id
git revert -e commit_id
git revert -n
重做commit_id的提交
git revert -n commit_id
將commit_id中修改,放到index區,我們可以對他重新做修改并重新提交
revert vs reset
- git revert是用一次新的commit來回滾之前的commit,此次提交之前的commit都會被保留不動;
- git reset是回到某次提交,提交及之前的commit都會被保留,但是此commit id之后的修改都會被洗掉或放回作業區等待下一次提交;
小明:還有這種操作,可以直接單獨操作提交程序中的某一個commit! 太棒了!
后悔藥-git checkout
小明:還有最后一個問題:
如果我在一次開發中,發現某個檔案修改錯誤了,想要將檔案恢復到剛pull代碼時的狀態怎么辦呢?
洋仔:簡單! 看git checkout解決這個問題!
我們知道使用git checkout可以
-
git checkout <branch_name>切換分支 -
git checkout -b <branch_bame>創建分支等操作
它還有回滾指定檔案的修改的功能
命令:git checkout -- <file_name>
上述陳述句的作用,就是將file_name的本地作業區的修改全部撤銷,有兩種情況:
-
如果file_name在commit后沒有add過這個檔案,則撤銷到版本庫中的狀態
-
如果file_name在commit后add過這個檔案,則撤銷到暫存區的狀態,也就是add后的狀態
總之,就是讓指定的檔案回滾到最近的一次git add 或者 git commit時的狀態!
小明:太棒了,以后再也不怕提錯代碼了!
總結
上述,我們介紹了git reset \ git revert \ git checkout 在版本回滾、重做、撤銷修改方面的作用;
可以應用到作業中對 誤操作、不滿足要求、不滿足意愿的commit記錄的重做和修改;
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/997.html
標籤:其他
上一篇:專案微管理37 - 陣痛
下一篇:Git:RPC failed; HTTP 413 curl 22 The requested URL returned error: 413
