圖解 Git

jopen 11年前發布 | 87K 次閱讀 Git 版本控制系統

此頁圖解git中的最常用命令。如果你稍微理解git的工作原理,這篇文章能夠讓你理解的更透徹。 如果你想知道這個站點怎樣產生,請前往GitHub repository

正文

  1. 基本用法
  2. 約定
  3. 命令詳解
    1. Diff
    2. Commit
    3. Checkout
    4. Detached HEAD(匿名分支提交)
    5. Reset
    6. Merge
    7. Cherry Pick
    8. Rebase
  4. 技術說明

基本用法

Git 圖解

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

  • git add files 把當前文件放入暫存區域。
  • git commit 給暫存區域生成快照并提交。
  • git reset -- files 用來撤銷最后一次git add files,你也可以用git reset 撤銷所有暫存區域文件。
  • git checkout -- files 把文件從暫存區域復制到工作目錄,用來丟棄本地修改。

你可以用 git reset -p, git checkout -p, or git add -p進入交互模式。

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

Git 圖解
  • git commit -a 相當于運行 git add 把所有當前目錄下的文件加入暫存區域再運行。git commit.
  • git commit files 進行一次包含最后一次提交加上工作目錄中文件快照的提交。并且文件被添加到暫存區域。
  • git checkout HEAD -- files 回滾到復制最后一次提交。

約定

后文中以下面的形式使用圖片。

Git 圖解

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

命令詳解

Diff

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

Git 圖解

Commit

提交時,git用暫存區域的文件創建一個新的提交,并把此時的節點設為父節點。然后把當前分支指向新的提交節點。下圖中,當前分支是master。 在運行命令之前,master指向ed489,提交后,master指向新的節點f0cec并以ed489作為父節點。

Git 圖解

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

Git 圖解

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

Git 圖解

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

Checkout

checkout命令通常用來從倉庫中取出文件,或者在分支中切換。

checkout命令讓git把文件復制到工作目錄和暫存區域。比如git checkout HEAD~ foo.c把文件從foo.c提交節點HEAD~ (當前提交節點的父節點)復制到工作目錄并且生成索引。注意當前分支沒有變化。

Git 圖解

如果沒有指定文件名,而是一個本地分支,那么將切換到那個分支去。同時把索引和工作目錄切換到那個分支對應的狀態。

Git 圖解

如果既沒有指定文件名,也沒有指定分支名,而是一個標簽、遠程分支、SHA-1值或者是像master~3類似的東西,就得到一個匿名分支,稱作detached HEAD。 這樣可以很方便的在歷史版本之間互相切換。但是,這樣的提交是完全不同的,詳細的在下面

Git 圖解

用分離HEAD提交(找不到好的譯法)

HEAD是分離的時候, 提交可以正常進行, 但是沒有更新已命名的分支. 。(可以看作是匿名分支。)

Git 圖解

如果此時切換到別的分支,那么所作的工作會全部丟失。注意這個命令之后就不存在2eecb了。

Git 圖解

如果你想保存當前的狀態,可以用這個命令創建一個新的分支: git checkout -b name

Git 圖解

Reset

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

如果不給選項,那么當前分支指向到那個提交。如果用--hard選項,那么工作目錄也更新,如果用--soft選項,那么都不變。

Git 圖解

如果沒有給出提交點的版本號,那么默認用HEAD。這樣,分支指向不變,但是索引會回滾到最后一次提交,如果用--hard選項,工作目錄也同樣。

Git 圖解

如果給了文件名(或者 -p選項), 那么工作效果和帶文件名的checkout差不多,除了索引被更新。

Git 圖解

Merge

merge 命令把不同分支合并起來。合并前,索引必須和當前提交相同。如果另一個分支是當前提交的祖父節點,那么合并命令將什么也不做。 另一種情況是如果當前提交是另一個分支的祖父節點,就導致fast-forward合并。指向只是簡單的移動,并生成一個新的提交。

Git 圖解

否則就是一次真正的合并。默認把當前提交(ed489 如下所示)和另一個提交(33104)以及他們的共同祖父節點(b325c)進行一次三方合并。結果是先保存當前目錄和索引,然后和父節點33104一起做一次新提交。

Git 圖解

Cherry Pick

cherry-pick命令"復制"一個提交節點并在當前復制做一次完全一樣的新提交。

Git 圖解

Rebase

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

Git 圖解

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

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

Git 圖解

同樣有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很像。

來自:http://marklodato.github.com/visual-git-guide/index-zh-cn.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!