1. 創(chuàng)建git項目
比如目前是在demo文件夾中,那么
git? init
可以吧demo文件夾創(chuàng)建為git的根目錄:
創(chuàng)建完成后可以看到,demo文件夾下面多了一個.git文件夾,里面存放的是git倉庫的所有文件和內(nèi)容:
里面的內(nèi)容包含了一個完整的git倉庫勒庄,比如前面提到的元數(shù)據(jù)就存儲在objects文件夾下面。
如果不想創(chuàng)建當(dāng)前目錄為git倉庫,想把倉庫創(chuàng)建在當(dāng)前目錄的子目錄下面涨颜,比如test,可以執(zhí)行下面的命令:
git? init? test
這樣就創(chuàng)建了一個test倉庫茧球,進去可以看到.git文件夾:
2. 提交文件
在git倉庫下面新建一個文件hello.txt庭瑰,并寫入內(nèi)容“hello world 11”(新文件也可以從其他地方拷貝過來):
增加新文件后,來看一下倉庫目前的狀態(tài):
git? status
這個命令列出了一些倉庫和文件的信息抢埋,其中hello.txt文件的名字為紅色弹灭,代表文件本身還是獨立的督暂,沒有交給git倉庫來管理。要把文件提交到git里面穷吮,第一步就是要把文件添加到暫存區(qū)逻翁,使用add命令:
git? add? hello.txt
添加到暫存區(qū)后,文件名字變?yōu)榫G色酒来,git狀態(tài)顯示hello.txt是一個倉庫新文件卢未,現(xiàn)在的狀態(tài)才允許我們?nèi)ヌ峤坏絞it里面。
status命令打印出的內(nèi)容也有一個提示堰汉,就是git rm名辽社,這個命令允許我們把添加到暫存區(qū)的文件從暫存區(qū)刪除:
git? rm? --cached? hello.txt
可以看到把文件從暫存區(qū)刪除以后,文件又恢復(fù)了新文件的一個狀態(tài)翘鸭,名字變?yōu)榱思t色滴铅。注意從git暫存區(qū)刪除并不是從目錄中刪除,文件只是改變了狀態(tài)就乓。
有時候文件夾下面文件非常多汉匙,一個一個添加顯然是很麻煩的,我們可以用批量添加到暫存區(qū)的命令來處理:
git? add? -A
文件添加到暫存區(qū)后生蚁,下一步就是提交到本地git倉庫:
git? commit? hello.txt? -m? '提交hello文件 11'
其中-m后面的內(nèi)容是對本次提交的一個注釋噩翠。
可以看到提交命令打印出了git倉庫變化的信息,一個文件發(fā)生了變化并新增到倉庫中邦投。再來看看倉庫的狀態(tài):
這時候顯示工作區(qū)很干凈伤锚,沒有要提交的文件。上面就是一個新文件從添加到提交到本地倉庫的一個整個的流程志衣。提交也有批量提交的命令:
git commit -am '快速提交所有'
如何回退到前面提交的版本呢屯援?首先找到版本號,查看所有提交日志:
git log????
commit后面的一長串序列化就是每次提交的唯一版本號念脯,也是上一篇文章提到的元數(shù)據(jù)的id狞洋,第一行里面HEAD指向的版本就是當(dāng)前版本,因此绿店,Git允許我們在版本的歷史之間穿梭吉懊,使用命令git reset --hard commit_id:
git reset --hard abeb59745aed5ae0402d61d2defcc57b83b82cd1
再來看提交歷史
顯示的就是HEAD當(dāng)前指向的版本和以前的提交,之后的提交并沒有顯示假勿,那么如果我們想回到最新的一次提交惕它,又忘了id了怎么辦?可以用git reflog查看命令歷史废登,以便確定要回到未來的哪個版本:
git reflog
打印出的內(nèi)容中淹魄,HEAD指向的歷史都打印了出來,顯然第二個HEAD@{2}是最新的一次提交堡距,我們可以把HEAD指向這個提交甲锡,前面的id只顯示前幾位兆蕉,不過我們使用版本號的時候,只要唯一缤沦,輸入前幾位也可以:
git reset --hard?5d43c54
這樣就又回來了虎韵。所以大家可以放心的在各個提交之間穿梭。
如果想要丟棄現(xiàn)在正在修改為部分缸废,如何操作包蓝?你在已經(jīng)提交的文件里又修改了一些內(nèi)容,加了一些代碼企量,沒提交前發(fā)現(xiàn)這些東西是錯誤的测萎,想把文件恢復(fù)到修改前的狀態(tài):
可以使用下面的命來丟棄對文件的修改:
git checkout --? hello.txt
如果丟棄前,發(fā)現(xiàn)已經(jīng)添加到了暫存區(qū)届巩,那么要先執(zhí)行一條命令:
git reset HEAD hello.txt
然后再執(zhí)行?git checkout --? hello.txt 就可以丟棄了硅瞧。
如果已經(jīng)提交了,那也很簡單恕汇,直接使用上面的版本退回即可腕唧。如果已經(jīng)推送到遠程了,那只能再修改回來然后提交推送了瘾英。
如果項目優(yōu)化后枣接,其中一個文件已經(jīng)徹底沒用了,可以刪除了缺谴,如何在git倉庫中刪除呢月腋?首先要從操作系統(tǒng)文件夾中刪除文件:
這時候查看倉庫狀態(tài):
這時候有兩種選擇,一個是刪除錯了瓣赂,需要恢復(fù),那么直接從倉庫里恢復(fù)即可:
git checkout -- delete.txt
還有一種情況是刪除對了片拍,但是現(xiàn)在只從文件夾中刪除了煌集,git中還沒有刪除,需要執(zhí)行下面的命令:
git rm delete.txt
git commit -m 'delete delete.txt'
這樣就從本地倉庫中刪除了捌省。
3. 推送文件到遠程倉庫
本地倉庫有了文件后苫纤,可以每次都推送到遠程倉庫,也可以積攢一批之后纲缓,整個推送過去卷拘。推送到遠程倉庫前,得先有一個遠程倉庫祝高,可以自行注冊github栗弟,gitlab,gitee等倉庫:
然后在遠程倉庫中創(chuàng)建一個test項目:
可以看到項目連接的左側(cè)顯示有https和ssh兩種傳輸方式工闺,一般我們開發(fā)都是使用最快的ssh方式支持的原生git協(xié)議乍赫,使用這種方式需要做一下配置瓣蛀,首先初始化本地git用戶信息:
git config --global user.name "Your Name"
git config --global user.email "Your email"
然后執(zhí)行命令創(chuàng)建?SSH Key:
ssh-keygen? -t? rsa? -C? "Your email"
中間所有的停頓不用輸入任何東西,直接回車即可雷厂。生成完后惋增,進入用戶目錄下的.ssh文件夾中:
cd ~/.ssh
這里有兩個文件,一個id_rsa改鲫,一個id_rsa.pub诈皿,我們打開id_rsa.pub文件,把里面的內(nèi)容復(fù)制一份像棘。進入遠程倉庫的個人設(shè)置頁面的ssh key設(shè)置頁碼:
添加一個公鑰:
點擊確定稽亏,公鑰就添加完成了。
注意即使一個賬號讲弄,有多個電腦開發(fā)提交措左,也要為每個電腦生成公鑰并添加到遠程配置中。公鑰設(shè)置完成后避除,就可以在本地倉庫添加遠程倉庫的地址了:
git remote add origin?git@gitee.com:blueses/test.git
其中origin是遠程倉庫的名字怎披,也是git為默認遠程倉庫起的名字。下面就可以推送到遠程了:
第一次推送瓶摆,提示當(dāng)前分支沒有對應(yīng)的遠程分支凉逛,我們要把兩個對應(yīng)起來,那么第一次推送必須加上--set-upstream參數(shù):
git push --set-upstream origin master
中間提問是否繼續(xù)連接群井,輸入yes状飞,回車即可,打印出來的信息可以看到本地master分支已經(jīng)設(shè)置為跟蹤遠程倉庫的master分支书斜,并已經(jīng)將本地master分支的文件推送到了遠程master上面诬辈。
第一次也可以使用命令:
git push -u origin master
效果一樣。
上面的第一次添加遠程倉庫荐吉,第一次建立跟蹤確實有點麻煩焙糟,不過添加遠程倉庫時也就是這一次,后面再推送就不會這么麻煩了⊙溃現(xiàn)在來看一下遠程倉庫:
可以看到遠程倉庫多了一個我們本地的文件穿撮,并顯示了我們提交文件時寫的注釋,證明推送是成功的痪欲!
來修改一下文件的內(nèi)容:
現(xiàn)在看一下倉庫狀態(tài):
狀態(tài)顯示文件以及進行了修改悦穿,把修改后的文件提交到本地倉庫也很簡單,和前面一樣业踢,先加到暫存區(qū):
git? add? hello.txt
然后提交到本地倉庫:
git? commit? hello.txt? -m '提交修改后的hello.txt? 11-222'
現(xiàn)在向遠程倉庫推送第二次提交內(nèi)容栗柒,就不會像第一次那么麻煩了:
git push origin
查看遠程倉庫變化:
我們自己的提交和推送的工作很順利,如果別人想加入項目知举,拉取代碼進行開發(fā)怎么辦呢傍衡?需要使用到克隆命令深员,不過在下載代碼之前,也需要本身生成ssh-key蛙埂,然后配置遠程自己的賬戶中倦畅,這個不再描述。
準(zhǔn)備工作做好以后绣的,接下來是克隆代碼:
git clone?git@gitee.com:blueses/test.git
可以看到克隆命令就是一個下載倉庫的過程叠赐,在克隆的目錄中,會生成一個項目名命名的文件夾:
如果想用別的名字屡江,可以在路徑后面加上想要命名的名字芭概,比如想命名為hello:
git clone?git@gitee.com:blueses/test.git hello
克隆完后進入文件夾,可以看到一個一模一樣的git倉庫:
新加入的人員也可以修改文件內(nèi)容并提交:
保存后查看狀態(tài):
然后是添加到暫存:
提交到本地倉庫:
由于新加入的人員是主動克隆的代碼惩嘉,在克隆的時候已經(jīng)做了本地和遠程分支的跟蹤配置罢洲,所以可以直接推送:
git push origin
前面說過origin是默認遠程倉庫的名字,所以這個是可以省略的:
git push
查看遠程倉庫的變化:
原來的項目人員文黎,或者說所有其他的項目人員也要繼續(xù)工作惹苗,提交和推送。關(guān)于添加到暫存區(qū)耸峭,和提交到本地倉庫中桩蓉,兩個都是本地操作,可以毫無顧忌的完成劳闹。但是推送到遠程倉庫前要注意院究,因為不知道遠程倉庫是否有變化,是否有他人的新的提交推送本涕,所以业汰,我們執(zhí)行g(shù)it push前往往都會先執(zhí)行一次從遠程更新到本地的操作:
git pull origin
注意上面的倉庫名origin是默認的,所以同樣可以省略:
git pull
執(zhí)行完后再把本地提交推送到遠程倉庫:
git push
所以菩颖,上面的整個流程就是開發(fā)時的常用流程(添加遠程倉庫和克隆因為只進行一次所以不算)样漆,添加(add),提交(commit)位他,更新(pull),推送(push)产场,當(dāng)然這個流程的前提是在一個分支上鹅髓,多分支開發(fā)后面再說。
查看所有遠程倉庫:
git remote
查看遠程詳細信息:
git remote -v
可以看到除了一個push還有一個fetch京景,git fetch命令是用來同步信息的窿冯,比如遠程新建了一個分支,本地是不能馬上看到的,執(zhí)行g(shù)it fetch之后才能看到:
添加和刪除遠程倉庫的命令是:
git remote add url remote_name
git remote remoge remote_name
如果是默認的遠程倉庫确徙,那么推送和拉取命令中可以省略名字醒串,其它的還是要加上执桌,這樣git可以操作多個遠程倉庫。如何知道默認的遠程倉庫是哪個呢芜赌?可以借助分支的命令:
git branch -avv
可以看到當(dāng)前分支默認關(guān)聯(lián)的是origin的master分支仰挣,所以不加名字會默認推送到origin下面的master分支。
4. 分支管理
使用git的都知道分支的管理缠沈。在使用中有很多人也遇到過各種風(fēng)格膘壶。比如一個master分支一路走到底。還比如一個bug一個分支洲愤,一個需求一個分支颓芭。還有的是根據(jù)環(huán)境進行分支管理,有開發(fā)分支柬赐,測試分支亡问,正式環(huán)境分支。等等各種風(fēng)格都有肛宋,這里值得一說的是州藕,沒有最好的,只有最合適的悼吱,git之所以牛就是因為它適用于從最簡單到最復(fù)雜的各種情況慎框,只要團隊使用方便,舒服后添,就是最好的分支使用方式笨枯。反之因為git分支的使用造成了開發(fā)的混亂,那就得不償失了遇西。
分支可以簡單也可以復(fù)雜馅精,那么分支有沒有用呢?實踐證明還是很有用的粱檀,比如現(xiàn)在已經(jīng)二月份了洲敢,正在緊急開發(fā),而線上運行的是一月份打包的版本茄蚯,這個時候突然發(fā)現(xiàn)線上有個bug需要修改压彭,這個時候在開發(fā)分支上改顯然是不合適的,不僅和新代碼新功能混在一起渗常,測試和上線都是問題壮不。最好的辦法是從線上運行版本的那個時間點的提交的地方拉取一個分支,進行修改這樣可以將影響最小化皱碘,修改完成測試通過上線以后询一,再講修改的代碼合并到其他分支。所以線上正式版本的分支最好用于是master分支,開發(fā)健蕊,測試菱阵,修改問題等等可以從線上拉取分支進行操作,這樣可以將影響降到最低缩功。分支的使用有很多地方晴及,不止這一個例子。
使用分支也能體現(xiàn)git相對于svn的一個優(yōu)勢掂之,以前使用svn切換分支抗俄,速度是相當(dāng)慢的,git則不同世舰,分支的切換速度是秒級的动雹。
下面來看一些具體的分支命令,首先是查看當(dāng)前分支:
git branch
可以看到當(dāng)前只有一個本地分支跟压,就是master胰蝠。但是本地分支有一個,總的分支數(shù)量卻不是一個震蒋,我們已經(jīng)將遠程倉庫關(guān)聯(lián)到了本地倉庫中茸塞,所以本地還有一個遠程倉庫的分支,查看本地和遠程所有分支的命令是:
git branch -avv
遠程分支和本地分支已經(jīng)進行了關(guān)聯(lián)查剖,那么它們是一個分支嗎钾虐?其實并不是,下面來修改一下文件笋庄,然后進行提交操作效扫,完成后,查看所有分支:
可以看到本地提交后,遠程分支并且有隨之改變,所以它們的內(nèi)容并不一樣存崖,因此并不是同一個分支。來看一下本地分支文件的內(nèi)容:
下面切換分支济丘,切換到遠程分支:
git? checkout? origin/master
然后查看文件內(nèi)容:
可以看到遠程分支的文件內(nèi)容還是上一個版本的內(nèi)容,因為我們還沒有push洽蛀,所以遠程沒有變化摹迷。切換回本地分支:
總結(jié):
git branch 查看本地分支
git branch -a 查看本地和遠程所有分支
git branch -av 查看所有分支的詳細信息
git branch -avv 查看所有分支詳細信息以及本地和遠程分支的關(guān)聯(lián)信息
git checkout 切換分支
下面來說說創(chuàng)建分支,首先基于本地當(dāng)前正在使用的分支郊供,創(chuàng)建一個新分支峡碉,比如基于本地master創(chuàng)建一個分支test:
git branch test
如果是基于非當(dāng)前分支創(chuàng)建,比如基于test創(chuàng)建dev颂碘,那么需要加上test分支的名字:
git branch dev test
然后是基于遠程分支創(chuàng)建一個本地新分支异赫,比如基于遠程master分支,創(chuàng)建一個本地demo分支:
git branch demo origin/master
然后是基于一個提交創(chuàng)建一個新分支头岔,首先看一下有哪些提交:
git log
可以看到越下面的記錄是越早的塔拳,第一次的提交是?02686ca5d87f9380d72ec845eb94d716e353d6f3 ,基于第一次提交創(chuàng)建一個分支 first:
git branch first??02686ca5d87f9380d72ec845eb94d716e353d6f3
其實本質(zhì)上來說峡竣,基于分任何內(nèi)容任何形式創(chuàng)建一個新分支靠抑,都是基于一個提交創(chuàng)建分支,這個后面講底層原理的時候回更清楚的講解适掰。
還可以基于一個tag(標(biāo)簽)創(chuàng)建一個新分支颂碧,標(biāo)簽本質(zhì)上可以理解為一個特殊的分支,它是只讀的类浪,因此更加安全载城,可以用來作為版本里程碑,查看所有標(biāo)簽:
git tag
基于當(dāng)前分支創(chuàng)建一個標(biāo)簽?
git tag v1.0
然后基于這個標(biāo)簽創(chuàng)建一個分支tagbranch:
git branch tagbranch v1.0
一個簡單的命令是费就,創(chuàng)建并切換分支dev:
git checkout -b dev
下面來看一下刪除分支诉瓦,比如刪除分支tagbranch:
git branch -d tagbranch
git branch -D 分支名(表示強行刪除一個分支)
-d后面可以跟多個分支,用空格隔開力细,這樣可以批量刪除多個分支睬澡。
上面講了創(chuàng)建分支,切換分支眠蚂,刪除分支煞聪,下面來看一下合并分支,首先整理分支逝慧,講本地master與遠程master保持一致:
基于當(dāng)前master分支創(chuàng)建一個dev分支昔脯,然后切換到dev分支,修改并提交:
注意當(dāng)前分支在dev上馋艺,我們需要把dev的內(nèi)容合并到master上面栅干,這時候先切換到master分支上,然后合并:
git checkout master
git merge dev? (表示將dev分支的內(nèi)容合并到當(dāng)前分支捐祠,也就是master分支)
git push
上面顯示的Fast-forward信息碱鳞,Git告訴我們,這次合并是“快進模式”踱蛀,也就是直接把master指向dev的當(dāng)前提交窿给,所以合并速度非常快率拒。
通常崩泡,合并分支時,如果可能猬膨,Git會用Fast forward模式角撞,但這種模式下,刪除分支后,會丟掉分支信息谒所。如果要強制禁用Fast forward模式热康,Git就會在merge時生成一個新的commit,這樣劣领,從分支歷史上就可以看出分支信息姐军。下面來看一下,創(chuàng)建并切換到一個新分支:
git checkout -b dev2
修改文件并提交尖淘,然后回到master分支:
準(zhǔn)備合并dev2分支奕锌,請注意--no-ff參數(shù),表示禁用Fast forward:
git merge --no-ff -m 'merge with no-ff' dev2
合并后村生,我們用git log看看分支歷史:
git log --graph --pretty=oneline --abbrev-commit
git push到遠程后惊暴,從遠程倉庫也能看到分支歷史:
建議開發(fā)過程中充分利用分支,并且都使用普通模式趁桃,禁用Fast forward缴守,否則看不出分支合并歷史。
下面看一個問題镇辉,如果文件修改到一半還么有提交屡穗,恰好有個bug需要新建一個分支修改,但是現(xiàn)在的代碼又不能提交怎么辦忽肛?可以把正在進行的工作隱藏起來:
git? stash
然后完成新建分支村砂,修改bug,最后切換回來屹逛,并合并分支的過程础废,完成后需要恢復(fù)剛才改到一半的工作,修改查看stash列表:
git stash list
工作現(xiàn)場還在罕模,Git把stash內(nèi)容存在某個地方了评腺,但是需要恢復(fù)一下:
git stash pop
這樣就恢復(fù)到了修改一半但是沒有提交的進度,是非常實用的功能淑掌!
很多人有這樣的習(xí)慣蒿讥,git push前先進行g(shù)it pull,從理論上來說沒啥問題抛腕,提交前先把遠程代碼拉到本地然后進行合并芋绸,最后將本地最新的結(jié)果推送到遠程,這樣是可以的担敌,但是提交時會出現(xiàn)很多自動merge的情況摔敛,其實git多人開發(fā)也是可以一條直線干凈的提交的。在最后push之前全封,可以進行rebase操作:
git? rebase
然后再執(zhí)行g(shù)it push即可马昙。
還有一些命令桃犬,比如在本地創(chuàng)建和遠程分支對應(yīng)的分支,使用
git checkout -b demo origin/demo
demo是分支名行楞,本地和遠程分支的名稱最好一致疫萤。
5. 標(biāo)簽管理
標(biāo)簽可以理解為只讀的一個分支,不能用來推送敢伸,可以下載,發(fā)布新版本往往會專門創(chuàng)建一個標(biāo)簽恒削,創(chuàng)建一個新標(biāo)簽:
git tag tag1
創(chuàng)建一個標(biāo)簽也可以指定標(biāo)簽的信息:
git tag -a v1.0 -m "創(chuàng)建v1.0版本標(biāo)簽"
基于某個分支創(chuàng)建一個標(biāo)簽:
git tag tag2 master
基于某個提交創(chuàng)建一個tag:
git tag tag3?02686ca5d87f9380d72ec845eb94d716e353d6f3
查看標(biāo)簽列表:
git tag
刪除標(biāo)簽
git tag -d tag_name
注意tag的名字最好不要和分支的名字一樣池颈!
推送一個本地標(biāo)簽到遠程:
git push origin <tagname>
推送全部未推送過的本地標(biāo)簽:
git push origin --tags
刪除一個遠程標(biāo)簽(注意origin后面是一個空格):
git? push? origin? :refs/tags/<tagname>
6. 日志管理
列出當(dāng)前master下面所有的提交日志:
git log
來看最上面的一個記錄:
commit右面的序列化表示最新的提交id,后面跟了一些分支和標(biāo)簽表示本次提交和那些分支標(biāo)簽同步钓丰,下面兩行是提交人和提交時間躯砰,最下面是提交備注。
git log命令輸入后携丁,并不會馬上退出琢歇,最下面是一個冒號,這里可以輸入內(nèi)容進行搜索:
輸入左斜杠加上內(nèi)容梦鉴,然后回車李茫,可以看到符合的內(nèi)容開始高亮顯示:
直接git log打印出來的內(nèi)容是非常繁瑣的,可以簡化輸出:
git log --oneline
可以看到省略了提交人和提交時間肥橙,把版本和注釋放在了一行魄宏。
查看指定分支的提交:
git log dev --oneline
查看master分支上面有多少提交dev分支上是沒有的:
git log dev..master
如果反過來就是查看dev上面有多少沒有提交到master上:
git log master..dev
兩個分支merge之后,互相對比才完全沒有區(qū)別存筏。
查看提交網(wǎng)絡(luò):
git log --graph
簡化輸出:
git log --graph --oneline
查看完整的提交id:
git log --graph --pretty=oneline
還有一個是我們上面講分支的時候用到的:
git log --graph --pretty=oneline --abbrev-commit
展示當(dāng)前本次改動的文件內(nèi)容:
git show
也可以展示別的分支:
git show dev
以上就git常用的一些命令宠互,在實際開發(fā)中大家基本上就是使用IDE操作git,但是建議大家能用命令的時候盡量用命令椭坚,這樣可以加深我們對git的理解予跌。