6、Git基礎操做之撤銷操做

版本控制的關鍵是可撤銷性,便可以使項目回退到某些操做以前狀態。Git做爲一款很是優秀的版本控制軟件具有了豐富的撤銷的命令來應對不一樣的場景,下面咱們來學習一下。html

1.修改最後一次提交

命令:`git commit --amend`
做用:本次提交覆蓋上次提交,以此達到修改上次提交的目的。
複製代碼

1.1 未修改直接提交

未修改直接再次提交
值得注意的是,兩次提交的項目內容和提交人沒有變化,可是因爲提交的時間不一樣,致使commit對象的內容不一樣,所以產生內容的ID也不相同。

1.2 修改後再提交

修改後再提交

2. reset、revert和checkout

Git使用reset、revert和checkout三個命令來回退項目到某一個歷史快照。
回退有兩個影響級別:
1) commit級別:根據指定的commit來恢復項目總體到歷史的某一快照。
2) 文件級別:根據指定commit和文件路徑來恢復指定文件到某一歷史版本。
複製代碼

2.1 commit級別回退

1)回退Git倉庫

  • 命令:git reset --soft [commit]
  • 做用:把HEAD引用的當前分支的commit引用移動到指定commit,以此達到回退的目的。

恢復git倉庫到上一次提交
從新根據reset命令撤銷剛纔的撤銷操做(是否是有點繞口)
撤銷剛纔的撤銷操做
恢復到撤銷前的狀態

2)回退Git倉庫和暫存區

  • 命令:git reset [commit]/git reset --mixed [commit]
  • 做用:本命令會恢復Git倉庫到指定commit,並根據指定commit清空覆蓋暫存區(不會提示衝突,由於是強行覆蓋)。
  • 結果:1)不在指定commit的文件樹中的工做區的目錄和文件會變成未跟蹤狀態;2)與指定commit的文件樹中的內容不一樣的文件會變成已修改狀態,待加入暫存區。

回退Git倉庫和暫存區

3)回退Git倉庫、暫存區和工做區

git reset
  • 命令:git reset --hard [commit]
  • 做用:根據指定commit的文件樹,覆蓋git倉庫和暫存區,清空工做區全部已跟蹤文件而後以指定commit的內容代替。
  • 結果:1)只有工做區內處於未跟蹤狀態的目錄和文件會維持原來狀態;2)其餘文件都會與指定commit內容具備相同內容。

git reset --hard
未跟蹤文件不被清除

git revert
  • 命令1:git revert [commit] 做用:打補丁的形式撤銷某次歷史版本;
  • 命令2:git revert -n [commit]..[commit] 做用:撤銷一個commit區間
  • 原理:根據diff操做計算出指定commit與其以前commit的內容差別,針對該差別計算出反補丁,應用反補丁到當前git倉庫、暫存區和工做區,併產生一次提交。
  • 條件:1)保持暫存區clean狀態;2)工做區不能有和revert補丁衝突的處於已修改狀態的文件,例如不能修改同一行等。

git revert
revert的衝突狀況

4)reset和revert的區別

初始狀態

  • git reset不會產生新的提交,只經過移動HEAD引用的分支指向的commit來恢復項目快照。
    初始狀態執行git rest HEAD~後結果
  • git revert不會影響已有歷史,它會產生新的提交來撤銷某次或必定範圍的修改。
    初始狀態執行git revert HEAD後結果
  • 區別列表
命令 git reset git revert
原理 改變分支的commit的引用 對已有commit引用打反補丁
反作用 改變commit歷史 不會改變commit歷史
適用性 本地分支 公共分支
衝突 無衝突 會有衝突
優勢 無衝突的恢復到某次歷史快照 可針對中間的某次提交進行撤銷操做
本質 覆蓋操做 修補操做

2.2 文件級別回退

1)回退暫存區文件

  • 命令:git reset [commit] [file],如果commit是HEAD可替換爲--
  • 做用:根據指定commit,撤銷暫存區指定文件的操做;
  • 結果:若新增,則刪除;若刪除和修改,則恢復。

2)回退工做區文件

  • 命令1:git checkout file
  • 做用:把暫存區文件檢出到工做區;
  • 命令2:git chekcout [commit] [file],如果commit是HEAD可替換爲--
  • 做用:根據指定commit,從git倉庫檢出指定文件到暫存區工做區

3.提交樹

Git中每次提交都會存儲在Git倉庫,只是有些提交通過reset、刪除分支、刪除儲藏等操做後不被分支和標籤引用,變成懸掛狀態(dangling)。咱們能夠經過如下命令查看這些提交(Git的提交樹和vim的undo樹殊途同歸)。node

1)完整提交樹

  • 命令:git log -ggit reflog來查看
  • 做用:顯示全部操做,包括撤銷的。

2)有效提交樹

  • 命令:git log查看
  • 做用:顯示當前有效的操做

3)撤銷的懸掛提交(dangling commit)

  • 命令:git fsck --lost-found
  • 做用:經過校驗Git倉庫的完整性(經過引用鏈),找出懸掛對象。

4)一圖以蔽之

提交樹

4.儲藏和恢復

因爲revert、分支合併等場景下的操做會與工做區和暫存區的內容產生衝突,若不想提交當前工做區和暫存區的修改內容,能夠經過儲藏命令將其儲藏起來,而後在合適的時候恢復工做區和暫存區。git

git stash       # 儲藏當前工做區和暫存區
git stash list  # 查看當前的儲藏列表
git stash apply # 恢復上一次的儲藏內容
git stach pop   # 恢復上一次的儲藏內容,並將其從儲藏區刪除
複製代碼

5.清除未跟蹤文件

  • 命令1:git clean -f 做用:刪除未跟蹤文件
  • 命令2:git clean -df 做用:刪除未跟蹤文件和目錄
  • 通常與git reset --hard命令搭配使用。
git reset --hard commit  # 恢復git倉庫、暫存區和工做區(不包含未跟蹤內容)到指定commit
git clean -df # 刪除當前處於未跟蹤狀態的文件和目錄
git status # 當前處於commit,且暫存區和工做區都處於clean狀態
複製代碼

參考

  1. 代碼回滾:git reset、git checkout和git revert區別和聯繫
  2. 在 git 中找回丟失的 commit
  3. Git 工具 - 儲藏(Stashing)
  4. Git的"~"和"^"的區別
相關文章
相關標籤/搜索