圖解Git

再次感謝原著做者和中文翻譯者。html

此頁圖解git中的最經常使用命令。若是你稍微理解git的工做原理,這篇文章可以讓你理解的更透徹。 若是你想知道這個站點怎樣產生,請前往GitHub repositorygit

正文

  1. 基本用法github

  2. 約定數據庫

  3. 命令詳解ide

    1. Diffui

    2. Commitspa

    3. Checkout翻譯

    4. Detached HEAD(匿名分支提交)code

    5. Resetorm

    6. Merge

    7. Cherry Pick

    8. Rebase

  4. 技術說明

基本用法

上面的四條命令在工做目錄、暫存目錄(也叫作索引)和倉庫之間複製文件。

  • git add files 把當前文件放入暫存區域。

  • git commit 給暫存區域生成快照並提交。

  • git reset -- files 用來撤銷最後一次git add files,你也能夠用git reset 撤銷全部暫存區域文件。

  • git checkout -- files 把文件從暫存區域複製到工做目錄,用來丟棄本地修改。

你能夠用 git reset -pgit checkout -p, or git add -p進入交互模式。

也能夠跳過暫存區域直接從倉庫取出文件或者直接提交代碼。

  • git commit -a 至關於運行 git add 把全部當前目錄下的文件加入暫存區域再運行。git commit.

  • git commit files 進行一次包含最後一次提交加上工做目錄中文件快照的提交。而且文件被添加到暫存區域。

  • git checkout HEAD -- files 回滾到複製最後一次提交。

約定

後文中如下面的形式使用圖片。

綠色的5位字符表示提交的ID,分別指向父節點。分支用橘色顯示,分別指向特定的提交。當前分支由附在其上的HEAD標識。 這張圖片裏顯示最後5次提交,ed489是最新提交。master分支指向這次提交,另外一個maint分支指向祖父提交節點。

命令詳解

Diff

有許多種方法查看兩次提交之間的變更。下面是一些示例。

Commit

提交時,git用暫存區域的文件建立一個新的提交,並把此時的節點設爲父節點。而後把當前分支指向新的提交節點。下圖中,當前分支是master。 在運行命令以前,master指向ed489,提交後,master指向新的節點f0cec並以ed489做爲父節點。

即使當前分支是某次提交的祖父節點,git會一樣操做。下圖中,在master分支的祖父節點maint分支進行一次提交,生成了1800b。 這樣,maint分支就再也不是master分支的祖父節點。此時,合併 (或者 衍合) 是必須的。

若是想更改一次提交,使用 git commit --amend。git會使用與當前提交相同的父節點進行一次新提交,舊的提交會被取消。

另外一個例子是分離HEAD提交,後文講。

Checkout

checkout命令用於從歷史提交(或者暫存區域)中拷貝文件到工做目錄,也可用於切換分支。

當給定某個文件名(或者打開-p選項,或者文件名和-p選項同時打開)時,git會從指定的提交中拷貝文件到暫存區域和工做目錄。好比,git checkout HEAD~ foo.c會將提交節點HEAD~(即當前提交節點的父節點)中的foo.c複製到工做目錄而且加到暫存區域中。(若是命令中沒有指定提交節點,則會從暫存區域中拷貝內容。)注意當前分支不會發生變化。

當不指定文件名,而是給出一個(本地)分支時,那麼HEAD標識會移動到那個分支(也就是說,咱們「切換」到那個分支了),而後暫存區域和工做目錄中的內容會和HEAD對應的提交節點一致。新提交節點(下圖中的a47c3)中的全部文件都會被複制(到暫存區域和工做目錄中);只存在於老的提交節點(ed489)中的文件會被刪除;不屬於上述二者的文件會被忽略,不受影響。

若是既沒有指定文件名,也沒有指定分支名,而是一個標籤、遠程分支、SHA-1值或者是像master~3相似的東西,就獲得一個匿名分支,稱做detached HEAD(被分離的HEAD標識)。這樣能夠很方便地在歷史版本之間互相切換。好比說你想要編譯1.6.6.1版本的git,你能夠運行git checkout v1.6.6.1(這是一個標籤,而非分支名),編譯,安裝,而後切換回另外一個分支,好比說git checkout master。然而,當提交操做涉及到「分離的HEAD」時,其行爲會略有不一樣,詳情見在下面

HEAD標識處於分離狀態時的提交操做

HEAD處於分離狀態(不依附於任一分支)時,提交操做能夠正常進行,可是不會更新任何已命名的分支。(你能夠認爲這是在更新一個匿名分支。)

一旦此後你切換到別的分支,好比說master,那麼這個提交節點(可能)不再會被引用到,而後就會被丟棄掉了。注意這個命令以後就不會有東西引用2eecb

可是,若是你想保存這個狀態,能夠用命令git checkout -b name來建立一個新的分支。

Reset

reset命令把當前分支指向另外一個位置,而且有選擇的變更工做目錄和索引。也用來在從歷史倉庫中複製文件到索引,而不動工做目錄。

若是不給選項,那麼當前分支指向到那個提交。若是用--hard選項,那麼工做目錄也更新,若是用--soft選項,那麼都不變。

若是沒有給出提交點的版本號,那麼默認用HEAD。這樣,分支指向不變,可是索引會回滾到最後一次提交,若是用--hard選項,工做目錄也一樣。

若是給了文件名(或者 -p選項), 那麼工做效果和帶文件名的checkout差很少,除了索引被更新。

Merge

merge 命令把不一樣分支合併起來。合併前,索引必須和當前提交相同。若是另外一個分支是當前提交的祖父節點,那麼合併命令將什麼也不作。 另外一種狀況是若是當前提交是另外一個分支的祖父節點,就致使fast-forward合併。指向只是簡單的移動,並生成一個新的提交。

不然就是一次真正的合併。默認把當前提交(ed489 以下所示)和另外一個提交(33104)以及他們的共同祖父節點(b325c)進行一次三方合併。結果是先保存當前目錄和索引,而後和父節點33104一塊兒作一次新提交。

Cherry Pick

cherry-pick命令"複製"一個提交節點並在當前分支作一次徹底同樣的新提交。

Rebase

衍合是合併命令的另外一種選擇。合併把兩個父分支合併進行一次提交,提交歷史不是線性的。衍合在當前分支上重演另外一個分支的歷史,提交歷史是線性的。 本質上,這是線性化的自動的 cherry-pick

上面的命令都在topic分支中進行,而不是master分支,在master分支上重演,而且把分支指向新的節點。注意舊提交沒有被引用,將被回收。

要限制回滾範圍,使用--onto選項。下面的命令在master分支上重演當前分支從169a6以來的最近幾個提交,即2c33a

一樣有git rebase --interactive讓你更方便的完成一些複雜操做,好比丟棄、重排、修改、合併提交。沒有圖片體現這些,細節看這裏:git-rebase(1)

技術說明

文件內容並無真正存儲在索引(.git/index)或者提交對象中,而是以blob的形式分別存儲在數據庫中(.git/objects),並用SHA-1值來校驗。 索引文件用識別碼列出相關的blob文件以及別的數據。對於提交來講,以樹(tree)的形式存儲,一樣用對於的哈希值識別。樹對應着工做目錄中的文件夾,樹中包含的 樹或者blob對象對應着相應的子目錄和文件。每次提交都存儲下它的上一級樹的識別碼。

若是用detached HEAD提交,那麼最後一次提交會被the reflog for HEAD引用。可是過一段時間就失效,最終被回收,與git commit --amend或者git rebase很像。




另附Git的詳細介紹網址一個:http://git-scm.com/book/zh/v1

相關文章
相關標籤/搜索