目錄
1.添加文件—場景一
2.查看.git文件
3.添加文件—場景三
4.修改文件
5.版本回退
6.撤銷修改
7.刪除文件
1.添加文件—場景一
在包含.git的目錄下新建?個ReadMe文件,我們可以使用?git add 命令可以將文件添加到暫存
區:
●添加一個或多個文件到暫存區: git add [file1] [file2]
●添加指定目錄到暫存區,包括子目錄: git add [dir]
●添加當前目錄下的所有文件改動到暫存區: git add
●添加一個或多個文件到暫存區: git add [file1] [file2]
●添加指定目錄到暫存區,包括子目錄: git add [dir]
●添加當前目錄下的所有文件改動到暫存區: git add
注意git commit 后面的-m選項,要跟上描述本次提交的message,由用戶自己完成,這部分內
容絕對不能省略,并要好好描述,是用來記錄你的提交細節,是給我們人看的。
例如:
git commit命令執行成功后會告訴我們,1個文件被改動(就是我們新添加的ReadMe文件),插入了兩行內容(ReadMe有 兩行內容)。
我們還可以多次add不同的文件,而只commit 一次便可以提交所有文件,是因為需要提交的文件是通通被add到暫存區中,然后一次性commit暫存區的所有修改。如:
截至目前為止,我們已經更夠將代碼直接提交至本地倉庫了。我們可以使用git log命令,來查看
下歷史提交記錄:
該命令顯示從最近到最遠的提交日志,并且可以看到我們commit時的日志消息。
如果嫌輸出信息太多,看得眼花繚亂的,可以試試加.上--pretty=oneline參數:
需要說明的是,我們看到的一大串類似23807c5... 56eed6的是每次提交的commit id (版本
號),Git的commit id不是1, 2, ....遞增的數字,而是一個SHA1計算出來的一個非常大的數
字,用十六進制表示(你看到的commit id 和我的肯定不一樣,以你自己的為準)。
2.查看.git文件
先來看看我們的. git的目錄結構:
1. index就是我們的暫存區,add后的內容都是添加到這里的。
2.HEAD就是我們的默認指向master分支的指針:
而默認的master分支,其實就是:
打印的23807c536969cd886c4 fb624b997ca575756eed6是什么東西呢?保存的就是當前最新
的commit id 。
3. objects 為Git的對象庫,里面包含了創建的各種版本庫對象及內容。當執行git add命令
時,暫存區的目錄樹被更新,同時工作區修改(或新增)的文件內容被寫入到對象庫中的一個新的
對象中,就位于".git/objects"目錄下,讓我們來看看這些對象有何用處:
查找object時要將commit id分成2部分,其前2位是文件夾名稱,后38位是文件名稱。
找到這個文件之后,一般不能直接看到里面是什么,該類文件是經過sha (安全哈希算法) 加密過的
文件,好在我們可以使用git cat-file 命令來查看版本庫對象的內容:
其中,還有一行tree 830a8c9fee fbdc098bbae2cdc25e5034ce1920d7,我們使用同樣的方法,看看結果:
在看ReadMe對應的9c9e1f0f6bf f3015df71a0963004476f5e6cfd54 :
總結一下,在本地的git倉庫中,有幾個文件或者目錄很特殊
????????index: 暫存區,git add后會更新該內容。
????????HEAD:默認指向master分支的一個指針。
????????refs/heads/master: 文件里保存當前master分支的最新commit id。
????????objects:包含了創建的各種版本庫對象及內容,可以簡單理解為放了git維護的所有修改。
3.添加文件—場景三
學習到這里,我們已經清楚了如何向倉庫中添加文件,并且對于工作區、暫存區、版本庫也有了一定的認識。那么我們再展示一種添加文件的場景,能加深對工作區、暫存區、版本庫的理解,示例如下:
提交后發現打印了1 file changed, 0 insertions(+), 0 deletions(-) ,意思是只有一個文件改變了,這時我們提出了疑問,不是新增了兩個文件嗎?
再來回憶下,git add是將文件添加到暫存區,git commit 是將暫存區的內容添加到本地倉庫
中。由于我們并沒有使用git add file5, file5 就不在暫存區中維護,所以我們commit的時候
其實只是把已經在暫存區的file4提交了,而遺漏了工作區的file5。如何提交file5呢?很簡單,再次
add,commit即可。
4.修改文件
Git比其他版本控制系統設計得優秀,因為Git跟蹤并管理的是修改,而非文件。
什么是修改?比如你新增了一行,這就是一一個修改,刪除了一-行,也是一一個修改,更改了某些字符,也是一個修改,刪了一些又加了一些,也是一一個修改,甚至創建一個新文件,也算一個修改。讓我們將ReadMe文件進行一次修改:
此時,倉庫中的ReadMe和我們工作區的ReadMe是不同的,如何查看當前倉庫的狀態呢? git
status命令用于查看在你上次提交之后是否有對文件進行再次修改。
上面的結果告訴我們,ReadMe被修改過了,但還沒有完成添加與提交。
目前,我們只知道文件被修改了,如果能知道具體哪些地方被修改了,就更好了。有同學會說,我剛改的我知道呀!可是,你還記得你三天前寫了什么代碼嗎?或者沒寫?
git diff [file] 命令用來顯示暫存區和工作區文件的差異,顯示的格式正是Unix通用的diff格式。也可以使用git diff HEAD -- [file] 命令來查看版本庫和工作區文件的區別。
知道了對ReadMe做了什么修改后,再把它提交到本地倉庫就放心多了。
git add之后,就沒有看到上面no changes added to commit (use "git add"and/or "git commit -a") 的消息了。接下來讓我們繼續git commit 即可:
5.版本回退
之前我們也提到過,Git 能夠管理文件的歷史版本,這也是版本控制器重要的能力。如果有一天你發現之前前的工作做的出現了很大的問題,需要在某個特定的歷史版本重新開始,這個時候,就需要版本回退的功能了。
執行git reset 命令用于回退版本,可以指定退回某一次提交的版本。要解釋一下“回退”本質是
要將版本庫中的內容進行回退,工作區或暫存區是否回退由命令參數決定:
git reset命令語法格式為: git reset [--soft | -- mixed | --hard] [HEAD ]
●--mixed為默認選項,使用時可以不用帶該參數。該參數將暫存區的內容退回為指定提交版本內
容,工作區文件保持不變。
●--soft參數對于工作區和暫存區的內容都不變,只是將版本庫回退到某個指定版本。
●--hard 參數將暫存區與工作區都退回到指定版本。切記工作區有未提交的代碼時不要用這個命
令,因為工作區會回滾,你沒有提交的代碼就再也找不回了,所以使用該參數前一定要慎重。
HEAD說明:
可直接寫成commit id,表示指定退回的版本
HEAD表示當前版本
HEAD^上一個版本
HEAD^^上.上一個版本
以此類推. ..
可以使用~數字表示:
HEAD~0表示當前版本
HEAD~1上一個版本
HEAD~2上上一個版本
以此類推..
為了便于表述,方便測試回退功能,我們先做一些準備工作: 更新3個版本的ReadMe,并分別進行3
次提交,如下所示:
現在,如果我們在提交完version3后,發現version 3編寫錯誤,想回退到version2,重新基于
version 2開始編寫。由于我們在這里希望的是將工作區的內容也回退到version 2版本,所以需
要用到--hard參數,示例如下:
我們驚奇的發現,此時ReadMe文件的內容,已經回退到version2了,當前,我們再次用git
log查看一下提交日志,發現HEAD指向了version2, 如下所示:
到這里一般回退功能就演示完了,但現在如果我后悔了,想再回到version 3怎么辦?我們可以繼續使.用git reset命令,回退到version 3版本,但我們必須要拿到version 3的commit id去指定回退的版本。但我們看到了git log 并不能打印出version 3的commit id,運氣好的話我們可以從終端上去找找之前的記錄,運氣不好的話commit id已經被我們搞丟了
Git還提供了一個git reflog 命令能補救一下,該命令用來記錄本地的每一次命令。
這樣,你就可以很方便的找到你的所有操作記錄了,但d95c13f這個是啥東西?這個是version?
3的commit id的部分。沒錯,Git版本回退的時候,也可以使用部分commit id來代表目標版本。示例如下:
可往往是理想很豐滿,現實很骨感。在實際開發中,由于長時間的開發了,導致commit id早就找
不到了,可突然某一天, 我又想回退到version3,那該如何操作呢?貌似現在不可能了
值得說的是,Git 的版本回退速度非常快,因為Git在內部有個指向當前分支(此處 是master)的
HEAD指針,refs/heads /master文件里保存當前master分支的最新commit id。當我們在回退版本的時候,Git 僅僅是給refs/heads/master 中存儲一-個特定的version,可以簡單理解成如下示意圖:
6.撤銷修改
如果我們在我們的工作區寫了很長時間代碼,越寫越寫不下去,覺得自己寫的實在是垃圾,想恢復到上一個版本。
情況一:對于工作區的代碼,還沒有add
你當然可以直接刪掉你目前在工作區新增的代碼,像這樣:
辛虧我們工作效率不高,才寫了一行代碼就發現不行了,要是你寫了3天,一直都沒有提交,該怎么刪掉呢?你自己都忘了自己新增過哪些,有同學說,我可以git diff xxx一下,看看差別在刪啊,
那你肯定又要花3天時間刪代碼了,并且很大的概率還會改出bug。一周過去了,你怎么向你的老板交代呢?
Git其實還為我們提供了更好的方式,我們可以使用git checkout -- [file] 命令讓工作區的文件回到最近一次add或commit 時的狀態。要注意git checkout -- [file] 命令中的很重要,切記不要省略,一旦省略,該命令就變為其他意思了,后面我們再說。示例如下:
情況二:已經add,但沒有commit
add后還是保存到了暫存區,怎么撤銷呢?
讓我們來回憶一下學過的git reset 回退命令,該命令如果使用--mixed 參數,可以將暫存區的內容退回為指定的版本內容,但工作區文件保持不變。那我們就可以回退下暫存區的內容了! ! !
示例如下:
用git status查看一下,發現現在暫存區是干凈的,工作區有修改。
還記得如何丟棄工作區的修改嗎?
通過這樣的策略就恢復了
情況三:已經add ,并且也commit了
不要擔心,我們可以git reset --hard HEAD^ 回退到上一個版本!不過,這是有條件的,就是你還沒有把自己的本地版本庫推送到遠程。還記得Git是分布式版本控制系統嗎?我們后面會講到遠程版本庫,一旦你推送到遠程版本庫,你就真的慘了.....
7.刪除文件
在Git中,刪除也是一個修改操作,我們實戰一下,如果要刪除file5文件,怎么搞呢?如果你這樣
做了:
但這樣直接刪除是沒有用的,反而徒增煩惱,git status 命令會立刻告訴你哪些文件被刪除了:
此時,工作區和版本庫就不-致了,要刪文件,目前除了要刪工作區的文件,還要清除版本庫的文件。
一般走到這里,有兩種可能:
????????●確實要從版本庫中刪除該文件
????????●不小心刪錯了
對第二種情況,很明顯誤刪,需要使用git來進行恢復,很簡單我們剛學過(刪除也是修改) :
對于第一種情況,很明顯是沒有刪完,我們只刪除了工作區的文件。這時就需要使用git rm將文
件從暫存區和工作區中刪除,并且commit? :
現在,文件就從版本庫中刪除了。