首頁 > 軟體

Git的4個階段的復原更改

2020-06-16 17:01:46

雖然 git 誕生距今已有 12 年之久,網上各種關於 git 的介紹文章數不勝數,但是依然有很多人(包括我自己在內)對於它的功能不能完全掌握。以下的介紹只是基於我個人對於 git 的理解,並且可能生編硬造了一些不完全符合 git 說法的詞語。目的只是為了讓 git 通俗化,使初學者也能大概了解如何快速上手 git 。同時,下面所有討論,我們都假設只使用一個分支,也就是主分支 master 的情況,雖然這種作法並不符合 git 規範,但是現實情況中絕大部分使用者是直接在 master 分支上進行工作的,所以在這裡我們不去引入更加複雜的各種分支的情況,也不涉及標籤 tag 的操作,只講在最簡單的主分支上如何回退。

基本概念

3個步驟

正常情況下,我們的工作流就是 3 個步驟,對應上圖中的 3 個箭頭線:

git add .
git commit -m "comment"
git push
  1. git add . 把所有檔案放入 暫存區
  2. git commit 把所有檔案從 暫存區 提交進 本地倉庫
  3. git push 把所有檔案從 本地倉庫 推播進 遠端倉庫

4個區

git 之所以令人費解,主要是它相比於 svn 等等傳統的版本管理工具,多引入了一個 暫存區 ( Stage )的概念,就因為多了這一個概念,而使很多人疑惑。其實,在初學者來說,每個區具體怎麼工作的,我們完全不需要關心,而只要知道有這麼 4 個區就夠了:

  • 工作區( Working Area )
  • 暫存區( Stage )
  • 本地倉庫( Local Repository )
  • 遠端倉庫( Remote Repository )

5種狀態

以上 4 個區,進入每一個區成功之後會產生一個狀態,再加上最初始的一個狀態,一共是 5 種狀態。以下我們把這 5 種狀態分別命名為:

  • 未修改( Origin )
  • 已修改( Modified )
  • 已暫存( Staged )
  • 已提交( Committed )
  • 已推播( Pushed )

檢查修改

了解了基本概念之後,我們來談一談犯錯誤之後如何復原的問題。首先,我們要了解如何檢查這 3 個步驟當中每一個步驟修改了什麼,然後才好判斷有沒有修改成功。檢查修改的二級命令都相同,都是 diff ,只是引數有所不同。

已修改,未暫存

git diff

首先,我們來看一下,如果我們只是簡單地在瀏覽器裡儲存了一下檔案,但是還沒有做 git add . 之前,我們如何檢查有哪些修改。我們先隨便拿一個檔案來做一下實驗:

我們在檔案開頭的第 2 行胡亂加了 4 個數位 1234 ,存檔,這時檔案進入了 已修改 狀態,但是還沒有進入 暫存區 ,我們執行 git diff ,結果如下:

diff --git a/index.md b/index.md
index 73ff1ba..1066758 100644
--- a/index.md
+++ b/index.md
@@ -1,5 +1,5 @@
 ---
-layout: main
+1234layout: main
 color: black
 ---

git diff 的結果告訴我們哪些檔案已經做了哪些修改。

已暫存,未提交

git diff --cached

現在我們把修改放入 暫存區 看一下。先執行 git add . ,然後執行 git diff ,你會發現沒有任何結果:

這說明 git diff 這個命令只檢查我們的 工作區暫存區 之間的差異,如果我們想看到 暫存區本地倉庫 之間的差異,就需要加一個引數 git diff --cached

diff --git a/index.md b/index.md
index 73ff1ba..1066758 100644
--- a/index.md
+++ b/index.md
@@ -1,5 +1,5 @@
 ---
-layout: main
+1234layout: main
 color: black
 ---

這時候我們看到的差異是 暫存區本地倉庫 之間的差異。

已提交,未推播

git diff master origin/master

現在,我們把修改從 暫存區 提交到 本地倉庫 ,再看一下差異。先執行 git commit ,然後再執行 git diff --cached ,沒有差異,執行 git diff master origin/master ,可以看到差異:

 

