1. 程式人生 > >git暫存區[重要]

git暫存區[重要]

本篇來討論git的核心,暫存區。首先上一張圖。

git暫存區

左側是工作區,也就是我們本地電腦上的檔案,中間的Index就是我們討論的暫存區,右側是HEAD。HEAD是一個頭指標,我會在下一篇部落格中討論HEAD,此處你先理解為HEAD就是git版本庫。

上面的這張圖,非常非常地重要,如果我下面討論的東西你有不明白的,這張圖可能都會給你答案。

其實,git的絕大部分的操作都是在將檔案在工作區、暫存區和版本庫中移來移去,就拿上一篇部落格中使用的git addgit commit來說吧,git add是把檔案從工作區複製到暫存區,git commit又把檔案從暫存區複製到或提交到了版本庫。

下面通過一些簡單的場景,把上面的命令都串一遍。
首先,通過git init

命令初始化一個空的版本庫,然後新增兩個新的檔案,分別是a.txt和b.txt。此時,工作區有兩個檔案,暫存區沒有檔案,版本庫也沒有檔案。

git add

git add a.txt b.txt

上面的命令將a.txt和b.txt檔案從工作區複製到了暫存區。這時三個區域的目錄結構是這樣的

  • 工作區:a.txt , b.txt
  • 暫存區:a.txt , b.txt
  • 版本庫:空

git commit

git commit -m '新增了a.txt和b.txt檔案'

上面的命令將暫存區的所有檔案複製到版本庫。這時三個區域的目錄結構就一樣了,都包含a.txt 和 b.txt。

git checkout

git checkout --<file>命令是用暫存區的某個檔案來覆蓋工作區,經常用於撤銷一些修改,這個命令比較危險,因為會修改工作區,且無法撤銷。假設我們現在需要正在編輯a.txt,並且假設需要寫兩段話,寫完第一段時,我們可以通過git add a.txt將a.txt複製到暫存區,這樣的話,如果在寫第二段時寫錯了,我們可以直接通過git checkout --a.txt來回到第一段完成時的樣子。
也就是說,git checkout --<file>是用來使工作區回到上次操作git add時的樣子。

git checkout HEAD

git checkout HEAD <file>

命令是用版本庫來同時覆蓋暫存區和工作區,用來徹底撤銷一個修改,這個命令更加危險,因為它會同時修改工作區和暫存區,且無法撤銷。還假設你想在a.txt中寫兩段話,寫完第一段時,使用git add a.txt命令先備份到暫存區,然後接著寫第二段,寫著寫著發現思路全錯了,就可以通過git checkout HEAD a.txt將工作區和暫存區中a.txt的修改都撤銷掉,回到上次提交之前的樣子。這個命令要慎用。

git reset HEAD

git reset HEAD <file>命令通常用來撤銷git add操作。假設你新增了一個c.txt檔案,並通過git add c.txt將此檔案複製到了暫存區,但你很快就發現其實這個檔案沒必要提交,你可以使用git reset HEAD c.txt命令,它的本質是使用版本庫來覆蓋暫存區,由於版本庫還沒有c.txt,所以,覆蓋後,暫存區也就沒有了c.txt,從而實現了對git add命令的撤銷。

git rm –cached

git rm --cached <file>命令是將一個檔案從暫存區刪除。那麼這有啥用呢?其實還是挺有用的。假設你有一個已經提交到版本庫的檔案,你發現這個檔案其實不應該提交上去(例如配置檔案,每個人的都不一樣,經常造成衝突),但又不能直接刪掉,假設這個檔案的名字叫做user.config,你可以這麼操作:

  1. 通過git rm --cached user.config命令將此檔案從暫存區刪除
  2. 通過修改.gitignore檔案,把user.config加到檔案中,使git忽略這個檔案
  3. 通過git commit -m 'XXX'命令,用暫存區覆蓋版本庫。由於暫存區沒了這個檔案,覆蓋後,版本庫也就沒了這個檔案,這個檔案就被這麼從版本庫刪掉了,但是它還留在你的工作區。

是不是有點繞?沒關係,多看看最上面的那張圖,答案都在那裡。