此頁圖解git中的最常用命令沿猜。如果你稍微理解git的工作原理,這篇文章能夠讓你理解的更透徹工碾。 如果你想知道這個站點怎樣產生庵楷,請前往GitHub repository。
本人內容來自:http://marklodato.github.io/visual-git-guide/index-zh-cn.html 伞矩,版權歸原作者所有笛洛。
正文
- 基本用法
- 約定
-
命令詳解
a. Diff
b. Commit
c. Checkout
d. Detached HEAD(匿名分支提交)
e. Reset
f. Merge
g. Cherry Pick
h. Rebase - 技術說明
基本用法
上面的四條命令在工作目錄、暫存目錄(也叫做索引)和倉庫之間復制文件乃坤。
- git add files 把當前文件放入暫存區(qū)域苛让。
- git commit 給暫存區(qū)域生成快照并提交。
- git reset -- files 用來撤銷最后一次git add files侥袜,你也可以用git reset 撤銷所有暫存區(qū)域文件蝌诡。
- git checkout -- files 把文件從暫存區(qū)域復制到工作目錄,用來丟棄本地修改枫吧。
你可以用 git reset -p, git checkout -p, or git add -p進入交互模式浦旱。
也可以跳過暫存區(qū)域直接從倉庫取出文件或者直接提交代碼。
- git commit -a 相當于運行 git add 把所有當前目錄下的文件加入暫存區(qū)域再運行九杂。git commit.
- git commit files 進行一次包含最后一次提交加上工作目錄中文件快照的提交颁湖。并且文件被添加到暫存區(qū)域。
- git checkout HEAD -- files 回滾到復制最后一次提交例隆。
約定
后文中以下面的形式使用圖片甥捺。
綠色的5位字符表示提交的ID,分別指向父節(jié)點镀层。分支用橘色顯示镰禾,分別指向特定的提交。當前分支由附在其上的HEAD標識。 這張圖片里顯示最后5次提交吴侦,ed489是最新提交屋休。 main分支指向此次提交,另一個stable分支指向祖父提交節(jié)點备韧。
命令詳解
Diff
有許多種方法查看兩次提交之間的變動劫樟。下面是一些示例。
Commit
提交時织堂,git用暫存區(qū)域的文件創(chuàng)建一個新的提交叠艳,并把此時的節(jié)點設為父節(jié)點。然后把當前分支指向新的提交節(jié)點易阳。下圖中附较,當前分支是main。 在運行命令之前闽烙,main指向ed489翅睛,提交后,main指向新的節(jié)點f0cec并以ed489作為父節(jié)點黑竞。
即便當前分支是某次提交的祖父節(jié)點捕发,git會同樣操作。下圖中很魂,在main分支的祖父節(jié)點stable分支進行一次提交扎酷,生成了1800b。 這樣遏匆,stable分支就不再是main分支的祖父節(jié)點法挨。此時,合并 (或者 衍合) 是必須的幅聘。
如果想更改一次提交凡纳,使用 git commit --amend。git會使用與當前提交相同的父節(jié)點進行一次新提交帝蒿,舊的提交會被取消荐糜。
另一個例子是分離HEAD提交,后文講。
Checkout
checkout命令用于從歷史提交(或者暫存區(qū)域)中拷貝文件到工作目錄葛超,也可用于切換分支暴氏。
當給定某個文件名(或者打開-p選項,或者文件名和-p選項同時打開)時绣张,git會從指定的提交中拷貝文件到暫存區(qū)域和工作目錄答渔。比如,git checkout HEAD~ foo.c
會將提交節(jié)點HEAD~(即當前提交節(jié)點的父節(jié)點)中的foo.c
復制到工作目錄并且加到暫存區(qū)域中侥涵。(如果命令中沒有指定提交節(jié)點沼撕,則會從暫存區(qū)域中拷貝內容宋雏。)注意當前分支不會發(fā)生變化。
當不指定文件名端朵,而是給出一個(本地)分支時好芭,那么HEAD標識會移動到那個分支(也就是說燃箭,我們“切換”到那個分支了)冲呢,然后暫存區(qū)域和工作目錄中的內容會和HEAD對應的提交節(jié)點一致。新提交節(jié)點(下圖中的a47c3)中的所有文件都會被復制(到暫存區(qū)域和工作目錄中)招狸;只存在于老的提交節(jié)點(ed489)中的文件會被刪除敬拓;不屬于上述兩者的文件會被忽略,不受影響裙戏。
如果既沒有指定文件名乘凸,也沒有指定分支名,而是一個標簽累榜、遠程分支营勤、SHA-1值或者是像main~3類似的東西,就得到一個匿名分支壹罚,稱作detached HEAD(被分離的HEAD標識)葛作。這樣可以很方便地在歷史版本之間互相切換。比如說你想要編譯1.6.6.1版本的git猖凛,你可以運行git checkout v1.6.6.1
(這是一個標簽赂蠢,而非分支名),編譯辨泳,安裝虱岂,然后切換回另一個分支,比如說git checkout main
菠红。然而第岖,當提交操作涉及到“分離的HEAD”時,其行為會略有不同试溯,詳情見在下面蔑滓。
HEAD標識處于分離狀態(tài)時的提交操作
當HEAD處于分離狀態(tài)(不依附于任一分支)時,提交操作可以正常進行耍共,但是不會更新任何已命名的分支烫饼。(你可以認為這是在更新一個匿名分支。)
一旦此后你切換到別的分支试读,比如說main杠纵,那么這個提交節(jié)點(可能)再也不會被引用到,然后就會被丟棄掉了钩骇。注意這個命令之后就不會有東西引用2eecb比藻。
但是铝量,如果你想保存這個狀態(tài),可以用命令git checkout -b name來創(chuàng)建一個新的分支银亲。
Reset
reset命令把當前分支指向另一個位置慢叨,并且有選擇的變動工作目錄和索引。也用來在從歷史倉庫中復制文件到索引务蝠,而不動工作目錄拍谐。
如果不給選項,那么當前分支指向到那個提交馏段。如果用--hard選項轩拨,那么工作目錄也更新,如果用--soft選項院喜,那么都不變亡蓉。
如果沒有給出提交點的版本號,那么默認用HEAD喷舀。這樣砍濒,分支指向不變,但是索引會回滾到最后一次提交硫麻,如果用--hard選項爸邢,工作目錄也同樣。
如果給了文件名(或者 -p
選項), 那么工作效果和帶文件名的checkout差不多庶香,除了索引被更新甲棍。
Merge
merge 命令把不同分支合并起來。合并前赶掖,索引必須和當前提交相同感猛。如果另一個分支是當前提交的祖父節(jié)點,那么合并命令將什么也不做奢赂。 另一種情況是如果當前提交是另一個分支的祖父節(jié)點陪白,就導致fast-forward合并。指向只是簡單的移動膳灶,并生成一個新的提交咱士。
否則就是一次真正的合并。默認把當前提交(ed489 如下所示)和另一個提交(33104)以及他們的共同祖父節(jié)點(b325c)進行一次三方合并轧钓。結果是先保存當前目錄和索引序厉,然后和父節(jié)點33104一起做一次新提交。
Cherry Pick
cherry-pick命令"復制"一個提交節(jié)點并在當前分支做一次完全一樣的新提交毕箍。
Rebase
衍合是合并命令的另一種選擇弛房。合并把兩個父分支合并進行一次提交,提交歷史不是線性的而柑。衍合在當前分支上重演另一個分支的歷史文捶,提交歷史是線性的荷逞。 本質上,這是線性化的自動的 cherry-pick
上面的命令都在topic分支中進行粹排,而不是main分支种远,在main分支上重演,并且把分支指向新的節(jié)點顽耳。注意舊提交沒有被引用坠敷,將被回收。
要限制回滾范圍斧抱,使用--onto選項常拓。下面的命令在main分支上重演當前分支從169a6以來的最近幾個提交,即2c33a辉浦。
同樣有git rebase --interactive
讓你更方便的完成一些復雜操作,比如丟棄茎辐、重排宪郊、修改、合并提交拖陆。沒有圖片體現(xiàn)這些弛槐,細節(jié)看這里:git-rebase(1)
技術說明
文件內容并沒有真正存儲在索引(.git/index)或者提交對象中,而是以blob的形式分別存儲在數(shù)據庫中(.git/objects)依啰,并用SHA-1值來校驗乎串。 索引文件用識別碼列出相關的blob文件以及別的數(shù)據。對于提交來說速警,以樹(tree)的形式存儲叹誉,同樣用對于的哈希值識別。樹對應著工作目錄中的文件夾闷旧,樹中包含的 樹或者blob對象對應著相應的子目錄和文件长豁。每次提交都存儲下它的上一級樹的識別碼。
如果用detached HEAD提交忙灼,那么最后一次提交會被the reflog for HEAD引用匠襟。但是過一段時間就失效,最終被回收该园,與git commit --amend
或者git rebase
很像酸舍。
Copyright ? 2010, Mark Lodato. Chinese translation ? 2012, wych.
[圖片上傳失敗...(image-6dfe7c-1616048433153)] 本著作系采用創(chuàng)用CC 姓名標示-非商業(yè)性-相同方式分享3.0 美國授權條款授權。