在這裡, master 就是你的 本地倉庫 ,而 origin/master 就是你的 遠端倉庫master 是主分支的意思,因為我們都在主分支上工作,所以這裡兩邊都是 master ,而 origin 就代表遠端。

復原修改

了解清楚如何檢查各種修改之後,我們開始嘗試各種復原操作。

已修改,未暫存

如果我們只是在編輯器裡修改了檔案,但還沒有執行 git add . ,這時候我們的檔案還在 工作區 ,並沒有進入 暫存區 ,我們可以用:

git checkout .

或者

git reset --hard

來進行復原操作。

可以看到,在執行完 git checkout . 之後,修改已被復原, git diff 沒有任何內容了。

一對反義詞

git add . 的反義詞是 git checkout . 。做完修改之後,如果你想向前走一步,讓修改進入 暫存區 ,就執行 git add . ,如果你想向後退一步,復原剛才的修改,就執行 git checkout .

已暫存,未提交

你已經執行了 git add . ,但還沒有執行 git commit -m "comment" 。這時候你意識到了錯誤,想要復原,你可以執行:

git reset
git checkout .

或者

git reset --hard

git reset 只是把修改退回到了 git add . 之前的狀態,也就是說檔案本身還處於 已修改未暫存 狀態,你如果想退回 未修改 狀態,還需要執行 git checkout .

或許你已經注意到了,以上兩個步驟都可以用同一個命令 git reset --hard 來完成。是的,就是這個強大的命令,可以一步到位地把你的修改完全恢復到 未修改 的狀態。

已提交,未推播

你的手太快,你既執行了 git add . ,又執行了 git commit ,這時候你的程式碼已經進入了你的 本地倉庫 ,然而你後悔了,怎麼辦?不要著急,還有辦法。

git reset --hard origin/master

還是這個 git reset --hard 命令,只不過這次多了一個引數 origin/master ,正如我們上面講過的, origin/master 代表 遠端倉庫 ,既然你已經汙染了你的 本地倉庫 ,那麼就從 遠端倉庫 把程式碼取回來吧。

已推播

很不幸,你的手實在是太快了,你既 git add 了,又 git commit 了,並且還 git push 了,這時你的程式碼已經進入 遠端倉庫 。如果你想恢復的話,還好,由於你的 本地倉庫遠端倉庫 是等價的,你只需要先恢復 本地倉庫 ,再強制 push遠端倉庫 就好了:

git reset --hard HEAD^
git push -f

 

總結

以上 4 種狀態的復原我們都用到了同一個命令 git reset --hard ,前 2 種狀態的用法甚至完全一樣,所以只要掌握了 git reset --hard 這個命令的用法,從此你再也不用擔心提交錯誤了。

GitHub 教學系列文??: 

通過GitHub建立個人技術部落格圖文詳解  http://www.linuxidc.com/Linux/2015-02/114121.htm

GitHub 使用教學圖文詳解  http://www.linuxidc.com/Linux/2014-09/106230.htm 

使用 GitHub / GitLab 的 Webhooks 進行網站自動化部署  http://www.linuxidc.com/Linux/2016-06/131993.htm

多個GitHub帳號的SSH key切換 http://www.linuxidc.com/Linux/2016-05/131080.htm

如何在同一台電腦上使用兩個GitHub賬戶 http://www.linuxidc.com/Linux/2016-05/131079.htm

利用GitHub搭建個人Maven倉庫  http://www.linuxidc.com/Linux/2016-04/130197.htm

一分鐘認識GitHub http://www.linuxidc.com/Linux/2015-11/125089.htm

分享實用的GitHub 使用教學 http://www.linuxidc.com/Linux/2014-04/100556.htm 

GitHub使用操作指南  http://www.linuxidc.com/Linux/2016-10/135782.htm

GitHub使用方法入門基礎  http://www.linuxidc.com/Linux/2017-05/144084.htm


IT145.com E-mail:sddin#qq.com