Git本地版本管理
一些基本概念
分布式版本控制系統(tǒng)
Git 是一種分布式版本控制系統(tǒng) (Distributed Version Control System DVCS) 。這種系統(tǒng)下,客戶端不只是簡單地拉取某個版本的文件,而是把整個記錄文件版本的數(shù)據(jù)庫(即整個代碼倉庫)都克隆到本地系統(tǒng)上。這樣以來,任何一處協(xié)同工作用的服務器發(fā)生故障,事后都可以用任何一個鏡像出來的本地倉庫恢復。因為每一次的克隆工作,實際上都是一次對代碼倉庫的完整備份。
存儲方式
Git 中所有數(shù)據(jù)在存儲前都會計算校驗和,然后以校驗和來引用某個版本的文件,該校驗和是根據(jù)文件的內容或目錄結構使用 SHA-1 哈希算法計算出來的,比如:
24b9da6552252987aa493b52f8696cd6d3b00373Git 數(shù)據(jù)庫中保存的信息都是以文件內容的哈希值來索引,而不是文件名。
三種狀態(tài)
Git 最重要的地方是有三個區(qū):
- Git 倉庫:這個就是保存各種文件版本的數(shù)據(jù)庫,可以向這個數(shù)據(jù)庫中拉取各個文件版本或把更新后的文件推入數(shù)據(jù)庫進行記錄。這是 Git 用來保存項目的元數(shù)據(jù)和對象數(shù)據(jù)庫的地方,是 Git 最重要的部分,從其他計算機克隆倉庫時,拷貝的就是這里的數(shù)據(jù)。已經推入到這個數(shù)據(jù)庫中的文件對應的狀態(tài)是 已提交 (commited) 。
- 暫存區(qū)域:這個區(qū)域用來存儲對當前已修改過并且作了版本標記的文件,在同一段時間內位于暫存區(qū)尚未提交的所有文件都屬于同一個當前的版本,這些標記使得對應文件被包含在下次提交的快照中。這個區(qū)域是一個文件,保存了下次將提交的文件列表信息,一般位于 Git 倉庫目錄中。在這個區(qū)域的文件狀態(tài)是 已暫存 (staged) 。
- 工作目錄:這個區(qū)域就是開發(fā)人員寫代碼的地方,對于已經修改并保存的文件,都會存儲在這個區(qū)域,等待轉移到暫存區(qū)并提交。它是對項目的某個版本獨立提取出來的內容。那些從 Git 倉庫的壓縮數(shù)據(jù)庫中提取出來的文件,就是放在這個區(qū)域所在的磁盤上供你使用或修改。在這個區(qū)域的文件狀態(tài)是 已修改 (modified) 。
Git 工作三部曲
常用命令
配置用戶名和密碼
$ git config --global user.name "Jack Cheng" $ git config --global user.email "767833640@qq.com"如果使用了 --global 選項,則該命令只需要提交一次,無論你以后在系統(tǒng)中執(zhí)行何種操作,Git 都會使用這種配置。如果你想針對某個特定的項目使用不同的用戶名稱和郵箱,可以在那個項目目錄下運行沒有 --global 選項的命令來配置。
檢查配置信息
$ git config --list檢查具體某一項的配置
$ git config user.name獲取幫助
$ git help config $ git help push創(chuàng)建倉庫
$ git init這個命令將創(chuàng)建一個名為 .git 的子目錄,這個字目錄含有你初始化的 Git 倉庫中所有的必須文件,這些文件是 Git 倉庫的骨干。但是這只是做了一個初始化操作,在當?shù)匚募A的項目里的文件還沒有被跟蹤。使用 git add 命令來跟蹤文件,使用 git commit 命令來提交文件到本地的 Git 倉庫中。
檢查狀態(tài)
$ git status可以查看當前倉庫哪些文件處于未跟蹤狀態(tài),哪些文件已經放入暫存區(qū)等待提交。
可以看到 .DS_Store 文件位于 Untracked files 標題下,表示這個文件是新創(chuàng)建的未被跟蹤的文件,Git 倉庫中不存在這個文件的信息。
可以看到這個時候 .gitignore 文件位于 Changes to be commited 這個標題下面,說明這個文件已經被移入暫存區(qū)了,處于已暫存的狀態(tài)。
把已修改或未跟蹤的文件放入暫存區(qū)
$ git add 文件名git add 不僅可以跟蹤新文件并放到暫存區(qū),還能把已修改的文件也放到暫存區(qū),這是一個多功能命令。放到暫存區(qū)的這些文件在下次提交時將會一并提交到 Git 倉庫中。因此對于 git add 命令的最好翻譯是 “添加內容到下一次的提交中”。
$ git add 文件目錄此時 git add 命令將遞歸地跟蹤該目錄下的所有文件,并把目錄下的所有文件都放入暫存區(qū)。
查看已暫存的文件和當前工作目錄中文件的差異
$ git diffgit diff 命令可以查看當前工作目錄中已修改的文件和暫存區(qū)的文件的差異(注意只是和暫存區(qū)的差異,不是和上次提交以來的差異,因此如果你把所有已經修改的文件都添加到暫存區(qū)后,git diff 將不會返回任何東西)
查看已暫存的文件和上一次提交后的文件的變化
$ git diff --staged 或者 $ git diff --cached提交處于暫存區(qū)的所有文件
$ git commit -m "說明當前做了什么,以后版本回退時可以輕易找到"注意提交的都是放在暫存區(qū)的文件,每一次的提交的版本都會在歷史記錄中記錄下來,以后都可以回到這個版本。(只有 commit 以后的版本可以回退)
回到過去
$ git log使用 git log 命令查看歷史提交記錄:
$ git log --pretty=oneline為了簡化查看,可以使用 git log --pretty=oneline 參數(shù):
$ git reset --hard commit_id找到要回退的版本的前面的 commit_id,然后使用 git reset --hard commit_id 命令來回退到想要的版本,只需要打出 commit_id 的前幾個字母即可,Git 會自動查找對應的 id :
可以看到此時項目的最新版本已經回退到了 3950d 的版本。
從過去回到現(xiàn)在
$ git reflog回退以后,會發(fā)現(xiàn)之前的最新版本 9fd77 已經不在 git log 的目錄中了,此時假如我們又想回到之前的最新的版本怎么辦?首先使用 git reflog 命令來查找提交 9fd77 時的記錄:
git reset --hard commit_id可以看到我們在回退前最新一次提交的 commit_id 是 9fd77b1 ,因此我們再用 git reset --hard 9fd77b1 來進入到回退前的最新版本:
因此,我們也就從過去回到現(xiàn)在了。
一些 trick
忽略文件
有時候我們會有一些文件不需要納入 Git 的管理,比如上面的 .DS_Store ,此時就應該編寫 .gitignore 文件來列出要 Git 倉庫忽略的文件模式。該文件的格式規(guī)范如下:
以 # 開頭的行為 Git 的注釋。
使用 / 放在文件名的開頭可以防止遞歸地忽略所有非當前目錄中的該文件。比如
TODO會忽略 Git 倉庫中所有目錄下的 TODO 文件,但如果只希望 Git 忽略當前目錄下的 TODO 文件,而不要忽略其它目錄下的 TODO 文件,則應該寫成這樣:
/TODO使用 / 放在文件名的末尾表明這個文件是一個目錄,Git 將會忽略這個目錄下的所有文件。
如果希望 Git 只記錄某一個特定的文件,而忽略除了這個文件以外的所有文件,可以在這個文件名前面使用 ! 取反。但是這種功能一般是用于以下情況:
# 忽略所有的 .a 文件*.a# 但是所有的 lib.a 文件不能被忽略!lib.a指定文件的格式一般要使用正則表達式:
- * 匹配 0 個或多個任意字符;
- [abc] 可以匹配任何一個在方框號中的字符(在這個例子中是要么匹配一個a,要么匹配一個b,要么匹配一個c);
- ? 只匹配一個任意字符;
- [0-9] 表示匹配在 0 到 9 范圍內的所有數(shù)字。
- 使用兩個星號 ** 表示匹配任意的中間目錄,比如 learn/**/git 可以匹配 learn/git 、learn/no/git 或者 learn/no/python/git 。
看一個 .gitignore 文件的例子:
# 忽略所有以 .a 結尾的文件 *.a# 不能忽略所有 lib.a 文件 !lib.a# 僅僅忽略當前目錄下的 TODO 文件 /TODO# 忽略 build 目錄下的所有文件 build/# 僅僅忽略 doc 一個目錄下的所有 .txt 文件 doc/*.txt# 忽略 doc 目錄下(包括子目錄)的所有 .pdf 文件 doc/**/*.pdf移除文件
最常見的情況是,在 .gitignore 文件中未列出對應的文件,有時為了貪求效率,使用 git add . 把所有文件都放到暫存區(qū)域,包括把一些不希望加入 Git 版本管理的日志文件等也放進去了,這個時候我們希望可以從暫存區(qū)域中刪除這些不希望被管理的文件,但是使這些文件仍然被存放在工作目錄上,而不被 Git 繼續(xù)跟蹤。此時可以使用 git rm --cached filename 命令:
這樣就可以把誤添加的文件從暫存區(qū)中移除,而防止下一次 commit 時加入到 Git 倉庫中去。
還有一種情況就是,我希望刪除的文件已經 commit 或者 add 了,即已經被跟蹤了,但我希望完全刪除這個文件,即把工作目錄中的這個文件也刪了,這時我們就可以先在本地項目目錄中刪除這個文件,然后再使用 git rm filename 命令把該文件從已跟蹤的文件清單中一并刪除:
這個是文件已經 add 但沒有 commit 的情況,使用 git rm 命令就直接清空了,如果文件之前有過 commit ,而你又把想刪除的文件從工作目錄中刪除了:
可以看到刪除文件的操作記錄在 Changes not staged for commit 標題下, 意味著你需要把這個刪除的操作再提交一遍,使得 Git 倉庫知道這個文件已經刪除了,不應該再被跟蹤了。
移動文件
如果要在 Git 中對某些文件進行重命名,可以使用 git mv original_name target_name 命令:
執(zhí)行這個命令后,可以看到在工作目錄中的 test.cpp 也被重命名為 main.cpp 了,這個時候只要提交這次重命名操作就可以了。
參考資料
總結
- 上一篇: CSS之viewports剖析
- 下一篇: EditPlus使用技巧