上一篇中咱們介紹了git的基礎概念,這篇咱們就來講說分支linux
git中的分支其實只是一個指針指向一個commit對象,而不是像傳統的版本控制系統同樣把整個當前版本複製一份出來。它背後其實就是一個文件,咱們能夠去.git/refs/heads文件夾下面查看,裏面的每一個文件其實就是一個分支,而內容其實就是一串SHA1值,而這個SHA1值又是什麼呢,其實就是一個commit id,如下圖爲例,其實此時master分支文件存放的就是master分支上的最後一次commit id,而分支背後表明的就是一條commit對象鏈。git
而HEAD又是什麼呢,其實它也是一個指針,指向着是當前分支,而不是commit對象。在.git目錄下有一個HEAD文件,裏面就是記錄着HEAD指向的分支。 app
接下來就用一個例子來介紹一下git分支合併的過程,首先假設咱們處於master分支上 post
git checkout -b dev
git merge dev
合併分支
--no-ff
便可,
git merge --no-ff dev
,那非快進模式的好處是什麼呢,其實就是如同下圖所示,非快進模式能夠幫咱們保留分支的樣子,在樹狀結構中能夠完整的看出分支的狀況
git reset其實有3中模式,mixed, soft和hard,默認不寫的話會調用mixed模式,那麼3者的區別是什麼呢,mixed其實就是會將reset以後的commit與原commit之間的修改轉到工做區,而soft則是轉到暫存區,最後hard就是直接丟棄掉,因此能夠看出其實reset與它的字面意思有些不一樣的,咱們常常會誤會它是從新設定把以後的commit砍掉,其實它只是回到以前的狀態。3d
git stash的做用是什麼呢,假設當咱們在feature1上作事時,忽然須要緊急去feature2上作事,此時就須要將feature1上的事情暫時用git stash先存起來而後去feature2上作事,作完再回feature1上經過git stash pop將以前保存的修改取出。須要注意的是git stash會記住目前的commit id,因此若是同一個commit下stash兩次對於同一文件同一行內容的修改,恢復完第一次而且提交事後,在執行第二次恢復就會有衝突。版本控制
tag就是咱們以前提到的其實就是一個標籤對象,它也是指向某一個commit對象,它與分支的區別就在於當有commit發生時,分支會跟着一塊兒向前移,可是標籤一旦定下來就不會再移動了,因此它一般是用於咱們項目到了一個milestone,須要發佈一個新版本時使用。git標籤分爲兩種輕量級標籤(lightweight)和附註標籤(annotated),就如同字面上的意思,輕量級於附註標籤的區別就是一個有描述信息一個沒有。指針
git diff背後其實就是利用了linux自帶的diff模塊用來比較文件之間的差異,有興趣的能夠去了解一下日誌
git branch
code
git branch 分支名
cdn
git checkout 分支名
git checkout -
git branch -d 分支名
這裏須要注意不能刪除當前處於的分支,若是非master分支有改動但還未merge的話也不能夠,除非使用git branch -D 分支名
git checkout -b 分支名
git branch -v
git merge 分支名
git merge --no-ff 分支名
git reset --hard HEAD^
git reset --hard HEAD^^
git reset --hard HEAD~n
git reset --hard commit信息的前幾位
git branch -m 原分支名 新分支名
git stash
git stash list
默認執行git stash返回的描述信息是
git stash save 'hello basic'
git stash pop
git stash apply
git stash apply stash@{0}
git stash drop stash@{0}
git tag v1.0.1
git tag -a v1.0.2 -m 'release 1.0.2'
git tag
能夠查看全部的標籤,同時也能夠經過git tag show 標籤名
來看某個標籤
git tag -l 'v1.0'
裏面可使用pattern,例如'v*', 表明v開頭的全部標籤
git tag -d 標籤名
git blame 文件名
git diff
git diff HEAD
git diff commit_id
git diff --cached
git diff --cached commit_id
git push origin --tags
能夠經過調用git push origin --delete tag 標籤名
,或者使用git push origin :refs/tags/v6.0
推送一個空標籤上去
有時候可能用戶a執行了命令刪除了遠程的a1分支,那麼對於用戶b來講當他執行git remote show origin
時,會發現遠程的a1分支是處於stale狀態,也就是說遠程已經沒有了,可是本地還在,這時候就能夠執行git remote prune origin
,這樣就會把那個stale狀態下的遠程分支刪掉
git reset --hard
指令回退到以前的commit時,執行git log
只能看到當前commit及其以前的commit,那若是我想回到以後的某個commit,我要怎麼獲取commit id呢?咱們能夠經過執行git reflog
來查看操做日誌,看到咱們使用git的指令的歷史,這樣就能夠找回咱們以前的commit id了,這裏說下reflog背後其實就是記錄着HEAD指針的改變歷史,因此日常都會說不要手動去修改.git目錄下的文件,由於手工修改以後是不會記錄在reflog中的
git branch -D 分支名
強制刪除掉了,還救得回來嗎?是救得回來的,這裏要先強調的是,分支其實只是一個指針,因此即使刪除掉了這個指針,咱們的commit對象還在,因此固然是能夠救回來的,只要咱們經過git reflog
找到本來分支指向的commit-id,而後執行git branch 分支名 commit-id
就能夠從新建立回咱們的分支了。這裏在延伸說一下,其實在git merge
時背後其實也是在合併commit對象,因此咱們其實也能夠經過git merge commit-id
來作合併的,分支只是給咱們一個相似貼紙同樣簡單標註了這串分支commit鏈作的是什麼。
git checkout commit-id
與 git reset --hard commit-id
有什麼區別呢?二者均可以回到對應的commit點,可是checkout與reset不一樣的是它會處於遊離狀態,任何的修改若是不作提交就會有警告不容許咱們跳去其餘的commit,同時修改完咱們能夠經過git branch 分支名 當前checkout的commit-id
來建立一個新分支。