1、status命令與diff命令
前面我們已經成功地添加並提交了一個readme.txt文件,修改readme.txt如下:
echo "Git is a distributed version control system. " > readme.txt echo "Git is free software." >> readme.txt
運行git status命令看看結果:
$ git status ... no changes added to commit (use "git add" and/or "git commit -a")
git status命令可以讓我們時刻掌握倉庫當前的狀態,上面顯示,readme.txt被修改過了,但還沒有准備提交的修改。
git diff這個命令看看:
$ git diff readme.txt ... -Git is version control system. +Git is a distributed version control system. Git is free software
git diff顧名思義就是查看difference,顯示的格式正是Unix通用的diff格式,可以從上面的命令輸出看到,我們在第一行添加了一個“distributed”單詞。
readme.txt作了什麼修改後,再把它提交到倉庫,提交修改和提交新文件是一樣的兩步,git add和git commit:
$ git add readme.txt $ git commit -m "add distributed"
注意
2、版本回退
現在,再練習一次,修改readme.txt文件如下:
echo "Git is a distributed version control system." > readme.txt echo "Git is free software distributed under the GPL." >> readme.txt
我們再次提交一次readme.txt
$ git add readme.txt $ git commit -m "append GPL"
我們現在已經提交多次文件,想看看有那些?版本控制系統肯定有某個命令可以告訴我們歷史記錄,在Git中,我們用git log命令查看:
$ git log commit 3628164fb26d48395383f8f31179f24e0882e1e0 Date: Tue Aug 25 15:11:49 2015 +0000 append GPL commit ea34578d5496d7dd233c827ed32a8cd576c5ee85 Date: Tue Aug 25 14:53:12 2015 +0000 add distributed commit cb926e7ea50ad11b8f9e909c05226233bf755030 Date: Mon Aug 24 17:51:55 2015 +0000 wrote a readme file
git log命令顯示從最近到最遠的提交日志,我們可以看到3次提交,最近的一次是append GPL,上一次是add distributed,最早的一次是wrote a readme file。commit 36281**2e1e0是commit id(版本號)。如果嫌輸出信息太多,可以使用$ git log --pretty=oneline,此時你看到的一大串類似3628164...882e1e0的是commit id(版本號)。
每提交一個新版本,實際上Git就會把它們自動串成一條時間線。現在准備把readme.txt回退到上一個版本,也就是“add distributed”的那個版本,怎麼做呢?
首先,Git必須知道當前版本是哪個版本,在Git中,用HEAD表示當前版本,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一樣),上一個版本就是HEAD^,上上一個版本就是HEAD^^,當然往上100個版本寫100個^比較容易數不過來,所以寫成HEAD~100。
現在,我們要把當前版本“append GPL”回退到上一個版本“add distributed”,就可以使用git reset命令:
$ git reset --hard HEAD^ HEAD is now at ea34578 add distributed
3、重新恢復到新版本
接著上節版本回退,還可以繼續回退到上一個版本wrote a readme file,不過我們現在看看版本庫的狀態git log:
$ git log
最新的那個版本append GPL已經看不到了!好比你從21世紀坐時光穿梭機來到了19世紀,想再回去已經回不去了,腫麼辦?
只要右側環境還在,就可以找到那個append GPL的commit id是3628164...,於是就可以指定回到未來的某個版本:
$ git reset --hard 3628164 HEAD is now at 3628164 append GPL
版本號沒必要寫全,前幾位就可以了,Git會自動去找。當然也不能只寫前一兩位,因為Git可能會找到多個版本號,就無法確定是哪一個了。
可以查看readme.txt的內容 $ cat readme.txt .
Git的版本回退速度非常快,因為Git在內部有個指向當前版本的HEAD指針,當你回退版本的時候,Git僅僅是把HEAD從指向append GPL改為指向add distributed。
4、git reflog命令
現在,你回退到了某個版本,當想恢復到新版本怎麼辦?找不到新版本的commit id怎麼辦?
在Git中可以放心下。當你用$ git reset --hard HEAD^回退到add distributed版本時,再想恢復到append GPL,就必須找到append GPL的commit id。Git提供了一個命令git reflog用來記錄你的每一次命令:
$ git reflog ea34578 HEAD@{0}: reset: moving to HEAD^ 3628164 HEAD@{1}: commit: append GPL ea34578 HEAD@{2}: commit: add distributed cb926e7 HEAD@{3}: commit (initial): wrote a readme file
這樣可以看到,第二行顯示append GPL的commit id是3628164,這樣我們就可以重新找到了。
注意,我們從這兩節中可以了解到:
5、基本概念
工作區:就是你在電腦裡能看到的目錄,learngit文件夾就是一個工作區,比如我們環境中當前的目錄。
版本庫:工作區有一個隱藏目錄.git 這個不算工作區,而是Git的版本庫。
暫存區:英文叫stage,或index。一般存放在git 目錄下的index文件(.git/index)中,所以我們把暫存區時也叫作索引(index).
Git的版本庫裡存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD。
我們把文件往Git版本庫裡添加的時候,是分兩步執行的:
因為我們創建Git版本庫時,Git自動為我們創建了唯一一個master分支,所以現在git commit就是往master分支上提交更改。
你可以簡單理解為,需要提交的文件修改通通放到暫存區,然後一次性提交暫存區的所有修改。
實踐理解暫存區
現在我們對readme.txt做個修改,比如追加一行內容:
echo "Git has a mutable index called stage." >> readme.txt
然後,在工作區新增一個LICENSE文本文件
echo "LICENSE is a new file." > LICENSE
用git status查看一下狀態,Git顯示結果,readme.txt被修改了,而LICENSE還從來沒有被添加過,所以它的狀態是Untracked。
現在,使用兩次命令git add,把readme.txt和LICENSE都添加後,用git status再查看一下,通過圖可以理解為:
所以,git add命令實際上就是把要提交的所有修改放到暫存區(Stage),然後,執行git commit就可以一次性把暫存區的所有修改提交到分支。
$ git commit -m "understand how stage works"
一旦提交後,如果你又沒有對工作區做任何修改,用git status查看下,沒有任何內容,現在版本庫變成了這樣,暫存區就沒有任何內容了: