在之前的內(nèi)容中蟆盹,有學(xué)習(xí)總結(jié)基本操作孩灯、修改撤回、分支 branch逾滥、貯藏 stash 峰档、標(biāo)簽 tag 以及部分遠(yuǎn)程操作。
涉及了 Git 的幾個(gè)工作區(qū)寨昙,工作目錄讥巡、暫存區(qū)、本地倉(cāng)庫(kù) 以及 遠(yuǎn)程倉(cāng)庫(kù)
他們之間的用 Git 操作的關(guān)系可總結(jié)如下圖:
從本期開(kāi)始進(jìn)入Git 的進(jìn)一步學(xué)習(xí)
本想先介紹下遠(yuǎn)程倉(cāng)庫(kù)的舔哪,有幾個(gè)好友說(shuō)很期待看 fetch欢顷,所以進(jìn)階首篇,學(xué)習(xí) fetch 命令捉蚤,也會(huì)區(qū)分下 git fetch
和 git pull
的使用抬驴。
fetch 概念
git fetch
和 git pull
是兩個(gè)比較相近的命令
git pull
我們已經(jīng)知道炼七,是從遠(yuǎn)程倉(cāng)庫(kù)拉取最新的內(nèi)容到本地,在 pull 的過(guò)程中如果沒(méi)有沖突布持,Git 會(huì)自動(dòng)將最新的內(nèi)容合并到本地倉(cāng)庫(kù)中豌拙,如果有沖突也是需要解決沖突。
fetch 可譯為獲取鳖链,官方給出如下說(shuō)明
git fetch
:Download objects and refs from another repository
git pull
:Fetch from and integrate with another repository or a local branch
fetch
直譯過(guò)來(lái)就是從另一個(gè)存儲(chǔ)庫(kù)下載對(duì)象和引用(refs)姆蘸,而 pull
可以看到除了 fetch
之外 還有 integrate(集成),所以大家習(xí)慣理解成 pull = fetch + merge芙委,用于本地存儲(chǔ)庫(kù)與遠(yuǎn)程存儲(chǔ)庫(kù)同步逞敷。
fetch & pull
我們來(lái)具體消化下上面的解釋
在我們進(jìn)行 commit
的時(shí)候,Git 會(huì)自動(dòng)生成一個(gè) commitid(即 SHA1 校驗(yàn)和)灌侣,此時(shí)如果進(jìn)行 push
操作推捐,遠(yuǎn)程倉(cāng)庫(kù)的對(duì)應(yīng)分支會(huì)同步這個(gè) commitid 的內(nèi)容,同時(shí)本地也會(huì)保存一份遠(yuǎn)程副本侧啼。
在入門(mén)(一)的時(shí)候牛柒,我們有提到過(guò),由 Git 管理的目錄會(huì)自動(dòng)生成一個(gè).git
文件夾痊乾,.git
文件夾包含著 Git 操作所需要的內(nèi)容皮壁。
在這個(gè)文件夾中就保存了 Git 本地倉(cāng)庫(kù) 以及 跟蹤的遠(yuǎn)程倉(cāng)庫(kù)的 commitid。
在上圖目錄 .git/refs
里面有幾個(gè)文件夾哪审,比如
- heads 存放著本地分支
- remotes 正在跟蹤的遠(yuǎn)程倉(cāng)庫(kù)
- tags 標(biāo)簽
通過(guò) git branch -a
查看分支蛾魄,和 .git
文件夾本地以及遠(yuǎn)程分支是一致的。
這些文件里面存放的就是對(duì)應(yīng)分支指向的 commitid (如下圖)
HEAD 文件里面存放的是當(dāng)前的指向(這里也和前面 git branch -a
查看的內(nèi)容是一樣的)
下面進(jìn)入正題
- 假設(shè)當(dāng)前操作的分支為 master 分支
使用 Git 進(jìn)行提交的時(shí)候湿滓,會(huì)使用 add
和 commit
命令將修改的文件提交 Git 版本庫(kù)滴须,同時(shí)在 heads/master(即,本地的當(dāng)前分支)生成對(duì)應(yīng)的 commitid(圖示中用 cid 表示)叽奥。然后扔水,通過(guò) push
同步到遠(yuǎn)程倉(cāng)庫(kù)對(duì)應(yīng)的分支中,同時(shí)本地也會(huì)保存一份遠(yuǎn)程的副本朝氓,即 origin/master
如果遠(yuǎn)程倉(cāng)庫(kù)被其他協(xié)同者更新了魔市,若要更新本地內(nèi)容,使用 push
膀篮,此時(shí)會(huì)從遠(yuǎn)程獲取的最新內(nèi)容并合并到本地
與 git pull
不同的是 fetch
是從遠(yuǎn)程倉(cāng)庫(kù) origin 的 master 分支獲取最新的內(nèi)容到 origin/master 分支上嘹狞,可以比較本地 master 和 origin/master 的差別之后,操作者視情況決定是否進(jìn)行合并
fetch 語(yǔ)法
git fetch
命令語(yǔ)法誓竿,詳見(jiàn)官方文檔 https://git-scm.com/docs/git-fetch
git fetch [<options>] [<repository> [<refspec>…?]]
git fetch [<options>] <group>
git fetch --multiple [<options>] [(<repository> | <group>)…?]
git fetch --all [<options>]
常用語(yǔ)法
git fetch
該命令將某個(gè)遠(yuǎn)程服務(wù)器的更新,全部取回本地谈截。默認(rèn)情況下筷屡,git fetch
取回所有分支的更新涧偷。
如果只想獲取特定分支的更新,可以指定分支名
git fetch <repository> <branch>
如
git fetch origin master
這里有個(gè)陌生的標(biāo)識(shí) FETCH_HEAD
FETCH_HEAD 是什么毙死?
FETCH_HEAD
指的是某個(gè) branch 在遠(yuǎn)程服務(wù)器上的最新?tīng)顟B(tài)
每一個(gè)執(zhí)行過(guò) fetch 操作的項(xiàng)目都會(huì)在 .git/FETCH_HEAD
文件中保存一個(gè) FETCH_HEAD
列表燎潮,其中每一行對(duì)應(yīng)著遠(yuǎn)程服務(wù)器的一個(gè)分支,而文件第一行就是當(dāng)前分支指向的 FETCH_HEAD
執(zhí)行 git fetch origin master
之后扼倘, FETCH_HEAD
就指向了 master 分支确封,
- 如果沒(méi)有指定遠(yuǎn)程分支,那么當(dāng)前操作的分支對(duì)應(yīng)的遠(yuǎn)程分支作為默認(rèn)的
FETCH_HEAD
(假設(shè)當(dāng)前在develop 分支 執(zhí)行命令git fetch
再菊,那么FETCH_HEAD
指向的就是遠(yuǎn)程端 develop 分支的最新提交) - 如果遠(yuǎn)程沒(méi)有對(duì)應(yīng)分支爪喘,也就沒(méi)有
FETCH_HEAD
- 如果指定了分支,就將這個(gè)分支作為
FETCH_HEAD
這里先插入介紹下可能用到的命令
便于實(shí)戰(zhàn)纠拔,提前做些數(shù)據(jù)
- 將之前創(chuàng)建的 feat_6 分支 push 到了遠(yuǎn)程服務(wù)器
- 同時(shí)通過(guò) GitHub 創(chuàng)建了一次描述為 “l(fā)earn fetch” 的提交(添加了一行 add line : learn fetch)秉剑,模擬多人協(xié)同時(shí),遠(yuǎn)程倉(cāng)庫(kù)有更新
執(zhí)行一次 git fetch origin feat_6
FETCH_HEAD 和 origin/feat_6 都更新了
- fetch 之后稠诲,如果想查看 fetch 日志侦鹏,可以使用
git log FETCH_HEAD
這里便于查看 log 的區(qū)別,將本地分支切換為 feat_6
最新的一次提交就是從遠(yuǎn)端獲取的臀叙,但是是本地沒(méi)有的日志
- 也可以使用 diff 查看具體的改動(dòng)
git diff FETCH_HEAD [HEAD]
查看的是HEAD
(當(dāng)前分支)相對(duì)于FETCH_HEAD
的區(qū)別- 如果使用
git diff HEAD FETCH_HEAD
查看的就是略水,FETCH_HEAD
相對(duì)于HEAD
的改變,注意和上邊做區(qū)分
講到這里劝萤,對(duì)于 pull = fetch + merge 的說(shuō)法便是指在同一分支
git pull
等同于
git fetch
git merge FETCH_HEAD
除了上面的內(nèi)容渊涝,在 fetch 獲取遠(yuǎn)程更新之后,可以在它的基礎(chǔ)上創(chuàng)建一個(gè)新的分支稳其,比如:
git checkout -b newBranch origin/master
當(dāng)然也可以 merge 或 rebase 在本地分支上合并遠(yuǎn)程分支
git merge origin/master
或 git rebase origin/master
(rebase 我們后面也會(huì)介紹到)
后記
fetch 這個(gè)功能在我平時(shí)的工作中也是疏于使用驶赏,但是不論使用 GitHub 還是 SourceTree 都可以看到 Fetch,F(xiàn)etch 之后會(huì)提示是否可 pull