一江场、Git的概念:
Git是Linus花了兩周的時間用C語言編寫的一個版本控制系統(tǒng)逛艰,它是目前世界上最先進(jìn)的分布式版本控制系統(tǒng)薪棒。
集中式版本控制系統(tǒng)造成,版本庫是集中存放在中央服務(wù)器的显熏,而干活的時候,用的都是自己的電腦晒屎,所以要先從中央服務(wù)器取得最新的版本喘蟆,然后開始干活,干完活了鼓鲁,再把自己的活推送給中央服務(wù)器蕴轨。中央服務(wù)器就好比是一個圖書館,你要改一本書骇吭,必須先從圖書館借出來橙弱,然后回到家自己改,改完了燥狰,再放回圖書館棘脐。
集中式版本控制系統(tǒng)最大的毛病就是必須有聯(lián)網(wǎng)才能工作,如果在局域網(wǎng)內(nèi)還好龙致,帶寬夠大蛀缝,速度夠快,可如果在互聯(lián)網(wǎng)上目代,遇到網(wǎng)速慢的話内斯,可能提交一個10M的文件就需要5分鐘,提交的速度會很慢像啼。
那分布式版本控制系統(tǒng)與集中式版本控制系統(tǒng)有何不同呢俘闯?首先,分布式版本控制系統(tǒng)根本沒有“中央服務(wù)器”忽冻,每個人的電腦上都是一個完整的版本庫真朗,這樣,你工作的時候僧诚,就不需要聯(lián)網(wǎng)了遮婶,因為版本庫就在你自己的電腦上。既然每個人電腦上都有一個完整的版本庫湖笨,那多個人如何協(xié)作呢旗扑?比方說你在自己電腦上改了文件A,你的同事也在他的電腦上改了文件A慈省,這時臀防,你們倆之間只需把各自的修改推送給對方,就可以互相看到對方的修改了。
和集中式版本控制系統(tǒng)相比袱衷,分布式版本控制系統(tǒng)的安全性要高很多捎废,因為每個人電腦里都有完整的版本庫,某一個人的電腦壞掉了不要緊致燥,隨便從其他人那里復(fù)制一個就可以了登疗。而集中式版本控制系統(tǒng)的中央服務(wù)器要是出了問題,所有人都沒法干活了嫌蚤。
在實際使用分布式版本控制系統(tǒng)的時候辐益,其實很少在兩人之間的電腦上推送版本庫的修改,因為可能你們倆不在一個局域網(wǎng)內(nèi)脱吱,兩臺電腦互相訪問不了智政,也可能今天你的同事病了,他的電腦壓根沒有開機(jī)急凰。因此女仰,分布式版本控制系統(tǒng)通常也有一臺充當(dāng)“中央服務(wù)器”的電腦,但這個服務(wù)器的作用僅僅是用來方便“交換”大家的修改抡锈,沒有它大家也一樣干活疾忍,只是交換修改不方便而已。一般用來充當(dāng)“中央服務(wù)器”的電腦就是一些代碼托管網(wǎng)站床三,比如GitHub一罩、GitLab、碼云等撇簿。
二聂渊、本機(jī)的分區(qū):
用git的方式管理代碼就會在本機(jī)上產(chǎn)生如下的幾個概念:
1、工作區(qū)(Working Directory):
電腦里能看到的目錄就是工作區(qū)四瘫,如下圖所示就是工作區(qū)汉嗽。
2、版本庫(Repository):
工作區(qū)有一個隱藏目錄.git找蜜,如下圖所示饼暑,在鍵盤上同時按下如下的幾個鍵就能顯示出隱藏文件。
這個.git文件不算工作區(qū)洗做,而是git的版本庫弓叛,如下圖所示就是版本庫。
git的版本庫里存了很多東西诚纸,其中最重要的就是被稱為stage(或者index)的暫存區(qū)撰筷,還有g(shù)it為我們自動創(chuàng)建的第一個分支master,以及指向master的一個指針HEAD畦徘。
3毕籽、暫存區(qū)(stage):
在工作區(qū)中把文件修改以后抬闯,然后在終端中鍵入命令行語句”git add”,意味著把文件的修改添加到了版本庫中的暫存區(qū)影钉,然后再鍵入”git commit”命令行語句提交修改画髓,意味著把暫存區(qū)的所有內(nèi)容提交到了當(dāng)前的分支上掘剪,整個過程如下圖所示:
三平委、git的使用:
一般Git有三種使用方法:第一種是利用Xcode自帶的Git把代碼存儲在遠(yuǎn)端的代碼托管網(wǎng)站上;第二種是利用命令行的方式使用Git把代碼存儲在遠(yuǎn)端的代碼托管網(wǎng)站上夺谁;第三種是利用Sourcetree這種可視化的方式利用Git把代碼存儲在遠(yuǎn)端的代碼托管網(wǎng)站上廉赔。下面重點介紹命令行的使用方法。
這個部分的目錄如下:
1匾鸥、命令行方式下的git的基本使用:
2蜡塌、命令行方式下的git的版本回退:
3、命令行方式下的git的文件撤銷修改:
4勿负、命令行方式下的git的文件刪除:
5馏艾、命令行方式下的git的遠(yuǎn)程庫的添加:
6、命令行方式下的git的沖突解決:
7奴愉、命令行方式下的git的分支管理策略:
8琅摩、命令行方式下的git的Bug分支處理:
9、命令行方式下的git的Feature分支:
10锭硼、命令行方式下的git的多人協(xié)作:
11房资、命令行方式下的git的標(biāo)簽創(chuàng)建:
12、命令行方式下的git的操作標(biāo)簽:
13檀头、如何使用Github:
14轰异、如何使用碼云:
15、命令行方式下的git的配置別名:
1暑始、命令行方式下的git的基本使用:
(1)創(chuàng)建空白目錄:
在創(chuàng)建版本庫之前要先創(chuàng)建一個空白的目錄搭独,把這個空白的目錄當(dāng)做工作區(qū)。用如下的命令行創(chuàng)建一個空白的目錄:
$ mkdir learngit
$ cd learngit
$ pwd
“pwd"命令行用于顯示當(dāng)前的目錄廊镜,在我的Mac上播赁,這個倉庫位于/Users/zhaopeng/learngit替劈。在終端中運行上述命令行之后的截圖如下:
在電腦中創(chuàng)建的空白目錄的截圖如下:
(2)創(chuàng)建版本庫(Repository):
? ? ? ?版本庫又名倉庫卓嫂,可以簡單理解成一個目錄,這個目錄里面的所有文件都可以被Git管理起來背桐,每個文件的修改、刪除Git都能跟蹤禾嫉,以便任何時刻都可以追蹤歷史灾杰,或者在將來某個時刻可以“還原”蚊丐。
? ? ? ?通過”git init”命令行在上面(1)步驟中創(chuàng)建的空白目錄(工作區(qū))中創(chuàng)建版本庫熙参,在終端中運行前述的命令行之后截圖如下:
運行”git init”命令行之后在之前創(chuàng)建的空白目錄(工作區(qū))中會出現(xiàn)一個隱藏的.git文件,截圖如下:
這個.git文件就是版本庫了麦备。版本庫中存放了很多內(nèi)容孽椰,其中最重要的就是暫存區(qū)(stage),還有g(shù)it為我們自動創(chuàng)建的第一個分支master凛篙,以及指向master的一個指針HEAD黍匾。一般情況下不去修改這個.git文件夾里面的文件,如果亂改的話就會把git倉庫給破壞了呛梆。
(3)把要進(jìn)行版本控制的文件添加到新創(chuàng)建的版本庫中:
? ? ? ?所有的版本控制系統(tǒng)锐涯,其實只能跟蹤文本文件的改動,比如TXT文件填物、網(wǎng)頁纹腌、所有的程序代碼等等,Git也不例外滞磺。版本控制系統(tǒng)可以告訴你每次的改動升薯,比如在第5行加了一個單詞”Linux",在第8行刪了一個單詞”Windows"击困。而圖片祈争、視頻這些二進(jìn)制文件寨闹,雖然也能由版本控制系統(tǒng)進(jìn)行管理,但沒法跟蹤這些文件的變化,只能把這些二進(jìn)制文件的每次改動串起來棍弄,也就是只能知道圖片從100KB改成了120KB,但到底改了什么每篷,版本控制系統(tǒng)不知道英遭,也沒法知道。
? ? ? ?因為文本是有編碼的企蹭,比如中文有常用的GBK編碼白筹,日文有Shift_JIS編碼智末,如果沒有歷史遺留問題,強(qiáng)烈建議使用標(biāo)準(zhǔn)的UTF-8編碼徒河,所有語言使用同一種編碼系馆,既沒有沖突,又被所有平臺所支持顽照。
編寫一個簡單的.rtf文件由蘑,內(nèi)容如下:
Gitisa version control system.
Gitisfree software.
然后把這個文件放到上述在(1)中創(chuàng)建的工作區(qū)中,放入之后的截圖如下:
利用"git add 文件名稱"命令行再把這個文件放到上述在(2)中創(chuàng)建好的版本庫中代兵,在終端操作的截圖如下:
如果執(zhí)行完"git add 文件名稱”命令行之后終端沒有任何提示的話就說明添加成功了尼酿,意味著把文件由工作區(qū)放到了版本庫中的暫存區(qū)(stage)中,但是在.git文件中看不到新添加的文件植影,實際上是已經(jīng)添加進(jìn)去了裳擎。
(4)把文件由版本庫中的暫存區(qū)提交到版本庫中的master分支上:
在上述的(2)中創(chuàng)建版本庫之后,版本庫中包含很多東西思币,除了暫存區(qū)(stage)之外還有g(shù)it為我們自動創(chuàng)建的第一個分支master鹿响。在終端中執(zhí)行"git commit -m?“提交說明""命令行,意味著把文件從版本庫中的暫存區(qū)中提交到當(dāng)前分支上谷饿,在終端的操作截圖如下:
終端中”-m"后面輸入的是本次提交的說明惶我,這樣就能從歷史記錄里方便地找到改動的記錄〔┩叮”git commit”命令執(zhí)行成功后會告訴你”1 file changed”:1個文件被改動(我們新添加的readme.txt文件)绸贡;"2 insertions":插入了兩行內(nèi)容(readme.rtf有兩行內(nèi)容)。
? ? ? ?為什么Git添加文件需要add毅哗,commit一共兩步呢听怕?因為commit可以一次提交很多文件,所以可以多次add不同的文件黎做,比如:
$ git add file1.txt
$ git add file2.txt file3.txt
$git commit -m"add 3 files.”
上述的就是在使用命令行的方式下git的基本使用方法叉跛。
? ? ? ?總結(jié):把工作區(qū)中的文件往版本庫中添加的時候分為兩個步驟,第一步是用”git add”命令行把文件的修改添加到版本庫中的暫存區(qū)中蒸殿,如下圖所示:
第二步是用”git commit”命令行把版本庫中的暫存區(qū)中的所有內(nèi)容提交到當(dāng)前分支中筷厘,如下圖所示:
2、命令行方式下的git的版本回退:
? ? ? ?在上述1中已經(jīng)成功地在版本庫中添加并提交了一個readme.rtf文件了宏所,現(xiàn)在在工作區(qū)中對這個文件進(jìn)行修改酥艳,在工作區(qū)中修改的這個文件其實可以看成是在修改版本庫中的暫存區(qū)中的那個文件。把文件的內(nèi)容修改為如下:
Gitisa distributed version control system.
Gitisfree software.
修改完以后在終端中運行”git status”命令行爬骤,”git status”命令行的意思是顯示當(dāng)前版本庫的狀態(tài)充石。運行之后的截圖如下:
從上面的命令輸出可以得知暫存區(qū)中的readme.rtf文件被修改了,但還沒有準(zhǔn)備提交修改了霞玄。在終端中可以通過”git diff 文件名稱”命令行查看文件修改前和修改后的不同之處骤铃,在查看完不同之處后再在終端中輸入”q”命令行跳出拉岁,在終端運行之后的截圖如下:
把工作區(qū)中修改過后的readme.rtf文件在終端中用”git add 文件名稱”命令行提交到版本庫中的暫存區(qū)中,在終端中運行之后的截圖如下:
同樣沒有任何輸出就證明已經(jīng)成功地將文件從工作區(qū)添加到了版本庫中的暫存區(qū)中了惰爬。在提交之前再運行”git status”命令行喊暖,查看當(dāng)前版本庫的狀態(tài),在終端中運行之后的截圖如下:
最后在終端中執(zhí)行”gitcommit -m “提交說明"”命令行撕瞧,把版本庫中的暫存區(qū)中的新修改的文件提交到版本庫中的master分支上陵叽,在終端中運行之后的截圖如下:
提交后再運行”git status”命令行,查看當(dāng)前版本庫的狀態(tài)丛版,終端的截圖如下:
Git告訴我們當(dāng)前沒有需要提交的修改巩掺,而且工作目錄是干凈(working tree clean)的。
再次修改工作區(qū)中的readme.rtf文件页畦,把文件的內(nèi)容修改如下:
Gitisa distributed version control system.
Gitisfree software distributed under the GPL.
然后把新修改的文件添加到版本庫中的暫存區(qū)中胖替,最后提交新修改的文件到版本庫中的master分支上,在終端中運行的截圖如下:
像這樣不斷對文件進(jìn)行修改寇漫,然后不斷提交修改到版本庫里的master分支上刊殉,讓git為你做一個修改文件的記錄者,一旦你把文件改亂了或者誤刪了文件州胳,還可以從最近的一個commit進(jìn)行恢復(fù),然后繼續(xù)工作逸月,而不是把這幾個月的工作成果全部丟失栓撞。
現(xiàn)在,回顧一下readme.rtf文件一共有幾個版本被提交到Git版本庫里的master分支上了:
版本1:wrote a readme file
Gitisa version control system.
Gitisfree software.
版本2:add distributed
Gitisa distributed version control system.
Gitisfree software.
版本3:append GPL
Gitisa distributed version control system.
Gitisfree software distributed under the GPL.
在終端中執(zhí)行”git log”命令行碗硬,用來查看文件的修改記錄瓤湘,截圖如下:
"git log”命令行顯示從近到遠(yuǎn)的提交日志,可以看到3次提交恩尾,最近的一次是"append GPL"弛说,上一次是"add distributed",最早的一次是"wrote a readme file"翰意。如果嫌輸出信息太多木人,看得眼花繚亂的,可以在"git log”后面加上"--pretty=oneline”冀偶,截圖如下:
在終端上看到的類似”9ece8301d9350a0b71e309912ff0f661cfac3a8b”的一大長串?dāng)?shù)組和字母的組合其實是每次commit的版本號(commit id)醒第,它是一個由SHA1計算出來的一個非常大的數(shù)字,用十六進(jìn)制表示进鸠。那為什么commit id需要用這么一大串?dāng)?shù)字表示呢稠曼?因為Git是分布式的版本控制系統(tǒng),如果大家都用1客年,2霞幅,3……作為版本號漠吻,那肯定就沖突了。
? ? ? ?現(xiàn)在準(zhǔn)備把readme.rtf文件回退到上一個版本司恳,也就是”add distributed”的那個版本侥猩。首先,Git必須知道當(dāng)前版本是哪個版本抵赢,在Git中用HEAD表示當(dāng)前的版本欺劳,也就是最新提交的,commit id為”9ece8301d9350a0b71e309912ff0f661cfac3a8b"铅鲤,上一個版本就是HEAD^划提,上上一個版本就是HEAD^^,當(dāng)然往上100個版本寫100個^比較容易數(shù)不過來邢享,所以寫成HEAD~100∨敉現(xiàn)在,我們要把當(dāng)前版本"append GPL"回退到上一個版本"add distributed"骇塘,就可以使用"git reset --hardcommit id”命令行伊履,截圖如下:
這個時候打開工作區(qū)中的文件,果然內(nèi)容變成了上一個版本的內(nèi)容款违。也可以在終端中通過”cat 文件名稱"命令行的方式查看工作區(qū)中的文件內(nèi)容唐瀑,截圖如下:
再用”git log”查看現(xiàn)在版本庫的狀態(tài),截圖如下:
發(fā)現(xiàn)最新的那個版本"append GPL"已經(jīng)看不到了插爹,如果要想回到最新的那個版本就在終端上往上倒哄辣,找到”append GPL”版本對應(yīng)的commit id(9ece83…),然后執(zhí)行"git reset --hardcommit id”命令行赠尾,截圖如下:
版本號沒必要寫全力穗,前幾位就可以了,Git會自動去找气嫁,當(dāng)然也不能只寫前一兩位当窗,因為Git可能會找到多個版本號,就無法確定是哪一個了寸宵。打開工作區(qū)中的readme.rtf文件崖面,可以看到文件的內(nèi)容已經(jīng)變成了最新的那個”append GPL”版本了。Git的版本回退速度非车寺快嘶朱,因為Git在內(nèi)部有個指向當(dāng)前版本的HEAD指針,當(dāng)你回退版本的時候光酣,Git僅僅是把HEAD指針從指向append GPL:
改為指向add distributed:
然后順便把工作區(qū)的文件更新了疏遏。所以你讓HEAD指針指向哪個版本號,你就把當(dāng)前版本定位在哪。如果當(dāng)回退到了某個版本之后關(guān)掉了電腦财异,第二天早上想恢復(fù)到新版本怎么辦倘零?找不到新版本的commit id怎么辦?現(xiàn)在執(zhí)行”git reset --hard HEAD^”命令行戳寸,文件回退到”add distributed”版本呈驶,截圖如下:
再想恢復(fù)到"append GPL",就必須找到"append GPL"的commit id疫鹊。Git提供了一個命令行"git reflog"用來記錄你的每一次命令袖瞻,截圖如下:
就可以找到”append GPL”版本的commit id(9ece830)了,從而可以把文件更新到最新的版本了拆吆,截圖如下:
打開工作區(qū)中的文件聋迎,果然文件更新到了最新的版本了。
3枣耀、命令行方式下的git的文件撤銷修改:
? ? ? ?在工作區(qū)中給文件readme.rtf不小心添加了一句”My stupid boss still prefers SVN.”霉晕,以至于readme.rtf文件的內(nèi)容變?yōu)榱耍?/p>
Gitisa distributed version control system.
Gitisfree software distributed under the GPL.
My stupid boss still prefers SVN.
這個時候還沒有執(zhí)行”git add”命令行,意味著已經(jīng)被修改的文件還沒有被加入到版本庫中的暫存區(qū)中了捞奕,這個時候執(zhí)行命令”git status”牺堰,截圖如下:
上面的"Changes not staged for commit這句話代表工作區(qū)中的文件修改還沒有被加入到版本庫中的暫存區(qū)中了。上面的”git checkout -- <file>…”的意思是可以丟棄工作區(qū)的修改颅围,所以在終端中執(zhí)行”git checkout -- 文件名稱”命令行伟葫,用來把工作區(qū)中的文件的修改進(jìn)行撤銷,截圖如下所示:
執(zhí)行完命令之后查看工作區(qū)中的文件谷浅,果然那句話被撤回了扒俯。
? ? ??“git checkout -- 文件名稱”命令行中的--很重要,沒有--一疯,就變成了“切換到另一個分支”的命令,我們在后面的分支管理中會再次遇到git checkout命令夺姑。
在工作區(qū)中修改readme.rtf文件后墩邀,執(zhí)行”git add”命令行把文件修改添加到版本庫中的暫存區(qū)中,截圖如下:
然后執(zhí)行”git status”命令行盏浙,截圖如下:
上面的”Changes to be committed”代表工作區(qū)中文件的修改已經(jīng)添加到了版本庫中的暫存區(qū)中了眉睹,只是還沒有commit了。執(zhí)行"git reset HEAD 文件名稱”命令行废膘,可以把暫存區(qū)的文件修改撤銷掉竹海,重新放回工作區(qū)。截圖如下:
執(zhí)行之后再用”git status”指令查看暫存區(qū)的狀態(tài)丐黄,截圖如下:
上面的”Changes not staged for commit”語句已經(jīng)說明之前存在暫存區(qū)中的文件修改已經(jīng)被撤銷了斋配,工作區(qū)中的文件有修改。最后再執(zhí)行”git checkout -- 文件名稱”指令把工作區(qū)中的文件的修改撤回,截圖如下:
執(zhí)行之后打開工作區(qū)中的文件艰争,果然修改被撤回了坏瞄。
總結(jié):
場景1:當(dāng)你改亂了工作區(qū)某個文件的內(nèi)容,想直接丟棄工作區(qū)的修改時甩卓,用命令行”git checkout -- 文件名稱”鸠匀。
場景2:當(dāng)你不但改亂了工作區(qū)某個文件的內(nèi)容,還添加到了暫存區(qū)時逾柿,想丟棄修改缀棍,分兩步,第一步用命令行"git reset HEAD 文件名稱"机错,撤回暫存區(qū)中的文件的修改爬范,然后就回到了場景1,第二步按場景1來操作毡熏。
場景3:已經(jīng)提交了不合適的修改到版本庫時坦敌,想要撤銷本次提交,參考版本回退一節(jié)痢法,不過前提是沒有推送到遠(yuǎn)程庫狱窘。
4、命令行方式下的git的文件刪除:
? ? ? ?在工作區(qū)中創(chuàng)建一個新的文件财搁,然后利用”git add 文件名稱”命令行把工作區(qū)中新創(chuàng)建的文件添加到版本庫中的暫存區(qū)中蘸炸,最后再利用"gitcommit -m “提交說明””命令行把版本庫中的暫存區(qū)中的文件提交到當(dāng)前的分支上。在終端中運行后截圖如下:
此時工作區(qū)中的情況如圖所示:
一般情況下尖奔,通常會直接在文件管理器中或者在終端中利用"rm 文件名稱"命令行把工作區(qū)中的文件刪除掉搭儒,截圖如下:
此時工作區(qū)中的情況如圖所示,剛才新添加的文件被刪除了:
這個時候提茁,Git知道你刪除了工作區(qū)中的文件淹禾,因此工作區(qū)和版本庫就不一致了,利用"git status”命令行來查看哪些文件被刪除了茴扁,截圖如下:
現(xiàn)在有兩種情況:
(1)確實要把文件從版本庫中刪除:利用”git rm 文件名稱”把文件從版本庫中的暫存區(qū)中刪除铃岔,并且利用"gitcommit -m “提交說明””把文件的變化提交到當(dāng)前的分支中,截圖如下:
現(xiàn)在文件就從版本庫中刪除了峭火,并且同步到了當(dāng)前的分支中嘿棘。
(2)在工作區(qū)中誤刪文件了肪获,把不應(yīng)該刪除的文件刪除了爹土。針對這種情況帮坚,因為版本庫中還有此文件了,所以可以利用”git checkout -- 文件名稱"把誤刪的文件恢復(fù)到最新的版本稍浆,截圖如下:
此時工作區(qū)中的情況如圖所示载碌,被刪除的文件又被加了回來:
“git checkout"其實是用版本庫里的版本替換工作區(qū)的版本猜嘱,無論工作區(qū)是修改還是刪除,都可以“一鍵還原”恐仑。"rm 文件名稱”命令行用于刪除工作區(qū)中的某個文件泉坐,如果一個文件已經(jīng)被提交到了版本庫,那么永遠(yuǎn)不用擔(dān)心被誤刪裳仆,但是要小心腕让,只能恢復(fù)文件到最新的版本,會丟失最近一次提交后修改的內(nèi)容歧斟。
5、命令行方式下的git的遠(yuǎn)程庫的添加:
? ? ? 現(xiàn)在的情形是在本地已經(jīng)創(chuàng)建了一個工作區(qū)和版本庫了觉鼻,并且readme.rtf文件已經(jīng)提交到了版本庫中的當(dāng)前的分支中了。現(xiàn)在想要在github網(wǎng)站上創(chuàng)建一個git的遠(yuǎn)程倉庫,讓本地倉庫和遠(yuǎn)程倉庫進(jìn)行同步花枫,這樣gitHub上的遠(yuǎn)程倉庫既可以作為備份刻盐,又可以讓其他人通過該倉庫來進(jìn)行協(xié)作,一舉多得劳翰。
? ? ? ?登錄github后點擊頁面右上角的綠色按鈕”New”敦锌,創(chuàng)建一個新的git的遠(yuǎn)程倉庫,如圖所示:
在倉庫名稱中填入learngit佳簸,并且填入描述信息供屉,然后點擊“Create repository”按鈕,創(chuàng)建一個git的遠(yuǎn)程倉庫溺蕉,如圖所示:
創(chuàng)建完的遠(yuǎn)程倉庫是空的。GitHub告訴我們悼做,可以從這個倉庫克隆出新的倉庫疯特,也可以把一個已有的本地倉庫與之關(guān)聯(lián),然后把本地倉庫的內(nèi)容推送到GitHub遠(yuǎn)程倉庫中肛走,如圖所示:
根據(jù)github上面的提示在終端中運行”git remote add origin github地址”和”git push -u origin master"命令行漓雅,把本地倉庫和遠(yuǎn)程倉庫進(jìn)行關(guān)聯(lián)并且把本地倉庫中的master上的內(nèi)容推送到遠(yuǎn)程倉庫中的master分支上,截圖如下:
關(guān)聯(lián)成功后遠(yuǎn)程倉庫的名字就默認(rèn)叫做origin了。
用”git push”命令行把本地倉庫中的內(nèi)容推送到遠(yuǎn)程倉庫中邻吞,實際上就是把本地的版本庫中的master分支上的文件推送到遠(yuǎn)程倉庫中的master分支上组题。由于遠(yuǎn)程倉庫是空的,當(dāng)?shù)谝淮瓮扑蚼aster分支時會使用”git push -u origin master”命令行抱冷,這樣做git不但會把本地的master分支上的內(nèi)容推送到遠(yuǎn)程的master分支上崔列,還會把本地的master分支和遠(yuǎn)程的的master分支關(guān)聯(lián)起來,在以后的推送或者拉取時就可以簡化命令行了旺遮。
推送成功后赵讯,就可以立刻在GitHub頁面中看到遠(yuǎn)程倉庫中的內(nèi)容已經(jīng)和本地倉庫中的一模一樣了,截圖如下:
從現(xiàn)在起耿眉,只要把本地版本庫中的暫存區(qū)中的文件提交到了本地版本庫中的master分支后边翼,就可以通過”git push -u origin master”命令行把本地master分支中的最新文件推送到遠(yuǎn)程倉庫中的master分支中。現(xiàn)在就擁有了真正的分布式版本庫了鸣剪!
備注:
SSH警告:當(dāng)?shù)谝淮问褂肎it的”clone”或者”push”命令行連接GitHub時组底,會得到一個警告:
The authenticity of host 'github.com(xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?
這是因為git使用SSH連接,而SSH連接在第一次驗證GitHub服務(wù)器的Key時需要你確認(rèn)GitHub的Key的指紋信息是否真的來自GitHub的服務(wù)器筐骇,輸入yes回車即可债鸡。
Git會輸出一個警告,告訴你已經(jīng)把GitHub的Key添加到本機(jī)的一個信任列表里了:
Warning: Permanently added'github.com'(RSA) to thelistof known hosts.
這個警告只會出現(xiàn)一次拥褂,后面的操作就不會有任何警告了娘锁。
如果實在擔(dān)心有人冒充GitHub服務(wù)器,輸入yes前可以對照GitHub的RSA Key的指紋信息是否與SSH連接給出的一致即可饺鹃。
分布式版本系統(tǒng)的最大好處之一就是在本地工作完全不需要考慮遠(yuǎn)程倉庫的存在莫秆,也就是有沒有聯(lián)網(wǎng)都可以正常工作,當(dāng)有網(wǎng)絡(luò)的時候再把本地提交推送一下就完成了同步悔详。而SVN在沒有聯(lián)網(wǎng)的時候是拒絕干活的镊屎。
6、命令行方式下的git從遠(yuǎn)程倉庫克虑洋Α:
現(xiàn)在遠(yuǎn)程庫已經(jīng)準(zhǔn)備好了缝驳,下一步是用命令行把遠(yuǎn)程庫克隆一個到本地。
在終端中執(zhí)行”git clone github地址”命令行归苍,把遠(yuǎn)程庫克隆到本地用狱,截圖如下:
一般會下載到本地的個人文件夾里面,并且已經(jīng)把遠(yuǎn)程庫中的README.md文件克隆了下來拼弃,如圖所示:
如果是多人協(xié)作開發(fā)的話夏伊,則每個人各自從遠(yuǎn)程克隆一份到本地就可以了。
7吻氧、命令行方式下的git的創(chuàng)建與合并分支:
? ? ? ?在上面的“2溺忧、命令行方式下的git的版本回退”中已經(jīng)知道咏连,每次提交,git都會把它們串成一條時間線鲁森,這條時間線就是一個分支祟滴。截止到目前,只有一條時間線歌溉,在git里把這個分支叫做主分支垄懂,即master分支。HEAD嚴(yán)格來說不是指向提交研底,而是指向master埠偿,master才是指向提交的,所以HEAD指向的就是當(dāng)前分支榜晦。
? ? ? ?一開始的時候冠蒋,master分支是一條線,git用master指向最新的提交乾胶,再用HEAD指向master抖剿,就能確定當(dāng)前的分支以及當(dāng)前分支的提交點,如圖所示:
當(dāng)在本地修改工作區(qū)中的文件以后识窿,在終端中利用”git add 文件名稱”命令行把之前的修改提交到本地的版本庫中的暫存區(qū)中斩郎,然后再利用"git commit -m?“提交說明””命令行把在本地版本庫中的暫存區(qū)中的文件的修改提交到本地的master分支中。這樣每次提交喻频,本地版本庫中的master分支都會向前移動一步缩宜,這樣,隨著不斷地提交甥温,本地master分支的線也就越來越長锻煌,如圖所示:
當(dāng)創(chuàng)建新的分支時(例如dev),git新建了一個指針叫做dev姻蚓,指向master相同的提交宋梧,再把HEAD指向dev,就表示當(dāng)前的分支是dev分支了狰挡,如圖所示:
從前述中可以看出git創(chuàng)建一個新分支很快捂龄,因為除了增加一個dev指針、改變HEAD的指向外加叁,工作區(qū)的文件沒有任何的變化倦沧。不過,從現(xiàn)在開始它匕,對工作區(qū)的修改和提交就是針對dev分支了刀脏。比如,這個時候修改本地工作區(qū)中的文件以后超凳,在終端中利用”git add 文件名稱”命令行把之前的修改提交到本地的版本庫中的暫存區(qū)中愈污,然后再利用"git commit -m?“提交說明””命令行把暫存區(qū)中的修改提交到本地的版本庫中的dev分支上,這樣轮傍,dev指針就往前移動了一步暂雹,而master指針則不變,如圖所示:
假如我們在dev分支上的工作完成了创夜,就可以把dev分支合并到master分支上了杭跪。合并最簡單的方法就是直接把master指向dev的當(dāng)前提交,就完成了合并驰吓,所以git的合并分支也很快涧尿,就是改改指針,工作區(qū)的內(nèi)容也不變檬贰。如圖所示:
合并完分支后姑廉,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪除掉翁涤,刪掉后就剩下了一條master分支了桥言,如圖所示:
上面是一些理論的知識,下面進(jìn)行實戰(zhàn):
在終端中利用”git checkout -b 分支名稱”命令行在本地的版本庫中創(chuàng)建一個新的分支并由原來的master分支切換到這個新的分支上葵礼,截圖如下:
“git checkout”命令后面加上”-b"參數(shù)表示創(chuàng)建并切換号阿,相當(dāng)于”git branch dev”和”git checkout dev”兩條命令行的作用。
可以用”git branch”命令行來查看本地版本庫中的當(dāng)前分支鸳粉,截圖如下:
“git?branch”命令行會列出本地版本庫中的所有分支扔涧,當(dāng)前分支前面會用一個*號來標(biāo)識。然后我們就可以在dev分支上正常地做提交了届谈。比如枯夜,在readme.rtf文件中加上一行"Creating anewbranch is quick.”,然后利用”git add 文件名稱”命令行把在本地的工作區(qū)中做的修改添加到本地的版本庫中的暫存區(qū)中疼约,然后利用"git commit -m?“提交說明””命令行把本地的暫存區(qū)中的修改提交到本地的版本庫中的dev分支上卤档,截圖如下:
現(xiàn)在,dev分支的工作完成了程剥,然后可以利用”git checkout master”命令行切換回master分支了劝枣,截圖如下:
切換回master分支后,再查看本地的工作區(qū)中的readme.rtf文件织鲸,發(fā)現(xiàn)剛才添加的內(nèi)容不見了舔腾,這是因為剛才提交的文件是提交到了本地的版本庫中的dev分支上了,而master分支此刻的提交點并沒有改變搂擦,如圖所示:
現(xiàn)在稳诚,利用”git merge dev”命令行把本地的版本庫中的dev分支上的工作成果合并到本地的版本庫中的master分支上,截圖如下:
“git merge 分支名稱”命令行用于合并指定分支到當(dāng)前的分支上瀑踢。合并后再查看本地的工作區(qū)中的readme.rtf文件的內(nèi)容就可以看到和dev分支上的最新提交的內(nèi)容是完全一樣的了扳还。
注意截圖上的Fast-forward信息才避,git告訴我們這次合并是“快進(jìn)模式”,也就是直接把master指向dev的當(dāng)前提交氨距,所以合并的速度非成J牛快。當(dāng)然俏让,也不是每次合并都能Fast-forward楞遏。
合并完成后,就可以利用”git branch -d dev”命令行放心地刪除dev分支了首昔,截圖如下:
刪除后利用”git branch”命令行查看branch寡喝,現(xiàn)在就只剩下master分支了,截圖如下:
因為創(chuàng)建勒奇、合并和刪除分支的速度非常的快预鬓,所以git鼓勵使用分支完成某個任務(wù),合并后再刪掉分支撬陵,這和直接在master分支上工作效果是一樣的珊皿,但過程更為安全。
備注:
git鼓勵大量使用分支:
查看分支:git branch
創(chuàng)建分支:git branch <name>
切換分支:git checkout <name>
創(chuàng)建+切換分支:git checkout -b <name>
合并某分支到當(dāng)前的分支:git merge <name>
刪除分支:git branch -d <name>
6巨税、命令行方式下的git的沖突解決:
利用”git checkout -b 分支名稱”命令行在本地的版本庫中創(chuàng)建新的feature1分支并切換到這個新分支上蟋定,繼續(xù)新分支的開發(fā),截圖如下:
創(chuàng)建并切換到新的分支以后草添,在本地的工作區(qū)中修改readme.rtf文件的內(nèi)容驶兜,在此文件中增加一句”Creating anewbranch is quickANDsimple.”,然后利用"git add 文件名稱”命令行把本地的工作區(qū)中的文件修改添加到本地的版本庫中的暫存區(qū)中远寸,然后再利用"git commit -m “提交說明””命令行把本地的版本庫中的暫存區(qū)中的文件的修改添加到新創(chuàng)建的feature1分支上抄淑,截圖如下:
然后利用”git checkout master”命令行切換到master分支上,截圖如下:
上面截圖中的”Your branch is ahead of 'origin/master' by 1 commit.”語句代表著git自動提示當(dāng)前本地的版本庫中的master分支比遠(yuǎn)程的master分支要超前一個提交驰后。
現(xiàn)在在master分支下打開本地工作區(qū)中的readme.rtf文件肆资,并在此文件中添加”Creating anewbranch is quick & simple.”語句,然后利用"git add 文件名稱”和?"git commit -m “提交說明””命令行把文件的修改提交到本地的版本庫中的master分支上灶芝,截圖如下:
現(xiàn)在本地的master分支和feature1分支各自都分別有新的提交郑原,如圖所示:
如果一個分支上有新的提交,而另外一個分支上沒有新的提交夜涕,則這種情況下適合上述的git的"快速合并”犯犁,像現(xiàn)在這種情況,兩個分支上都有新的提交女器,則就不適用git的“快速合并”了酸役,只能試圖把各自的修改合并起來,但這種合并就有可能會造成沖突。利用”git merge feature1”命令行把feature1分支上的內(nèi)容合并到master分支上涣澡,截圖如下:
git告訴我們贱呐,readme.rtf文件存在沖突,必須手動解決沖突后再提交才可以暑塑。
可以利用”git status”命令行來查看沖突的文件吼句,截圖如下:
或者直接打開本地工作區(qū)中的readme.rtf文件,查看里面的內(nèi)容事格,截圖所示:
git用<<<<<<<,=======搞隐,>>>>>>>標(biāo)記出不同分支的內(nèi)容驹愚,把這些內(nèi)容刪除后更改為”Creating anewbranch is quickandsimple.”,然后再利用命令行把解決沖突后的文件提交到本地的版本庫中的當(dāng)前分支(master)上劣纲,截圖如下:
現(xiàn)在逢捺,master分支和feature1分支的關(guān)系如下圖所示:
利用”git log --graph --pretty=oneline --abbrev-commit”命令行可以看到兩個分支的合并情況,截圖如下:
最后利用”git branch -d feature1”命令行刪除本地的版本庫中的feature1分支癞季,截圖如下:
至此劫瞳,解決沖突的工作完成。
備注:
當(dāng)Git無法自動合并分支時绷柒,就必須首先解決沖突志于。解決沖突后,再提交废睦,合并完成伺绽;
解決沖突就是把Git合并失敗的文件手動編輯為我們希望的內(nèi)容,再提交嗜湃。
7奈应、命令行方式下的git的分支管理策略:
通常合并分支時,如果可能的話git會用Fast forward(快進(jìn))模式购披,但在這種模式下刪除分支后杖挣,會丟掉分支上的信息亮蒋。
如果想要強(qiáng)制禁用Fast forward模式的話酪术,就要使用--no-ff方式的git merge,示例如下:
利用”git checkout -b dev”命令行在本地的版本庫中創(chuàng)建并切換到dev分支上借宵,截圖如下:
在dev分支上修改本地工作區(qū)中的readme.rtf文件的內(nèi)容橘荠,修改之后利用"git add 文件名稱”命令行把文件的修改添加到本地的版本庫中的暫存區(qū)中屿附,然后利用"git commit -m “提交說明””命令行把本地的版本庫中的暫存區(qū)中的修改提交到本地的版本庫中的dev分支中,截圖如下:
然后利用”git checkout master”命令行切換回本地的master分支中哥童,截圖如下:
然后利用”git merge --no-ff -m"文字說明"dev”命令行把dev分支上的內(nèi)容合并到當(dāng)前的master分支上挺份,命令行中的--no-ff參數(shù)表示禁用Fast forward(快進(jìn))模式,截圖如下:
因為本次合并要創(chuàng)建一個新的commit贮懈,所以加上-m參數(shù)匀泊,要把commit的描述寫進(jìn)去优训。
合并后利用”git log--graph --pretty=oneline --abbrev-commit”命令行來查看分支的歷史,截圖如下:
可以看到在不使用Fast forward模式的情況下各聘,merge后就如下圖所示:
分支策略:
在實際的開發(fā)過程中揣非,應(yīng)該按照如下的幾個基本原則進(jìn)行分支管理:
首先,master分支應(yīng)該是非常穩(wěn)定的躲因,也就是僅用來發(fā)布新版本的早敬,平時不能在上面進(jìn)行開發(fā);
如下圖所示大脉,先在master分支之外創(chuàng)建一個dev分支搞监,然后基于dev分支再創(chuàng)建不同開發(fā)者的分支,每個開發(fā)者都有一個屬于他們自己的獨立分支镰矿,可以使用開發(fā)者的名字來給這些分支進(jìn)行命名琐驴。每個開發(fā)者都在屬于他們自己的分支上進(jìn)行開發(fā),然后時不時地往dev分支上進(jìn)行合并秤标,到某個時候绝淡,比如1.0版本發(fā)布的時候,再把dev分支合并到master分支上苍姜,最后在master分支上發(fā)布1.0版本牢酵。
合并分支時,加上--no-ff參數(shù)就可以用普通的模式進(jìn)行合并了怖现,用這種方式進(jìn)行的合并可以看出合并的歷史記錄茁帽,而fast forward合并就看不出來曾經(jīng)合并的歷史記錄。
8屈嗤、命令行方式下的git的Bug分支處理:
? ? ? ?在軟件開發(fā)過程中潘拨,一旦有了bug就需要及時地進(jìn)行修復(fù)。在git中由于分支是如此的強(qiáng)大饶号,所以每個bug都可以通過一個新的臨時分支來進(jìn)行修復(fù)铁追,修復(fù)后合并分支,然后將臨時的分支刪除就可以了茫船。
? ? ? ?當(dāng)開發(fā)者接到一個修復(fù)一個代號為101的bug的任務(wù)時琅束,很自然地首先想創(chuàng)建一個名為issue-101的分支來修復(fù)它,但是當(dāng)前正在dev分支上進(jìn)行的工作還沒有提交了算谈,截圖如下:
并不是開發(fā)者不想提交涩禀,而是工作只進(jìn)行到了一半,沒有辦法進(jìn)行提交然眼,預(yù)計完成還需要一天的時間艾船。但是,必須在兩個小時內(nèi)修復(fù)該bug,此時應(yīng)該怎么辦呢屿岂?針對這種情況践宴,可以在終端中執(zhí)行”git stash”命令行,它的作用是把當(dāng)前工作的現(xiàn)場“儲藏”起來爷怀,等以后恢復(fù)現(xiàn)場了再繼續(xù)進(jìn)行工作阻肩,截圖如下:
然后利用”git status”命令行來查看當(dāng)前dev分支的情況,發(fā)現(xiàn)當(dāng)前dev分支是干凈的(除非有沒有被Git管理的文件)运授,因此可以放心地創(chuàng)建新的分支來修復(fù)bug了烤惊,截圖如下:
首先要確定在哪個分支上修復(fù)該bug,假定需要在master分支上進(jìn)行修復(fù)吁朦,就從master分支上創(chuàng)建臨時的分支撕氧。利用”git checkout master”命令行切換到master分支上,截圖如下:
然后利用”git checkout -b 分支名稱”命令行在master分支上創(chuàng)建一個臨時分支來處理此bug喇完,截圖如下:
打開本地工作區(qū)中的readme.rtf文件,在此文件中修復(fù)bug剥啤,然后利用"git add 文件名稱”命令行把本地文件的修改添加到本地版本庫中的暫存區(qū)中锦溪,然后再利用"git commit -m “提交說明””命令行把本地版本庫中的暫存區(qū)中的文件的修改提交到本地版本庫中的臨時分支issue-101上,截圖如下:
修復(fù)完成后府怯,利用”git checkout master”命令行切換到master分支上刻诊,然后再利用”git merge --no-ff -m"提交說明"issue-101”命令行把issue-101分支上的內(nèi)容合并到當(dāng)前的master分支上,最后再利用”git branch -dissue-101”命令行刪除issue-101分支即可牺丙。這樣一波操作下來则涯,原計劃兩個小時的bug修復(fù)只花了五分鐘,然后再利用”git checkout dev”命令行切回到dev分支繼續(xù)干活冲簿,截圖如下:
切換回dev分支以后利用”git status”命令行查看當(dāng)前工作區(qū)的情況粟判,發(fā)現(xiàn)當(dāng)前的工作區(qū)中是干凈的,截圖如下:
然后利用”git stash list”命令行查看之前把dev分支上的內(nèi)容存到了什么地方峦剔,截圖如下:
從終端中可以看出档礁,把之前的內(nèi)容存到了stash里面了。有兩種恢復(fù)的方式吝沫,第一種是利用”git stash apply”命令行進(jìn)行恢復(fù)呻澜,但是恢復(fù)之后stash里面的內(nèi)容不能刪除,還需要再利用"git stash drop”命令行來刪除惨险。另一種方式是利用”git stash pop”命令行在恢復(fù)的同時把stash里面的內(nèi)容也刪除了羹幸,用第二種方式操作的截圖如下:
然后再利用”git stash list”命令行進(jìn)行查看就看不到stash里面的內(nèi)容了,截圖如下:
可以在終端中多次使用”git stash”命令行辫愉,然后在恢復(fù)的時候先用”git stash list”命令行進(jìn)行查看栅受,然后再利用”git stash apply stash@{指定數(shù)字}”命令行恢復(fù)指定的stash即可。
備注:
修復(fù)bug時,會通過創(chuàng)建新的bug分支來進(jìn)行修復(fù)窘疮,然后合并袋哼,最后刪除;
當(dāng)手頭的工作沒有完成時闸衫,先把工作現(xiàn)場利用”git stash”命令行存儲一下涛贯,然后去修復(fù)bug,修復(fù)完成后再利用”git stash pop”命令行回到工作現(xiàn)場繼續(xù)之前的開發(fā)蔚出。
9弟翘、命令行方式下的git的Feature分支:
在軟件開發(fā)中,總會有無窮無盡的新功能不斷地添加進(jìn)來骄酗。當(dāng)每添加一個新功能時稀余,肯定不希望因為一些實驗性質(zhì)的代碼而把主分支搞亂了,所以當(dāng)每添加一個新功能時趋翻,最好新創(chuàng)建一個feature分支睛琳,在上面進(jìn)行開發(fā),待開發(fā)完成后再進(jìn)行合并踏烙,最后刪除該feature分支即可师骗。
? ? ? ?現(xiàn)在開發(fā)名為”Vulcan”的新功能。利用”git checkout -b 分支名稱”命令行創(chuàng)建并切換到一個新的分支上讨惩,截圖如下:
然后打開feature-vulcan分支上的本地的工作區(qū)中的readme.rtf文件辟癌,修改其中的內(nèi)容,然后利用"git add 文件名稱”命令行和"git commit -m “提交說明””命令行把文件的修改提交到本地的版本庫中的feature-vulcan分支上荐捻,截圖如下:
然后利用”git checkout dev”命令行切回dev分支準(zhǔn)備合并黍少,截圖如下:
一切順利的話,feature分支和bug分支是類似的处面,合并厂置,然后刪除就可以了,但是此時接到上級的命令鸳君,由于某種原因新功能必須取消农渊。雖然白干了,但是這個包含機(jī)密資料的分支還是必須就地銷毀或颊,利用”git branch -d feature-vulcan”命令行把feature-vulcan分支刪除砸紊,截圖如下:
銷毀失敗,原因是feature-vulcan分支還沒有被合并了囱挑,如果刪除將丟失掉修改醉顽,如果要強(qiáng)行刪除,就需要使用大寫的-D參數(shù)平挑,即”git branch -Dfeature-vulcan”命令行游添,截圖如下:
備注:
開發(fā)一個新的功能系草,最好新建一個feature分支;
如果要丟棄一個沒有被合并過的分支唆涝,可以通過”git branch -D <name>”命令行強(qiáng)行進(jìn)行刪除找都。
10、命令行方式下的git的多人協(xié)作:
? ? ? ?當(dāng)從遠(yuǎn)程倉庫克隆時廊酣,實際上git自動把本地的master分支和遠(yuǎn)程的master分支對應(yīng)起來了能耻,并且遠(yuǎn)程倉庫的默認(rèn)名稱是origin。
? ? ? ?利用”git remote”命令行查看遠(yuǎn)程倉庫的信息亡驰,截圖如下:
還可以利用”git remote -v”命令行查看更為詳細(xì)的遠(yuǎn)程倉庫的信息晓猛,截圖如下:
上面顯示了可以抓取和推送的origin的地址。如果沒有推送權(quán)限凡辱,就看不到push的地址了戒职。
推送分支:
推送分支就是把該分支上的所有的本地提交推送到遠(yuǎn)程庫中⊥盖可以利用”git pushorigin分支名稱”命令行把指定本地的分支推送到遠(yuǎn)程分支上洪燥,截圖如下:
但是,并不是一定要把所有的本地分支都往遠(yuǎn)程進(jìn)行推送乳乌,比如:
(1)master分支是主分支蚓曼,因此要時刻與遠(yuǎn)程進(jìn)行同步;
(2)dev分支是開發(fā)分支钦扭,團(tuán)隊所有成員都需要在上面進(jìn)行工作,所以也需要與遠(yuǎn)程進(jìn)行同步床绪;
(3)bug分支只用于在本地修復(fù)bug客情,就沒必要推送到遠(yuǎn)程了;
(4)feature分支是否推到遠(yuǎn)程要取決于實際的情況癞己。
現(xiàn)在模擬項目中的另一個開發(fā)者在他的電腦中克隆遠(yuǎn)程倉庫(在同一臺電腦下的另一個目錄中對遠(yuǎn)程倉庫進(jìn)行克掳蛘)”匝牛可以使用”git clone 遠(yuǎn)程倉庫地址”命令行實現(xiàn)上述的目的仰担,截圖如下:
當(dāng)另外的開發(fā)者從遠(yuǎn)程倉庫克隆時,默認(rèn)情況下只能克隆到遠(yuǎn)程倉庫的master分支绩社,利用”git branch”命令行進(jìn)行查看摔蓝,截圖如下:
現(xiàn)在,另外的開發(fā)者要在dev分支上進(jìn)行開發(fā)愉耙,就必須創(chuàng)建本地的版本庫中的dev分支和遠(yuǎn)程倉庫origin的dev分支贮尉,并且把它們兩個進(jìn)行關(guān)聯(lián),可以利用”git checkout -b dev origin/dev”命令行達(dá)到上述的目的朴沿,截圖如下:
現(xiàn)在這個開發(fā)者就可以在本地的版本庫中的dev分支上進(jìn)行文件的修改猜谚,然后把這個修改push到遠(yuǎn)程倉庫origin的dev分支上了败砂。
在本地的工作區(qū)中創(chuàng)建一個名為"clone test.docx”的新的文件,然后使用"git add 文件名稱”命令行把這個新創(chuàng)建的文件從本地的工作區(qū)中添加到本地的版本庫中的暫存區(qū)中魏铅,然后再使用"git commit -m “提交說明””命令行把這個文件添加到本地的版本庫中的dev分支上昌犹,截圖如下:
然后再利用”git push origin dev”命令行把本地的文件推送到遠(yuǎn)程倉庫origin的dev分支上,截圖如下:
再看此時相應(yīng)的github上览芳,多了一個dev分支了斜姥,截圖如下:
另一個開發(fā)者已經(jīng)向遠(yuǎn)程倉庫origin的dev分支上推送了他的提交,而碰巧自己在自己電腦上的工作區(qū)中(dev分支)對文件也進(jìn)行了修改路操,并提交到了本地的版本庫中的dev分支上了疾渴,然后將進(jìn)一步提交到遠(yuǎn)程倉庫origin的dev分支上,截圖如下:
從截圖中可以看出推送失敗了屯仗,因為之前另一個開發(fā)者推送到遠(yuǎn)程倉庫的提交和你試圖推送的提交有沖突搞坝。解決辦法如下:
使用"git pullorigin/dev”命令行把遠(yuǎn)程倉庫origin中的dev分支上的最新的文件提交拉取下來,截圖如下:
從截圖中的”There is no tracking information for the current branch.”語句可以看出拉取失敗魁袜,原因是沒有指定本地dev分支與遠(yuǎn)程origin/dev分支的鏈接桩撮。利用”git branch--set-upstream-to=origin/dev dev”命令行把本地dev分支與遠(yuǎn)程origin/dev分支進(jìn)行連接,截圖如下:
然后再使用”git pull”命令行進(jìn)行拉取峰弹,截圖如下:
拉取成功店量。如果拉取的時候有沖突的話需要先手動解決沖突,解決完沖突后再利用"git add 文件名稱”命令行把本地工作區(qū)中的文件添加到本地的版本庫中的暫存區(qū)中鞠呈,然后再利用"git commit -m “提交說明””命令行把文件提交到本地的版本庫中的dev分支上融师,最后再push到遠(yuǎn)程倉庫origin中的dev分支上。
總結(jié):
多人協(xié)作的工作模式通常是這樣的:
(1)首先蚁吝,可以使用”git push origin <branch-name>”命令行把本地的版本庫中的相應(yīng)的分支中的內(nèi)容推送到遠(yuǎn)程倉庫origin中的對應(yīng)的分支上旱爆;
(2)如果推送失敗,原因是遠(yuǎn)程倉庫的分支比本地倉庫的分支更新窘茁,需要先使用”git pull?origin/分支名稱”命令行把遠(yuǎn)程倉庫中的內(nèi)容拉取過來怀伦;
(3)如果在拉取的過程中發(fā)現(xiàn)有沖突的話則應(yīng)該先在本地手動解決沖突,解決完之后再使用”git push origin <branch-name>”命令行推送到遠(yuǎn)程倉庫中山林。
備注:
(1)利用”git remote -v”命令行查看更為詳細(xì)的遠(yuǎn)程倉庫的信息房待;
(2)在本地新建的分支如果不推送到遠(yuǎn)程的話其他人是不可見的;
(3)使用”git push origin<branch-name>”命令行把本地的文件推送到遠(yuǎn)程倉庫中驼抹;
(4)如果推送失敗的話是因為遠(yuǎn)程倉庫的分支比本地倉庫的分支更新桑孩,應(yīng)該使用”git pull?origin/分支名稱”命令行把遠(yuǎn)程倉庫中的內(nèi)容拉取過來,如果發(fā)現(xiàn)有沖突的話則應(yīng)該在本地手動解決沖突框冀,然后再利用”git push origin <branch-name>”命令行推送到遠(yuǎn)程倉庫中洼怔;
(5)如果git pull的時候提示no tracking information,則說明本地的分支和遠(yuǎn)程的分支的鏈接關(guān)系沒有創(chuàng)建左驾,需要用"git branch --set-upstream-to <branch-name> origin/<branch-name>”命令行先創(chuàng)建鏈接镣隶,然后再使用”git pull”命令行從遠(yuǎn)程倉庫中進(jìn)行拉取极谊。
11、命令行方式下的git的標(biāo)簽創(chuàng)建:
? ? ? ?首先要使用”git checkout 分支名稱”命令行切換到需要打標(biāo)簽的分支上安岂,截圖如下:
然后使用“git tag 標(biāo)簽名稱”命令行給這個分支打一個標(biāo)簽轻猖,截圖如下:
然后可以使用”git tag”命令行查看此分支上的所有標(biāo)簽,截圖如下:
默認(rèn)標(biāo)簽是打在最新提交的commit上的域那,但有時候忘了打標(biāo)簽咙边,比如現(xiàn)在已經(jīng)是周五了,但應(yīng)該在周一打的標(biāo)簽沒有打次员,如果想在再打周一的標(biāo)簽的話則首先應(yīng)該使用”git log --pretty=oneline --abbrev-commit”命令行來查看文件的修改記錄败许,截圖如下:
然后對想要打標(biāo)簽的版本打標(biāo)簽。比如希望給”creat test.rtf"操作打標(biāo)簽淑蔚,找到它對應(yīng)的版本號”966273f”市殷,然后使用”git tag 標(biāo)簽名稱 版本號”命令行打標(biāo)簽,截圖如下:
再使用”git tag”命令行查看標(biāo)簽刹衫,截圖如下:
標(biāo)簽不是按時間順序列出的醋寝,而是按字母排序的。
然后可以使用”git show 標(biāo)簽名稱”來查看標(biāo)簽的信息带迟,截圖如下:
還可以使用"git tag -a 標(biāo)簽名稱-m“說明文字”指定的版本號”命令行來創(chuàng)建帶有說明的標(biāo)簽音羞,命令行中的-a用來指定標(biāo)簽名,-m用來指定說明文字仓犬,截圖如下:
然后可以使用”git show 標(biāo)簽名稱”命令行來查看說明文字嗅绰,截圖如下:
備注:
(1)”git tag 標(biāo)簽名稱”命令行用于新建一個標(biāo)簽,默認(rèn)為HEAD搀继,也可以指定一個commit id办陷;
(2)"git tag -a 標(biāo)簽名稱-m“說明文字”指定的版本號”命令行來創(chuàng)建帶有說明的標(biāo)簽;
(3)”git tag”命令行用來查看所有的標(biāo)簽律歼。
12、命令行方式下的git的操作標(biāo)簽:
如果標(biāo)簽打錯了可以使用”git tag -d 標(biāo)簽名稱”命令行來刪除這個標(biāo)簽啡专,截圖如下:
因為創(chuàng)建的標(biāo)簽都只存儲在本地险毁,不會自動推送到遠(yuǎn)程,所以打錯的標(biāo)簽可以在本地安全地刪除们童。
可以使用”git push origin 標(biāo)簽名稱”命令行把本地的標(biāo)簽推送到遠(yuǎn)程倉庫畔况,截圖如下:
或者使用”git push origin—tags”命令行一次性地把本地標(biāo)簽都推送到遠(yuǎn)程倉庫中:
如果標(biāo)簽已經(jīng)推送到遠(yuǎn)程,要刪除遠(yuǎn)程標(biāo)簽就麻煩一點慧库,先從本地刪除:
然后從遠(yuǎn)程刪除跷跪。刪除命令也是push,但是格式如下:
備注:
(1)”git push origin 標(biāo)簽名稱”命令行可以把本地的標(biāo)簽推送到遠(yuǎn)程倉庫齐板;
(2)”git push origin --tags”命令行可以推送全部未推送過的本地標(biāo)簽到遠(yuǎn)程倉庫吵瞻;
(3)”git tag -d 標(biāo)簽名稱”命令行來刪除一個本地標(biāo)簽葛菇;
(4)”git push origin :refs/tags/標(biāo)簽名稱”來刪除一個遠(yuǎn)程倉庫中的標(biāo)簽。
13橡羞、如何使用Github:
? ? ? ?我們一直用GitHub作為免費的遠(yuǎn)程倉庫眯停,如果是個人的開源項目,放到GitHub上是完全沒有問題的卿泽。其實GitHub還是一個開源協(xié)作社區(qū)莺债,通過GitHub既可以讓別人參與你的開源項目,同時也可以參與別人的開源項目签夭。
? ? ? ?在GitHub出現(xiàn)以前齐邦,開源項目開源容易,但讓廣大開發(fā)者參與進(jìn)來就是比較困難的事情了第租。因為要參與措拇,就要提交代碼,而給每個想提交代碼的開發(fā)者都開一個賬號那是不現(xiàn)實的煌妈,因此開發(fā)者也僅限于報個bug迂曲,即使能改掉bug凑术,也只能把diff文件用郵件發(fā)過去,很不方便。但是在GitHub上捆交,利用git極其強(qiáng)大的克隆和分支功能真正實現(xiàn)了廣大開發(fā)者自由參與各種開源項目的目的了。
? ? ? ?如果想在GitHub上為某個庫修復(fù)一個bug或者增加一個新功能捻脖,那就要先fork那個庫到自己的GitHub上鸠窗,實際上是給原來的那個庫增加了一個新分支,然后從自己的GitHub(遠(yuǎn)程庫)中把項目克隆到本地比被,然后在本地的工作區(qū)中給這個項目增加一個新文件色难,然后再把這個項目由本地的工作區(qū)中添加到本地的版本庫中的暫存區(qū)中,然后再把這個項目提交到本地的版本庫中的master分支中等缀,最后再push到自己的GitHub(遠(yuǎn)程庫)中枷莉。如果希望原來的官方庫能夠接受自己的修改,就要在自己的GitHub上發(fā)起一個pull request請求尺迂,當(dāng)然對方是否接受請求就不一定了笤妙。
? ? ? ?下面以fork廖雪峰的GitHub上的一個庫"https://github.com/michaelliao/learngit”為例進(jìn)行說明,截圖如下:
對應(yīng)的本地的工作區(qū)中的截圖如下:
提交完pull request請求之后噪裕,在原庫的GitHub上就顯示如下的截圖:
總結(jié):
(1)在GitHub上蹲盘,可以任意fork開源倉庫;
(2)自己擁有fork后的倉庫的讀寫權(quán)限膳音;
(3)可以推送pull request給官方倉庫來貢獻(xiàn)代碼召衔。
14、如何使用碼云:
? ? ? ?中國大陸用戶在使用GitHub時由于國內(nèi)防火墻的原因祭陷,用戶經(jīng)常會遇到訪問速度太慢的問題苍凛,有時候還會出現(xiàn)無法連接的情況趣席。如果想在國內(nèi)環(huán)境下正常使用git的話可以使用國內(nèi)的git托管服務(wù)“碼云”。
? ? ? ?和GitHub相比毫深,碼云也提供了免費的git倉庫吩坝。此外還集成了代碼的質(zhì)量檢測、項目演示等功能哑蔫。對于團(tuán)隊協(xié)作開發(fā)钉寝,碼云還提供了項目管理、代碼托管闸迷、文檔管理的服務(wù)嵌纲,5人以下小團(tuán)隊免費。
? ? ? ?如果我們已經(jīng)有了一個本地的git倉庫(例如腥沽,一個名為mayun的本地庫)逮走,可以按照如下的步驟把它關(guān)聯(lián)到碼云的遠(yuǎn)程庫中。首先今阳,在碼云上創(chuàng)建一個新的倉庫师溅,如圖所示:
在填寫相關(guān)信息后,點擊“創(chuàng)建”按鈕來正式創(chuàng)建碼云的遠(yuǎn)程庫盾舌,創(chuàng)建成功后截圖如下:
然后在本地的終端中利用”cd 本地的工作區(qū)的地址”命令行打開本地的工作區(qū)墓臭,然后再利用”git init”命令行在本地的工作區(qū)中創(chuàng)建版本庫,然后在本地的工作區(qū)中創(chuàng)建一個”test.docx”文件妖谴,截圖如下:
然后利用"git add 文件名稱”命令行把文件由本地的工作區(qū)添加到本地的版本庫中的暫存區(qū)中窿锉,然后再利用"git commit -m “提交說明””命令行把文件由本地的版本庫中的暫存區(qū)中提交到本地的版本庫中的master分支上,截圖如下:
然后再利用"git remote add origin 碼云遠(yuǎn)程倉庫地址”命令行和”git push -u origin master"命令行膝舅,把本地倉庫和遠(yuǎn)程倉庫進(jìn)行關(guān)聯(lián)并把本地倉庫中的master分支上的內(nèi)容推送到遠(yuǎn)程倉庫中的master分支上嗡载,截圖如下:
可以看到當(dāng)推送的時候會報錯,這是因為碼云中的README.md文件不在本地代碼的目錄中仍稀⊥莨觯可以在終端中運行”git pull --rebase origin master”命令行來解決這個問題,然后再運行”git push -u origin master”命令行把本地的版本庫中的master分支上的內(nèi)容上傳到碼云的遠(yuǎn)程倉庫中的master分支中技潘,截圖如下:
再看碼云遠(yuǎn)程庫中遥巴,已經(jīng)出現(xiàn)了在本地新添加的文件了,說明push成功崭篡,截圖如下:
利用"git remote -v”命令行查看遠(yuǎn)程庫信息,截圖如下:
備注:一個本地庫既可以關(guān)聯(lián)碼云又可以關(guān)聯(lián)Github吧秕,只不過要把兩個遠(yuǎn)程庫的名字做區(qū)別琉闪。
15、命令行方式下的git的配置別名:
? ? ? ?有的指令比較長砸彬,不便于記憶颠毙,可以在終端中使用"git config --globalalias.簡化后的指令 簡化前的指令”命令行來把指令進(jìn)行簡化斯入。
? ? ? ?如果想用co表示checkout,ci表示commit蛀蜜,br表示branch刻两,則可以在終端中運行如下的命令行:
$ git config --globalalias.co checkout
$ git config --globalalias.ci commit
$ git config --globalalias.br branch
上面命令行中的”--global”代表的是是全局參數(shù),也就是說這些指令在這臺電腦的所有Git倉庫下都有用滴某。
通過上面的修改磅摹,以后再提交時就可以簡寫成如下的命令行了:
$git ci -m"bala bala bala..."
在“3、命令行方式下的git的文件撤銷修改”一節(jié)中可以知道霎奢,”git reset HEAD file”命令行可以把暫存區(qū)的修改撤銷掉(unstage)户誓,重新放回到工作區(qū)中。既然是一個unstage操作幕侠,就可以用如下的命令行配置一個unstage別名:
$git config --globalalias.unstage'reset HEAD’
當(dāng)你敲入命令行:
$git unstagetest.py
實際上git執(zhí)行的是:
$ git resetHEADtest.py
? ? ? ?配置一個"git last"指令帝美,讓其顯示最后一次提交的信息:
$git config --globalalias.last'log -1’
這樣,用git last就能顯示最近一次的提交了:
在配置git的時候晤硕,加上”--global”參數(shù)代表的是這些指令在這臺電腦的所有Git倉庫下都有用悼潭,如果不加,那只針對當(dāng)前的倉庫起作用舞箍。
每個倉庫的git配置文件都放在本地的版本庫中的config文件中舰褪,截圖如下:
在終端中用命令行打開config文件,如下圖所示:
別名就在[alias]后面创译,要刪除別名抵知,直接把對應(yīng)的行刪掉即可。