在Git中提交時,會保存一個提交(commit)對象,它包含一個指向暫存內容快照的指針,做者和相關附屬信息,以及必定數量(也可能沒有)指向linux
提交對象直接祖先的指針:第一次提交是沒有直接祖先的,普通提交有一個祖先,由兩個或多個分支合併產生的提交則有多個祖先。如今假設git
工做目錄下有3個文件,準備將他們暫存後提交。暫存操做會對每個文件計算校驗和(即SHA-1哈希字符串),而後把當前版本控制的文件快照spa
保存到Git倉庫中,並將校驗和加入暫存區域。當使用git commit新建一個提交對象前,Git會先計算每個子目錄(本例中就是就是項目根目錄)版本控制
的校驗和,而後在Git倉庫中將這些目錄保存爲樹(tree)對象。以後Git建立的提交對象(commit),除了包含相關提交信息之外,還包含着指向這指針
個樹對象(項目根目錄)的指針,如此他就能夠在未來須要的時候,重現這次快照的內容。orm
這個是提交一次後倉庫裏的數據對象
屢次提交後Git倉庫數據three
Git中的分支,其實本質就是個指向commit對象的可變指針。Git會使用master做爲分支的默認名字。在若干次提交後,你其實已經有了一個ip
指向最後一次提交對象的master分支,它在每次提交的時候都會自動向前移動。rem
一:git branch
通過屢次提交倉庫中的狀況如上,master指向最新的commit,那麼怎樣建立一個新的分支呢,可使用git branch+分知名,這裏用
git branch testing,就建立了一個基於master的分支。
$git branch testing
HEAD是一個引用,指向正在使用的分支。
進行查看:
下面切換到新的分支:
$git checkout testing
使用git branch能夠查看當前都有哪些branch,前面有*的表示,當前所在的branch。
能夠看到,此時master與testing都指向同一個commit,這裏的9831*******,一共是20個字節,40個十六進制的字符,這個就是將文
件放到暫存區時產生的哈希字符串,它做爲文件的名字,這裏使用git cat-file -t 查看object的類型,這裏至少用前四個字符。
如今 切換到testing分支,修改工做目錄下的main.c文件,而後提交,再次看HEAD的指向,發現testing中的HEAD已經指向新的
commit了。
如今對master分支的main.c文件進行修改:
能夠看到此時master指向的commit已經變化,造成上圖的分支。
git branch -a 列出全部分支,包括remote和local branches
git branch -r 列出remote branches
git branch -d new-branch 刪除new-branch
git branch -D new-branch 強制刪除new-branch
二:git merge
從上邊幾張圖能夠看出先是基於master建立了分支iss53,此時它們指向同一個commit,以後iss32分支進行了commit,而後基
於master建立了新的分支hotfix,並進行了commit。如今要把hotfix分支合併到master分支中。
git merge + 要merge的branch,這樣就能夠把branch merge到當前branch上了。先git checkout master,而後git merge hotfix,
這樣hotfix branch就能夠merge到master分支上了,而後git branch -d hotfix對hotfix分支進行刪除。這裏的merge實際上是比較簡
單的,因爲master分支指向的commit是hotfix分支指向的commit的parent,因此直接移動master指針到hotfix指向的commit就能夠了。
git branch --merge查看哪些分支已被併入當前分支
git branch --no-merge查看哪些分支沒有被併入當前分支
下面這個是three-way merge
這裏要merge c4和c5,此時Git會用兩個分支的末端(C4和C5)和他們的共同祖先(C2)進行一次簡單的三方合併計算。Git能夠
本身裁決哪一個公共祖先纔是最佳合併基礎。
三:git checkout
git checkout branch-name 切換到branch-name
git checkout master 切換到master
git checkout -b new-branch master 從master創建新的new-branch,並同時切換過去new-branch
git checkout -b newbranch 由如今的分支爲基礎,創建新的branch
git checkout -b newbranch origin 由origin的基礎,創建新的branch
git checkout filename 還原檔案到Repository狀態
git checkout HEAD 將全部檔案都checkout出來(最後一次commit的版本),注意,如有修改的檔案都會被還原到上一版
git checkout xxxx 將全部檔案都checkout出來(xxxx commit的版本,xxxx是commit的編號前四位),注意,如有修改的檔案
都會被還原到上一版
四:git show
可使用git show加上commit名稱來顯示更詳細的commit信息:
也可使用git show加分支名稱,也可顯示分支信息:
使用HEAD字段能夠表明當前分支的頭(也就是最近一次commit):
$git show HEAD
每一次commit都會有「parent commit」,可使用^表示parent:
$git show HEAD^ 查看HEAD的父母的信息
$git show HEAD^^ 查看HEAD的父母的父母的信息
$git show HEAD~5 查看HEAD上溯5代的信息
有的時候git merge會產生雙父母,好比three-way merge的時候,這種狀況這樣處理:
$git show HEAD^1 查看HEAD的第一個父母
$git show HEAD^2 查看HEAD的第二個父母
五:git archive
能夠把當前版本(HEAD所處的位置)給export出來
使用git describe能夠查看當前的version
$mkdir ../linux-2.6.11
$git archive -v v2.6.11 | (cd ../linux-2.6.11/ && tar xf -)
$head -4 ../linux-2.6.11/Makefile
從本地git倉庫中提取某個版本的kernel:
$git archive -v v2.6.11 | (cd ../linux-2.6.11/ && tar xf -)
-v表示--verbose,注意'v2.6.11'能夠是git tag -l列出的tags中的一個,也能夠是其餘Rev ID例如HEAD等
這裏的「&&」相似「;」不過是有區別的,若是每一個命令被一個分號「;」所分隔,那麼命令會連續的執行下去。若是每一個命令
被「&&」號分隔,那麼這些命令會一直執行下去,若是中間有錯誤的命令存在,則再也不執行後面的命令,沒錯則執行到完爲止。
這裏的「-」做用是把前邊的輸出做爲這裏的輸入
導出最新的kernel:
$git archive -v HEAD | (cd ../linux-HEAD/ && tar xf -)
或者打成tar包:
$git archive -v --format=tar v3.0 | bzip2 >../linux-3.0.tar.bz2