本文主要講解以下內(nèi)容:
一郊愧、安裝 Git 、創(chuàng)建版本庫(kù)
二井佑、時(shí)光機(jī)穿梭
三属铁、遠(yuǎn)程倉(cāng)庫(kù)
四、分支管理
五毅糟、標(biāo)簽管理
六红选、使用GitHub澜公、碼云
第一章
最早Git是在Linux上開(kāi)發(fā)的姆另,很長(zhǎng)一段時(shí)間內(nèi),Git也只能在Linux和Unix系統(tǒng)上跑坟乾。不過(guò)迹辐,慢慢地有人把它移植到了Windows上。現(xiàn)在甚侣,Git可以在Linux明吩、Unix、Mac和Windows這幾大平臺(tái)上正常運(yùn)行了殷费。
要使用Git印荔,第一步當(dāng)然是安裝Git了。本文只講在 Mac OS X 平臺(tái)上的安裝详羡,其他平臺(tái)的安裝都很簡(jiǎn)單仍律,網(wǎng)上教程也很多,再次不再詳述实柠。
如果你正在使用Mac做開(kāi)發(fā)水泉,有兩種安裝Git的方法。
1.1窒盐、安裝 Git
一是安裝homebrew草则,然后通過(guò)homebrew安裝Git,具體方法請(qǐng)參考homebrew的文檔:http://brew.sh/蟹漓。
第二種方法更簡(jiǎn)單炕横,也是推薦的方法,就是直接從AppStore安裝Xcode葡粒,Xcode集成了Git份殿,不過(guò)默認(rèn)沒(méi)有安裝姿锭,你需要運(yùn)行Xcode,選擇菜單“Xcode”->“Preferences”伯铣,在彈出窗口中找到“Downloads”往声,選擇“Command Line Tools”宅荤,點(diǎn)“Install”就可以完成安裝了。
1.2、創(chuàng)建版本庫(kù)
什么是版本庫(kù)呢喂分?版本庫(kù)又名倉(cāng)庫(kù),英文名repository男翰,你可以簡(jiǎn)單理解成一個(gè)目錄痊焊,這個(gè)目錄里面的所有文件都可以被Git管理起來(lái),每個(gè)文件的修改凭语、刪除葱她,Git都能跟蹤,以便任何時(shí)刻都可以追蹤歷史似扔,或者在將來(lái)某個(gè)時(shí)刻可以“還原”吨些。
所以,創(chuàng)建一個(gè)版本庫(kù)非常簡(jiǎn)單炒辉,首先豪墅,選擇一個(gè)合適的地方,創(chuàng)建一個(gè)空目錄:
$ mkdir learngit
$ cd learngit
$ pwd
/Users/Michael/learngit
pwd
命令用于顯示當(dāng)前目錄黔寇。在我的Mac上偶器,這個(gè)倉(cāng)庫(kù)位于/Users/Michael/learngit。
第二步缝裤,通過(guò)git init命令把這個(gè)目錄變成Git可以管理的倉(cāng)庫(kù):
$ git init
Initialized empty Git repository in /Users/michael/learngit/.git/
瞬間Git就把倉(cāng)庫(kù)建好了屏轰,而且告訴你是一個(gè)空的倉(cāng)庫(kù)(empty Git repository),細(xì)心的讀者可以發(fā)現(xiàn)當(dāng)前目錄下多了一個(gè).git
的目錄憋飞,這個(gè)目錄是Git來(lái)跟蹤管理版本庫(kù)的霎苗,沒(méi)事千萬(wàn)不要手動(dòng)修改這個(gè)目錄里面的文件,不然改亂了搀崭,就把Git倉(cāng)庫(kù)給破壞了叨粘。
如果你沒(méi)有看到.git
目錄,那是因?yàn)檫@個(gè)目錄默認(rèn)是隱藏的瘤睹,用ls -ah
命令就可以看見(jiàn)升敲。
也不一定必須在空目錄下創(chuàng)建Git倉(cāng)庫(kù),選擇一個(gè)已經(jīng)有東西的目錄也是可以的轰传。不過(guò)驴党,不建議你使用自己正在開(kāi)發(fā)的公司項(xiàng)目來(lái)學(xué)習(xí)Git,否則造成的一切后果概不負(fù)責(zé)获茬。
1.3 把文件添加到版本庫(kù)
在當(dāng)前目錄下(或者子目錄)下創(chuàng)建一個(gè)文件港庄,然后:
- git add xxx
- git commit -m "xxx"
說(shuō)明
:
添加文件到Git倉(cāng)庫(kù)倔既,分兩步:
使用命令git add <file>,注意鹏氧,可反復(fù)多次使用渤涌,添加多個(gè)文件;
使用命令git commit -m <message>把还,完成实蓬。
第二章
Git和其他版本控制系統(tǒng)如SVN的一個(gè)不同之處就是有暫存區(qū)的概念。
先來(lái)看名詞解釋吊履。
2.1安皱、 工作區(qū)(Working Directory)
就是你在電腦里能看到的目錄,比如我的learngit
文件夾就是一個(gè)工作區(qū):
2.2艇炎、版本庫(kù)(Repository)
工作區(qū)有一個(gè)隱藏目錄.git
酌伊,這個(gè)不算工作區(qū),而是 Git 的版本庫(kù)缀踪。
Git的版本庫(kù)里存了很多東西居砖,其中最重要的就是稱為stage(或者叫index)的暫存區(qū),還有Git為我們自動(dòng)創(chuàng)建的第一個(gè)分支master辜贵,以及指向master的一個(gè)指針叫HEAD悯蝉。
分支和HEAD的概念我們以后再講归形。
前面講了我們把文件往Git版本庫(kù)里添加的時(shí)候托慨,是分兩步執(zhí)行的:
第一步
是用git add把文件添加進(jìn)去,實(shí)際上就是把文件修改添加到暫存區(qū)暇榴;
第二步
是用git commit提交更改厚棵,實(shí)際上就是把暫存區(qū)的所有內(nèi)容提交到當(dāng)前分支。
因?yàn)槲覀儎?chuàng)建Git版本庫(kù)時(shí)蔼紧,Git自動(dòng)為我們創(chuàng)建了唯一一個(gè)master分支婆硬,所以,現(xiàn)在奸例,git commit就是往master分支上提交更改彬犯。
你可以簡(jiǎn)單理解為,需要提交的文件修改通通放到暫存區(qū)查吊,然后谐区,一次性提交暫存區(qū)的所有修改。
當(dāng)我們使用多次 Git add 命令之后逻卖,版本庫(kù)就會(huì)變成下面的樣子:
我們發(fā)現(xiàn)暫存區(qū)的內(nèi)容改變了K瘟小!评也!所以炼杖,git add命令實(shí)際上就是把要提交的所有修改放到暫存區(qū)(Stage)灭返。
然后接著執(zhí)行 git commit -m "XXX",執(zhí)行以后結(jié)果如下圖:
發(fā)現(xiàn)暫存區(qū)變得很“干凈”@ば啊熙含!執(zhí)行git commit
就可以一次性把暫存區(qū)的所有修改提交到分支。如果我們修改的文件很多
2.3艇纺、撤銷文件
工作中我們經(jīng)常用遇到要撤銷修改的情況婆芦,大致分為兩種撤銷:
- 僅僅在工作區(qū)進(jìn)行了修改,并沒(méi)有添加到暫存區(qū)
- 修改的內(nèi)容添加到了暫存區(qū)
- 修改的內(nèi)容已經(jīng)提交到了 版本庫(kù)
第一種情況:
命令 git checkout -- xxx
意思就是喂饥,把xxx文件在工作區(qū)的修改全部撤銷消约。git checkout -- file命令中的--很重要,沒(méi)有--员帮,就變成了“切換到另一個(gè)分支”的命令或粮,我們?cè)诤竺娴姆种Ч芾碇袝?huì)再次遇到git checkout命令。
第二種情況:
Git同樣告訴我們捞高,用命令 git reset HEAD <file>
可以把暫存區(qū)的修改撤銷掉(unstage)氯材,重新放回工作區(qū)。git reset命令既可以回退版本硝岗,也可以把暫存區(qū)的修改回退到工作區(qū)氢哮。當(dāng)我們用HEAD時(shí),表示最新的版本
Tips
: 如果不知道指令怎么寫型檀,可以使用 git status
查看冗尤。
如果只是發(fā)生上述兩種情況,那么還是很好解決的胀溺。如果要是當(dāng)初一個(gè)不當(dāng)心裂七,把修改提交到 版本庫(kù) 了!2治搿背零!怎么辦?无埃?徙瓶?這就用到了 版本回退...
第三種情況:
回退之前,用git log
可以查看提交歷史嫉称,以便確定要回退到哪個(gè)版本侦镇。
HEAD指向的版本就是當(dāng)前版本,因此澎埠,Git允許我們?cè)诎姹镜臍v史之間穿梭虽缕,使用命令 git reset --hard commit_id
要重返未來(lái),用git reflog
查看命令歷史,以便確定要回到未來(lái)的哪個(gè)版本
2.4氮趋、刪除文件
刪除文件分為兩種情況:
情況一:
直接在文件管理器中把沒(méi)用的文件刪了伍派,或者用rm命令刪了:rm xxx
情況二:
從版本庫(kù)中刪除該文件,那就用命令 git rm
刪掉剩胁,并且 git commit
第三章
3.1诉植、添加遠(yuǎn)程庫(kù)
現(xiàn)在的情景是,你已經(jīng)在本地創(chuàng)建了一個(gè)Git倉(cāng)庫(kù)后昵观,又想在GitHub創(chuàng)建一個(gè)Git倉(cāng)庫(kù)晾腔,并且讓這兩個(gè)倉(cāng)庫(kù)進(jìn)行遠(yuǎn)程同步,這樣啊犬,GitHub上的倉(cāng)庫(kù)既可以作為備份灼擂,又可以讓其他人通過(guò)該倉(cāng)庫(kù)來(lái)協(xié)作,真是一舉多得觉至。
首先剔应,登陸GitHub,然后语御,在右上角找到“Create a new repo”按鈕峻贮,創(chuàng)建一個(gè)新的倉(cāng)庫(kù):
在Repository name填入learngit,其他保持默認(rèn)設(shè)置应闯,點(diǎn)擊“Create repository”按鈕纤控,就成功地創(chuàng)建了一個(gè)新的Git倉(cāng)庫(kù):
目前,在GitHub上的這個(gè)learngit倉(cāng)庫(kù)還是空的碉纺,GitHub告訴我們船万,可以從這個(gè)倉(cāng)庫(kù)克隆出新的倉(cāng)庫(kù),也可以把一個(gè)已有的本地倉(cāng)庫(kù)與之關(guān)聯(lián)惜辑,然后唬涧,把本地倉(cāng)庫(kù)的內(nèi)容推送到GitHub倉(cāng)庫(kù)。
現(xiàn)在盛撑,我們根據(jù)GitHub的提示,在本地的learngit倉(cāng)庫(kù)下運(yùn)行命令:
git remote add origin git@github.com:michaelliao/learngit.git
這樣的話本地倉(cāng)庫(kù)和遠(yuǎn)程倉(cāng)庫(kù)就可以產(chǎn)生關(guān)聯(lián)捧搞!
請(qǐng)千萬(wàn)注意抵卫,把上面的michaelliao替換成你自己的GitHub賬戶名,否則胎撇,你在本地關(guān)聯(lián)的就是我的遠(yuǎn)程庫(kù)介粘,關(guān)聯(lián)沒(méi)有問(wèn)題,但是你以后推送是推不上去的晚树,因?yàn)槟愕腟SH Key公鑰不在我的賬戶列表中姻采。
添加后,遠(yuǎn)程庫(kù)的名字就是origin爵憎,這是Git默認(rèn)的叫法慨亲,也可以改成別的婚瓜,但是origin這個(gè)名字一看就知道是遠(yuǎn)程庫(kù)。
下一步刑棵,就可以把本地庫(kù)的所有內(nèi)容推送到遠(yuǎn)程庫(kù)上:
$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (20/20), 1.64 KiB | 560.00 KiB/s, done.
Total 20 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.
To github.com:michaelliao/learngit.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
把本地庫(kù)的內(nèi)容推送到遠(yuǎn)程巴刻,用git push
命令,實(shí)際上是把當(dāng)前分支master推送到遠(yuǎn)程蛉签。
由于遠(yuǎn)程庫(kù)是空的胡陪,我們第一次推送master分支時(shí),加上了-u
參數(shù)碍舍,Git不但會(huì)把本地的master分支內(nèi)容推送的遠(yuǎn)程新的master分支柠座,還會(huì)把本地的master分支和遠(yuǎn)程的master分支關(guān)聯(lián)起來(lái)
,在以后的推送或者拉取時(shí)就可以簡(jiǎn)化命令片橡。
推送成功后愚隧,可以立刻在GitHub頁(yè)面中看到遠(yuǎn)程庫(kù)的內(nèi)容已經(jīng)和本地一模一樣:
從現(xiàn)在起,只要本地作了提交锻全,就可以通過(guò)命令:
git push origin master
把本地master分支的最新修改推送至GitHub狂塘,現(xiàn)在,你就擁有了真正的分布式版本庫(kù)鳄厌!
添加遠(yuǎn)程庫(kù)分為三步:
- 要關(guān)聯(lián)一個(gè)遠(yuǎn)程庫(kù)荞胡,使用命令git remote add origin git@server-name:path/repo-name.git
- 關(guān)聯(lián)后,使用命令git push -u origin master第一次推送master分支的所有內(nèi)容
- 此后了嚎,每次本地提交后泪漂,只要有必要,就可以使用命令git push origin master推送最新修改歪泳。
3.2萝勤、 從遠(yuǎn)程庫(kù)克隆
上次我們講了先有本地庫(kù),后有遠(yuǎn)程庫(kù)的時(shí)候呐伞,如何關(guān)聯(lián)遠(yuǎn)程庫(kù)敌卓。
現(xiàn)在,假設(shè)我們從零開(kāi)發(fā)伶氢,那么最好的方式是先創(chuàng)建遠(yuǎn)程庫(kù)趟径,然后,從遠(yuǎn)程庫(kù)克隆癣防。
首先蜗巧,登陸GitHub,創(chuàng)建一個(gè)新的倉(cāng)庫(kù)蕾盯,名字叫g(shù)itskills:
我們勾選Initialize this repository with a README幕屹,這樣GitHub會(huì)自動(dòng)為我們創(chuàng)建一個(gè)README.md文件。創(chuàng)建完畢后,可以看到README.md文件:
現(xiàn)在望拖,遠(yuǎn)程庫(kù)已經(jīng)準(zhǔn)備好了渺尘,下一步是用命令git clone克隆一個(gè)本地庫(kù):
$ git clone git@github.com:michaelliao/gitskills.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (3/3), done.
第四章
4.1、創(chuàng)建與合并分支
在上文靠娱,已經(jīng)知道沧烈,每次提交,Git都把它們串成一條時(shí)間線像云,這條時(shí)間線就是一個(gè)分支锌雀。截止到目前,只有一條時(shí)間線迅诬,在Git里腋逆,這個(gè)分支叫主分支,即master
分支侈贷。HEAD
嚴(yán)格來(lái)說(shuō)不是指向提交惩歉,而是指向master
,master
才是指向提交的俏蛮,所以撑蚌,HEAD
指向的就是當(dāng)前分支。
一開(kāi)始的時(shí)候搏屑,master
分支是一條線争涌,Git用master
指向最新的提交,再用HEAD
指向master
辣恋,就能確定當(dāng)前分支亮垫,以及當(dāng)前分支的提交點(diǎn):
每次提交,master分支都會(huì)向前移動(dòng)一步伟骨,這樣饮潦,隨著你不斷提交,master分支的線也越來(lái)越長(zhǎng)携狭。
當(dāng)我們用
git checkout -b xxx
(創(chuàng)建并切換)創(chuàng)建分支继蜡,Git新建了一個(gè)指針叫dev,指向master相同的提交暑中,再把HEAD指向dev壹瘟,就表示當(dāng)前分支在dev上:
你看,Git創(chuàng)建一個(gè)分支很快鳄逾,因?yàn)槌嗽黾右粋€(gè)dev指針,改改HEAD的指向灵莲,工作區(qū)的文件都沒(méi)有任何變化雕凹!
不過(guò),從現(xiàn)在開(kāi)始,對(duì)工作區(qū)的修改和提交就是針對(duì)dev分支了枚抵,比如新提交一次后线欲,dev指針往前移動(dòng)一步,而master指針不變:
假如我們?cè)赿ev上的工作完成了汽摹,就可以把dev合并到master上李丰。Git怎么合并呢?最簡(jiǎn)單的方法逼泣,就是直接把master指向dev的當(dāng)前提交趴泌,就完成了合并:
所以Git合并分支也很快!就改改指針拉庶,工作區(qū)內(nèi)容也不變嗜憔!
合并完分支后,甚至可以刪除dev分支氏仗。刪除dev分支就是把dev指針給刪掉吉捶,刪掉后,我們就剩下了一條master分支:
下面用代碼說(shuō)明:
首先皆尔,我們創(chuàng)建dev分支呐舔,然后切換到dev分支:
$ git checkout -b dev
Switched to a new branch 'dev'
git checkout
命令加上-b參數(shù)表示創(chuàng)建并切換,相當(dāng)于以下兩條命令
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
然后慷蠕,用git branch
命令查看當(dāng)前分支:
$ git branch
* dev
master
可以在Dev分支上進(jìn)行操作珊拼,操作完成以后,我們就可以切換回master分支:
$ git checkout master
Switched to branch 'master'
切換回master分支后砌们,master分支上的東西并沒(méi)有同步之前提交的:
如果想讓master分支上也有同樣的內(nèi)容:
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge
命令用于合并指定分支到當(dāng)前分支
合并完成后杆麸,就可以放心地刪除dev分支了:
$ git branch -d dev
Deleted branch dev (was b17d20e).
總結(jié):
Git鼓勵(lì)大量使用分支:
查看分支: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>
4.2、解決沖突
我們先創(chuàng)建一個(gè)分支并切換到當(dāng)前分支feature1
$ git checkout -b feature1
Switched to a new branch 'feature1'
假設(shè)工作區(qū)有個(gè)文件為 readme.txt
,我們修改這個(gè)文件里面的內(nèi)容:
Creating a new branch is quick AND simple.
然后提交:
$ git add readme.txt
$ git commit -m "AND simple"
[feature1 14096d0] AND simple
1 file changed, 1 insertion(+), 1 deletion(-)
然后
然后
然后
然后我們切換到 master 分支:
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Git還會(huì)自動(dòng)提示我們當(dāng)前master分支比遠(yuǎn)程的master分支要超前1個(gè)提交浪感。
正常情況下昔头,現(xiàn)在我們就可以合并了!S笆蕖=腋!但是如果沒(méi)有合并會(huì)出現(xiàn)什么情況呢峻堰?讹开?
比如,在工作區(qū)做一次修改 再次提交到當(dāng)前分支:
在master分支上把readme.txt文件的最后一行改為:
Creating a new branch is quick & simple.
提交:
$ git add readme.txt
$ git commit -m "& simple"
[master 5dc6824] & simple
1 file changed, 1 insertion(+), 1 deletion(-)
現(xiàn)在捐名,master
分支和feature1
分支各自都分別有新的提交旦万,變成了這樣:
這種情況下,Git無(wú)法執(zhí)行“快速合并”镶蹋,只能試圖把各自的修改合并起來(lái)成艘,但這種合并就可能會(huì)有沖突赏半,我們?cè)囋嚳矗?/p>
$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
果然沖突了!Git告訴我們淆两,readme.txt文件存在沖突断箫,必須手動(dòng)解決沖突后再提交。git status也可以告訴我們沖突的文件:
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
我們可以直接查看readme.txt的內(nèi)容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1
Git用<<<<<<<
秋冰,=======
仲义,>>>>>>>
標(biāo)記出不同分支的內(nèi)容,我們修改如下后保存:
Creating a new branch is quick and simple.
再提交:
$ git add readme.txt
$ git commit -m "conflict fixed"
[master cf810e4] conflict fixed
現(xiàn)在剑勾,master分支和feature1分支變成了下圖所示:
用帶參數(shù)的git log也可以看到分支的合并情況:
$ git log --graph --pretty=oneline --abbrev-commit
* cf810e4 (HEAD -> master) conflict fixed
|\
| * 14096d0 (feature1) AND simple
* | 5dc6824 & simple
|/
* b17d20e branch test
* d46f35e (origin/master) remove test.txt
* b84166e add test.txt
* 519219b git tracks changes
* e43a48b understand how stage works
* 1094adb append GPL
* e475afc add distributed
* eaadf4e wrote a readme file
最后埃撵,刪除feature1
分支:
$ git branch -d feature1
Deleted branch feature1 (was 14096d0).
小結(jié)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
當(dāng)Git無(wú)法自動(dòng)合并分支時(shí),就必須首先解決沖突甥材。解決沖突后盯另,再提交,合并完成洲赵。
解決沖突就是把Git合并失敗的文件手動(dòng)編輯為我們希望的內(nèi)容鸳惯,再提交。
用git log --graph命令可以看到分支合并圖叠萍。
4.3芝发、分支策略
在實(shí)際開(kāi)發(fā)中,我們應(yīng)該按照幾個(gè)基本原則進(jìn)行分支管理:
首先苛谷,master分支應(yīng)該是非常穩(wěn)定的辅鲸,也就是僅用來(lái)發(fā)布新版本,平時(shí)不能在上面干活腹殿;
那在哪干活呢独悴?干活都在dev分支上,也就是說(shuō)锣尉,dev分支是不穩(wěn)定的刻炒,到某個(gè)時(shí)候,比如1.0版本發(fā)布時(shí)自沧,再把dev分支合并到master上坟奥,在master分支發(fā)布1.0版本;
你和你的小伙伴們每個(gè)人都在dev分支上干活拇厢,每個(gè)人都有自己的分支爱谁,時(shí)不時(shí)地往dev分支上合并就可以了。
所以孝偎,團(tuán)隊(duì)合作的分支看起來(lái)就像這樣:
4.4访敌、bug分支
假如我們現(xiàn)在在Dev分支上進(jìn)行開(kāi)發(fā),突然要去 master 分支上解決一個(gè)bug衣盾。怎么辦捐顷?
- 先把當(dāng)前的工作區(qū)給保存 使用
git stash
- 切換到master分支上荡陷,創(chuàng)建并切換一個(gè)新的分支雨效,在新分支上手動(dòng)修改
- 修改完成以后迅涮,切換到master分支,合并新的修改徽龟,刪除新建的bug分支
- 重新切換到Dev分支叮姑,使用 git stash pop 恢復(fù)剛才的工作區(qū)內(nèi)容
注意:
如果多次使用 git stash
之后,再pop之前可以先進(jìn)行查看保存的列表 git stash list
据悔,如果想回到指定的地方可以使用 $ git stash apply stash@{n}
4.5传透、Feature分支
軟件開(kāi)發(fā)中,總有無(wú)窮無(wú)盡的新的功能要不斷添加進(jìn)來(lái)极颓。
添加一個(gè)新功能時(shí)朱盐,你肯定不希望因?yàn)橐恍?shí)驗(yàn)性質(zhì)的代碼,把主分支搞亂了菠隆,所以兵琳,每添加一個(gè)新功能,最好新建一個(gè)feature分支骇径,在上面開(kāi)發(fā)躯肌,完成后,合并破衔,最后清女,刪除該feature分支。
如果在合并之前想放棄修改晰筛,可以使用 git branch -D xxx
4.6嫡丙、多人協(xié)作
當(dāng)你從遠(yuǎn)程倉(cāng)庫(kù)克隆時(shí),實(shí)際上Git自動(dòng)把本地的master
分支和遠(yuǎn)程的master
分支對(duì)應(yīng)起來(lái)了读第,并且曙博,遠(yuǎn)程倉(cāng)庫(kù)的默認(rèn)名稱是origin
。
要查看遠(yuǎn)程庫(kù)的信息卦方,用git remote
:
$ git remote
origin
推送分支
推送分支羊瘩,就是把該分支上的所有本地提交推送到遠(yuǎn)程庫(kù)。推送時(shí)盼砍,要指定本地分支尘吗,這樣,Git就會(huì)把該分支推送到遠(yuǎn)程庫(kù)對(duì)應(yīng)的遠(yuǎn)程分支上:
$ git push origin master
如果要推送其他分支浇坐,比如dev
睬捶,就改成:
$ git push origin dev
但是,并不是一定要把本地分支往遠(yuǎn)程推送近刘,那么擒贸,哪些分支需要推送臀晃,哪些不需要呢?
master分支是主分支介劫,因此要時(shí)刻與遠(yuǎn)程同步徽惋;
dev分支是開(kāi)發(fā)分支,團(tuán)隊(duì)所有成員都需要在上面工作座韵,所以也需要與遠(yuǎn)程同步险绘;
bug分支只用于在本地修復(fù)bug,就沒(méi)必要推到遠(yuǎn)程了誉碴,除非老板要看看你每周到底修復(fù)了幾個(gè)bug宦棺;
feature分支是否推到遠(yuǎn)程,取決于你是否和你的小伙伴合作在上面開(kāi)發(fā)黔帕。
抓取分支
多人協(xié)作時(shí)代咸,大家都會(huì)往master和dev分支上推送各自的修改。
現(xiàn)在成黄,模擬一個(gè)你的小伙伴呐芥,可以在另一臺(tái)電腦(注意要把SSH Key添加到GitHub)或者同一臺(tái)電腦的另一個(gè)目錄下克隆:
$ git clone git@github.com:michaelliao/learngit.git
Cloning into 'learngit'...
remote: Counting objects: 40, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 40 (delta 14), reused 40 (delta 14), pack-reused 0
Receiving objects: 100% (40/40), done.
Resolving deltas: 100% (14/14), done.
當(dāng)你的小伙伴從遠(yuǎn)程庫(kù)clone時(shí)慨默,默認(rèn)情況下贩耐,你的小伙伴只能看到本地的master分支。不信可以用git branch
命令看看:
$ git branch
* master
現(xiàn)在厦取,你的小伙伴要在dev分支上開(kāi)發(fā)潮太,就必須創(chuàng)建遠(yuǎn)程origin
的dev
分支到本地,于是他用這個(gè)命令創(chuàng)建本地dev分支:
git checkout -b dev origin/dev
現(xiàn)在虾攻,他就可以在dev上繼續(xù)修改铡买,然后,時(shí)不時(shí)地把dev分支push到遠(yuǎn)程:
$ git add env.txt
$ git commit -m "add env"
[dev 7a5e5dd] add env
1 file changed, 1 insertion(+)
create mode 100644 env.txt
$ git push origin dev
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 308 bytes | 308.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
f52c633..7a5e5dd dev -> dev
你的小伙伴已經(jīng)向origin/dev分支推送了他的提交霎箍,而碰巧你也對(duì)同樣的文件作了修改奇钞,這樣就會(huì)報(bào)錯(cuò)!可以先用git pull
把最新的提交從origin/dev
抓下來(lái)漂坏,然后景埃,在本地合并,解決沖突
如果git pull
失敗顶别,那是因?yàn)闆](méi)有指定本地dev
和遠(yuǎn)程origin/dev
之間的關(guān)聯(lián):git branch --set-upstream-to=origin/<branch> dev
小結(jié)
查看遠(yuǎn)程庫(kù)信息谷徙,使用git remote -v;
本地新建的分支如果不推送到遠(yuǎn)程驯绎,對(duì)其他人就是不可見(jiàn)的完慧;
從本地推送分支,使用git push origin branch-name剩失,如果推送失敗屈尼,先用git pull抓取遠(yuǎn)程的新提交册着;
在本地創(chuàng)建和遠(yuǎn)程分支對(duì)應(yīng)的分支,使用git checkout -b branch-name origin/branch-name脾歧,本地和遠(yuǎn)程分支的名稱最好一致甲捏;
建立本地分支和遠(yuǎn)程分支的關(guān)聯(lián),使用git branch --set-upstream branch-name origin/branch-name涨椒;
從遠(yuǎn)程抓取分支摊鸡,使用git pull,如果有沖突蚕冬,要先處理沖突。
第五章
5.1是辕、創(chuàng)建標(biāo)簽
在Git中打標(biāo)簽非常簡(jiǎn)單囤热,首先,切換到需要打標(biāo)簽的分支上:
$ git branch
* dev
master
$ git checkout master
Switched to branch 'master'
然后获三,敲命令git tag <name>
就可以打一個(gè)新標(biāo)簽:
$ git tag v1.0
可以用命令git tag
查看所有標(biāo)簽:
$ git tag
v1.0
默認(rèn)標(biāo)簽是打在最新提交的commit
上的旁蔼。有時(shí)候,如果忘了打標(biāo)簽疙教,比如棺聊,現(xiàn)在已經(jīng)是周五了,但應(yīng)該在周一打的標(biāo)簽沒(méi)有打贞谓,怎么辦限佩?
方法是找到歷史提交的commit id,然后打上就可以了:
$ git log --pretty=oneline --abbrev-commit
12a631b (HEAD -> master, tag: v1.0, origin/master) merged bug fix 101
4c805e2 fix bug 101
e1e9c68 merge with no-ff
f52c633 add merge
cf810e4 conflict fixed
5dc6824 & simple
14096d0 AND simple
b17d20e branch test
d46f35e remove test.txt
b84166e add test.txt
519219b git tracks changes
e43a48b understand how stage works
1094adb append GPL
e475afc add distributed
eaadf4e wrote a readme file
比方說(shuō)要對(duì)add merge這次提交打標(biāo)簽裸弦,它對(duì)應(yīng)的commit id
是f52c633祟同,敲入命令:
$ git tag v0.9 f52c633
再用命令git tag查看標(biāo)簽:
$ git tag
v0.9
v1.0
注意,標(biāo)簽不是按時(shí)間順序列出理疙,而是按字母排序的晕城。可以用git show <tagname>
查看標(biāo)簽信息:
$ git show v0.9
commit f52c63349bc3c1593499807e5c8e972b82c8f286 (tag: v0.9)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:56:54 2018 +0800
add merge
diff --git a/readme.txt b/readme.txt
...
小結(jié)
命令git tag <tagname>用于新建一個(gè)標(biāo)簽窖贤,默認(rèn)為HEAD砖顷,也可以指定一個(gè)commit id;
命令git tag -a <tagname> -m "blablabla..."可以指定標(biāo)簽信息赃梧;
命令git tag可以查看所有標(biāo)簽滤蝠。
5.2、操作標(biāo)簽
如果標(biāo)簽打錯(cuò)了槽奕,也可以刪除:
$ git tag -d v0.1
Deleted tag 'v0.1' (was f15b0dd)
因?yàn)閯?chuàng)建的標(biāo)簽都只存儲(chǔ)在本地几睛,不會(huì)自動(dòng)推送到遠(yuǎn)程。所以粤攒,打錯(cuò)的標(biāo)簽可以在本地安全刪除所森。
如果要推送某個(gè)標(biāo)簽到遠(yuǎn)程囱持,使用命令git push origin <tagname>:
$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
* [new tag] v1.0 -> v1.0
或者,一次性推送全部尚未推送到遠(yuǎn)程的本地標(biāo)簽:
$ git push origin --tags
Total 0 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
* [new tag] v0.9 -> v0.9
如果標(biāo)簽已經(jīng)推送到遠(yuǎn)程焕济,要?jiǎng)h除遠(yuǎn)程標(biāo)簽就麻煩一點(diǎn)纷妆,先從本地刪除:
$ git tag -d v0.9
Deleted tag 'v0.9' (was f52c633)
然后,從遠(yuǎn)程刪除晴弃。刪除命令也是push掩幢,但是格式如下:
$ git push origin :refs/tags/v0.9
To github.com:michaelliao/learngit.git
- [deleted] v0.9
小結(jié)
命令
git push origin <tagname>
可以推送一個(gè)本地標(biāo)簽;命令
git push origin --tags
可以推送全部未推送過(guò)的本地標(biāo)簽上鞠;命令
git tag -d <tagname>
可以刪除一個(gè)本地標(biāo)簽际邻;命令
git push origin :refs/tags/<tagname>
可以刪除一個(gè)遠(yuǎn)程標(biāo)簽。