前面一篇文章簡單介紹了Git,並前在Windows平台上搭建了Git環境,現在就正式的Git使用了。
Git基本概念
在開始Git的使用之前,需要先介紹一些概念,通過這些概念對Git有些基本的認識,這將會對我們后面的操作有很大的幫助。
在Git中,每個版本庫都叫做一個倉庫(repository),每個倉庫可以簡單理解成一個目錄,這個目錄里面的所有文件都通過Git來實現版本管理,Git都能跟蹤並記錄在該目錄中發生的所有更新。
現在我們已經知道什么是repository(縮寫repo)了,假如我們現在建立一個倉庫(repo),那么在建立倉庫的這個目錄中會有一個".git"的文件夾。這個文件夾非常重要,所有的版本信息、更新記錄,以及Git進行倉庫管理的相關信息全都保存在這個文件夾里面。所以,不要修改/刪除其中的文件,以免造成數據的丟失。
進一步的講解請參考下面一張圖,大概展示出了我們需要了解的基本知識(注意,".git"目錄中還有很多別的東西,圖中並沒有涉及,這里也不做解釋了)。
根據上面的圖片,下面給出了每個部分的簡要說明:
- Directory:使用Git管理的一個目錄,也就是一個倉庫;包含我們的工作空間和Git的管理空間。
- WorkSpace:從倉庫中checkout出來的,需要通過Git進行版本控制的目錄和文件;這些目錄和文件組成了工作空間。
- .git:存放Git管理信息的目錄,初始化倉庫的時候自動創建。
- Index/Stage:暫存區,或者叫做待提交更新區;在提交進入repo之前,我們可以把所有的更新放在暫存區。
- Local Repo:本地倉庫,一個存放在本地的版本庫;HEAD會指示當前的開發分支(branch)。
- Stash:是一個工作狀態保存棧,用於保存/恢復WorkSpace中的臨時狀態。
有了上面概念的了解,下面就開始在本地repo上進行Git的操作了。
創建倉庫
通過"Git Bash"命令行窗口進入到想要建立版本倉庫的目錄,通過"git init"就可以輕松的建立一個倉庫。
這時,我們的倉庫目錄中會自動的產生一個".git"文件夾,這個就是我們前面提到的Git管理信息的目錄。
添加
現在我們在倉庫中新建一個"calc.py"的文件,文件內容如下。
def add(a, b): print a + b if __name__ == "__main__": add(2, 3)
通過"git status"可以查看WorkSpace的狀態,看到輸出顯示"calc.py"沒有被Git跟蹤,並且提示我們可以使用"git add <file>..."把該文件添加到待提交區(暫存區)。
注意,這時的更新只是在WorkSpace中。
使用"git add calc.py"或者"git add .",然后繼續查看WorkSpace的狀態。這是發現文件已經被放到暫存區。
這時的更新已經從WorkSpace保存到了Stage中。
最后,我們就可以通過"git commit -m"來提交更新了。-m后面跟的是對commit的描述(message)。
這時的更新已經又從Stage保存到了Local Repo中。
通過上面的操作,文件"calc.py"就成功的被添加到了倉庫中。
更新
假設現在需要對"calc.py"進行更新,修改文件后,查看WorkSpace的狀態,會發現提示文件有更新,但是更新只是在WorkSpace中,沒有存到暫存區中。
def add(a, b): print a + b def sub(a, b): print a - b if __name__ == "__main__": add(2, 3)
同樣,通過add、commit的操作,我們可以把文件的更新先存放到暫存區,然后從暫存區提交到repo中。
注意,只有被add到暫存區的更新才會被提交進入repo。比如下面的一系列操作,操作結束后只有"multi"函數的更新會被提交到repo中,"div"函數的更新還在WorkSpace中。這點應該也是比較容易理解的。
def multi(a, b): print a * b def div(a, b): if b != 0: print a / b
git diff
"git diff"是一個很有用,而且會經常用到的命令。基於上面的例子,我們通過"git diff"來查看WorkSpace和Stage的diff情況,當我們把更新add到Stage中,diff就不會有任何輸出了。
當然,我們也可以把WorkSpace中的狀態跟repo中的狀態進行diff,命令如下,關於HEAD,將在后面解釋。
git diff HEAD~n
撤銷更新
根據前面對基本概念的了解,更新可能存在三個地方,WorkSpace中、Stage中和repo中。下面就分別介紹一下怎么撤銷這些更新。
撤銷WorkSpace中的更新
接着上面的例子,我們想撤銷WorkSpace中的"div"函數的更新,可以看到"git status"的輸出中有提示,我們可以使用"git checkout -- <file>…"(注意一定不要漏掉--)來撤銷WorkSpace中的更新。
注意,在使用這種方法撤銷更新的時候一定要慎重,因為通過這種方式撤銷后,更新將沒有辦法再被找回。
撤銷Stage中的更新
加入我們在WorkSpace中重新添加了"div"函數的更新,並且使用了"git add"把這個更新提交到了暫存區。這時,"git status"的輸出中提示我們可以通過"git reset HEAD <file>..."把暫存區的更新移出到WorkSpace中。
如果想繼續撤銷WorkSpace中的更新,請參考上面一步。
撤銷repo中的更新
介紹撤銷repo中的更新之前,我們先看一下"git log"這個命令,通過這個命令我們可以查看commit的歷史記錄。可以看到我們進行的三次提交。
其中"WilberTian"和"Wilber***com"就是我們在前面一片文章中配置的用戶名和郵箱。
假設我們現在要撤銷"add mulit function in calc.py"這個提交,有兩種方式:使用HEAD指針和使用commit id。
在Git中,有一個HEAD指針指向當前分支中最新的提交,在上面的例子中HEAD就是對應1a72f49ae49c1716e52c12f2b93fdcef6aac0886(commit id)這次提交。
所以可以使用下面的命令來撤銷"add mulit function in calc.py"這個提交。注意,當前版本,我們使用"HEAD^",那么再前一個版本可以使用"HEAD^^",如果想回退到更早的提交,可以使用"HEAD~n"。(也就是,HEAD^=HEAD~1,HEAD^^=HEAD~2)
git rest --hard HEAD^
等價於
git rest --hard 1a72f49ae49c1716e52c12f2b93fdcef6aac0886
再次查看,發現"add mulit function in calc.py"的commit已經被撤銷了,查看"calc.py"文件,"multi函數"也已經被刪除了。
那么問題就來了,我現在又想要恢復"add mulit function in calc.py"這個提交了,當然Git是支持這樣的操作。
下面來看看"git reflog"這個命令。"git log"只是包括了當前分支中的commit記錄,而"git reflog"中會記錄這個倉庫中所有分支的所有更新記錄,包括已經撤銷的更新。
有了這個,我們就可以查找到"add mulit function in calc.py"提交,然后可以通過下面命令來恢復對"add mulit function in calc.py"的撤銷操作。
git reset --hard HEAD@{1}
等價於
git reset --hard 1a72f49
再次查看,發現我們的"add mulit function in calc.py"更新已經回來了。
--hard和--soft
前面在使用reset來撤銷更新的時候,我們都是使用的"--hard"選項,其實與之對應的還有一個"--soft"選項,區別如下:
- --hard:撤銷並刪除相應的更新
- --soft:撤銷相應的更新,把這些更新的內容放的Stage中
這里就不再對--soft進行演示了。
刪除文件
在Git中,如果我們要刪除一個文件,可以使用下面的命令,"git rm"相比"rm"只是多了一步,把這次刪除的更新發到Stage中。
rm <file>
git rm <file>
刪除操作還是很簡單的,這里就不多做演示了。
總結
通過這篇文章,了解了Git的一些基本概念。
然后介紹了Git中常用的命令來操作本地repo,內容比較多,但是都是基本的,只要自己動手操作一遍就清楚了。
到這里,下面命令流圖中的命令都已經被介紹到了。相信通過這些命令,我們已經可以對自己的本地repo進行Git的版本管理了。
最后,同樣share出文章中的兩個visio圖。