溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何分析git的知識(shí)

發(fā)布時(shí)間:2022-01-15 10:03:08 來(lái)源:億速云 閱讀:150 作者:柒染 欄目:軟件技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)如何分析git的知識(shí),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

分支管理策略

git 分支強(qiáng)大的同時(shí)也非常靈活,如果沒(méi)有一個(gè)好的分支管理策略,團(tuán)隊(duì)人員隨意合并推送,就會(huì)造成分支混亂,各種覆蓋,沖突,丟失等問(wèn)題。

目前最流行的分支管理策略,也稱工作流(Workflow),主要包含三種:

  • Git Flow

  • GitHub Flow

  • GitLab Flow

我司前端團(tuán)隊(duì)結(jié)合實(shí)際情況,制定出自己的一套分支管理策略。

我們將分支分為 4 個(gè)大類:

  • dev-*

  • develop

  • staging

  • release

dev-* 是一組開(kāi)發(fā)分支的統(tǒng)稱,包括個(gè)人分支,模塊分支,修復(fù)分支等,團(tuán)隊(duì)開(kāi)發(fā)人員在這組分支上進(jìn)行開(kāi)發(fā)。

開(kāi)發(fā)前,先通過(guò) merge 合并 develop 分支的最新代碼;開(kāi)發(fā)完成后,必須通過(guò) cherry-pick 合并回 develop 分支。

develop 是一個(gè)單獨(dú)分支,對(duì)應(yīng)開(kāi)發(fā)環(huán)境,保留最新的完整的開(kāi)發(fā)代碼。它只接受 cherry-pick 的合并,不允許使用 merge。

staging 分支對(duì)應(yīng)測(cè)試環(huán)境。當(dāng) develop 分支有更新并且準(zhǔn)備發(fā)布測(cè)試時(shí),staging 要通過(guò) rebase 合并 develop 分支,然后將最新代碼發(fā)布到測(cè)試服務(wù)器,供測(cè)試人員測(cè)試。

測(cè)試發(fā)現(xiàn)問(wèn)題后,再走 dev-* -> develop -> staging 的流程,直到測(cè)試通過(guò)。

release 則表示生產(chǎn)環(huán)境。release 分支的最新提交永遠(yuǎn)與線上生產(chǎn)環(huán)境代碼保持同步,也就是說(shuō),release 分支是隨時(shí)可發(fā)布的。

當(dāng) staging 測(cè)試通過(guò)后,release 分支通過(guò) rebase 合并 staging 分支,然后將最新代碼發(fā)布到生產(chǎn)服務(wù)器。

總結(jié)下合并規(guī)則:

  • develop -> (merge) -> dev-*

  • dev-* -> (cherry-pick) -> develop

  • develop -> (rebase) -> staging

  • staging -> (rebase) -> release

為什么合并到 develop 必須用 cherry-pick?

使用 merge 合并,如果有沖突,會(huì)產(chǎn)生分叉;dev-* 分支多而雜,直接 merge 到 develop 會(huì)產(chǎn)生錯(cuò)綜復(fù)雜的分叉,難以理清提交進(jìn)度。

而 cherry-pick 只將需要的 commit 合并到 develop 分支上,且不會(huì)產(chǎn)生分叉,使 git 提交圖譜(git graph)永遠(yuǎn)保持一條直線。

再有,模塊開(kāi)發(fā)分支完成后,需要將多個(gè) commit 合為一個(gè) commit,再合并到 develop 分支,避免了多余的 commit,這也是不用 merge 的原因之一。

為什么合并到 staging/release 必須用 rebase?

rebase 譯為變基,合并同樣不會(huì)產(chǎn)生分叉。當(dāng) develop 更新了許多功能,要合并到 staging 測(cè)試,不可能用 cherry-pick 一個(gè)一個(gè)把 commit 合并過(guò)去。因此要通過(guò) rebase 一次性合并過(guò)去,并且保證了 staging 與 develop 完全同步。

release 也一樣,測(cè)試通過(guò)后,用 rebase 一次性將 staging 合并過(guò)去,同樣保證了 staging 與 release 完全同步。

commit 規(guī)范與提交驗(yàn)證

commit 規(guī)范是指 git commit 時(shí)填寫(xiě)的描述信息,要符合統(tǒng)一規(guī)范。

試想,如果團(tuán)隊(duì)成員的 commit 是隨意填寫(xiě)的,在協(xié)作開(kāi)發(fā)和 review 代碼時(shí),其他人根本不知道這個(gè) commit 是完成了什么功能,或是修復(fù)了什么 Bug,很難把控進(jìn)度。

為了直觀的看出 commit 的更新內(nèi)容,開(kāi)發(fā)者社區(qū)誕生了一種規(guī)范,將 commit 按照功能劃分,加一些固定前綴,比如 fix:,feat:,用來(lái)標(biāo)記這個(gè) commit 主要做了什么事情。

目前主流的前綴包括以下部分:

  • build:表示構(gòu)建,發(fā)布版本可用這個(gè)

  • ci:更新 CI/CD 等自動(dòng)化配置

  • chore:雜項(xiàng),其他更改

  • docs:更新文檔

  • feat:常用,表示新增功能

  • fix:常用:表示修復(fù) bug

  • perf:性能優(yōu)化

  • refactor:重構(gòu)

  • revert:代碼回滾

  • style:樣式更改

  • test:?jiǎn)卧獪y(cè)試更改

這些前綴每次提交都要寫(xiě),剛開(kāi)始很多人還是記不住的。這里推薦一個(gè)非常好用的工具,可以自動(dòng)生成前綴。地址在這里

首先全局安裝:

npm install -g commitizen cz-conventional-changelog

創(chuàng)建 ~/.czrc 文件,寫(xiě)入如下內(nèi)容:

{ "path": "cz-conventional-changelog" }

現(xiàn)在可以用 git cz 命令來(lái)代替 git commit 命令,效果如下:

如何分析git的知識(shí)

然后上下箭選擇前綴,根據(jù)提示即可方便的創(chuàng)建符合規(guī)范的提交。

有了規(guī)范之后,光靠人的自覺(jué)遵守是不行的,還要在流程上對(duì)提交信息進(jìn)行校驗(yàn)。

這個(gè)時(shí)候,我們要用到一個(gè)新東西 —— git hook,也就是 git 鉤子。

git hook 的作用是在 git 動(dòng)作發(fā)生前后觸發(fā)自定義腳本。這些動(dòng)作包括提交,合并,推送等,我們可以利用這些鉤子在 git 流程的各個(gè)環(huán)節(jié)實(shí)現(xiàn)自己的業(yè)務(wù)邏輯。

git hook 分為客戶端 hook 和服務(wù)端 hook。

客戶端 hook 主要有四個(gè):

  • pre-commit:提交信息前運(yùn)行,可檢查暫存區(qū)的代碼

  • prepare-commit-msg:不常用

  • commit-msg:非常重要,檢查提交信息就用這個(gè)鉤子

  • post-commit:提交完成后運(yùn)行

服務(wù)端 hook 包括:

  • pre-receive:非常重要,推送前的各種檢查都在這

  • post-receive:不常用

  • update:不常用

大多數(shù)團(tuán)隊(duì)是在客戶端做校驗(yàn),所以我們用 commit-msg 鉤子在客戶端對(duì) commit 信息做校驗(yàn)。

幸運(yùn)的是,不需要我們手動(dòng)去寫(xiě)校驗(yàn)邏輯,社區(qū)有成熟的方案:husky + commitlint

husky 是創(chuàng)建 git 客戶端鉤子的神器,commitlint 是校驗(yàn) commit 信息是否符合上述規(guī)范。兩者配合,可以阻止創(chuàng)建不符合 commit 規(guī)范的提交,從源頭保證提交的規(guī)范。

husky + commitlint 的具體使用方法請(qǐng)看這里

誤操作的撤回方案

開(kāi)發(fā)中頻繁使用 git 拉取推送代碼,難免會(huì)有誤操作。這個(gè)時(shí)候不要慌,git 支持絕大多數(shù)場(chǎng)景的撤回方案,我們來(lái)總結(jié)一下。

撤回主要是兩個(gè)命令:reset 和 revert

git reset

reset 命令的原理是根據(jù) commitId 來(lái)恢復(fù)版本。因?yàn)槊看翁峤欢紩?huì)生成一個(gè) commitId,所以說(shuō) reset 可以幫你恢復(fù)到歷史的任何一個(gè)版本。

這里的版本和提交是一個(gè)意思,一個(gè) commitId 就是一個(gè)版本

reset 命令格式如下:

$ git reset [option] [commitId]

比如,要撤回到某一次提交,命令是這樣:

$ git reset --hard cc7b5be

上面的命令,commitId 是如何獲取的?很簡(jiǎn)單,用 git log 命令查看提交記錄,可以看到 commitId 值,這個(gè)值很長(zhǎng),我們?nèi)∏?7 位即可。

這里的 option 用的是 --hard,其實(shí)共有 3 個(gè)值,具體含義如下:

  • --hard:撤銷 commit,撤銷 add,刪除工作區(qū)改動(dòng)代碼

  • --mixed:默認(rèn)參數(shù)。撤銷 commit,撤銷 add,還原工作區(qū)改動(dòng)代碼

  • --soft:撤銷 commit,不撤銷 add,還原工作區(qū)改動(dòng)代碼

這里要格外注意 --hard,使用這個(gè)參數(shù)恢復(fù)會(huì)刪除工作區(qū)代碼。也就是說(shuō),如果你的項(xiàng)目中有未提交的代碼,使用該參數(shù)會(huì)直接刪除掉,不可恢復(fù),慎重啊!

除了使用 commitId 恢復(fù),git reset 還提供了恢復(fù)到上一次提交的快捷方式:

$ git reset --soft HEAD^

HEAD^ 表示上一個(gè)提交,可多次使用。

其實(shí)平日開(kāi)發(fā)中最多的誤操作是這樣:剛剛提交完,突然發(fā)現(xiàn)了問(wèn)題,比如提交信息沒(méi)寫(xiě)好,或者代碼更改有遺漏,這時(shí)需要撤回到上次提交,修改代碼,然后重新提交。

這個(gè)流程大致是這樣的:

# 1. 回退到上次提交
$ git reset HEAD^
# 2. 修改代碼...
...
# 3. 加入暫存
$ git add .
# 4. 重新提交
$ git commit -m 'fix: ***'

針對(duì)這個(gè)流程,git 還提供了一個(gè)更便捷的方法:
$ git commit --amend

這個(gè)命令會(huì)直接修改當(dāng)前的提交信息。如果代碼有更改,先執(zhí)行 git add,然后再執(zhí)行這個(gè)命令,比上述的流程更快捷更方便。

reset 還有一個(gè)非常重要的特性,就是真正的后退一個(gè)版本。

什么意思呢?比如說(shuō)當(dāng)前提交,你已經(jīng)推送到了遠(yuǎn)程倉(cāng)庫(kù);現(xiàn)在你用 reset 撤回了一次提交,此時(shí)本地 git 倉(cāng)庫(kù)要落后于遠(yuǎn)程倉(cāng)庫(kù)一個(gè)版本。此時(shí)你再 push,遠(yuǎn)程倉(cāng)庫(kù)會(huì)拒絕,要求你先 pull。

如果你需要遠(yuǎn)程倉(cāng)庫(kù)也后退版本,就需要 -f 參數(shù),強(qiáng)制推送,這時(shí)本地代碼會(huì)覆蓋遠(yuǎn)程代碼。

注意,-f 參數(shù)非常危險(xiǎn)!如果你對(duì) git 原理和命令行不是非常熟悉,切記不要用這個(gè)參數(shù)。

那撤回上一個(gè)版本的代碼,怎么同步到遠(yuǎn)程更安全呢?

方案就是下面要說(shuō)的第二個(gè)命令:git revert

git revert

revert 與 reset 的作用一樣,都是恢復(fù)版本,但是它們兩的實(shí)現(xiàn)方式不同。

簡(jiǎn)單來(lái)說(shuō),reset 直接恢復(fù)到上一個(gè)提交,工作區(qū)代碼自然也是上一個(gè)提交的代碼;而 revert 是新增一個(gè)提交,但是這個(gè)提交是使用上一個(gè)提交的代碼。

因此,它們兩恢復(fù)后的代碼是一致的,區(qū)別是一個(gè)新增提交(revert),一個(gè)回退提交(reset)。

正因?yàn)?revert 永遠(yuǎn)是在新增提交,因此本地倉(cāng)庫(kù)版本永遠(yuǎn)不可能落后于遠(yuǎn)程倉(cāng)庫(kù),可以直接推送到遠(yuǎn)程倉(cāng)庫(kù),故而解決了 reset 后推送需要加 -f 參數(shù)的問(wèn)題,提高了安全性。

說(shuō)完了原理,我們?cè)倏匆幌率褂梅椒ǎ?/p>

$ git revert -n [commitId]

掌握了原理使用就很簡(jiǎn)單,只要一個(gè) commitId 就可以了。

Tag 與生產(chǎn)環(huán)境

git 支持對(duì)于歷史的某個(gè)提交,打一個(gè) tag 標(biāo)簽,常用于標(biāo)識(shí)重要的版本更新。

目前普遍的做法是,用 tag 來(lái)表示生產(chǎn)環(huán)境的版本。當(dāng)最新的提交通過(guò)測(cè)試,準(zhǔn)備發(fā)布之時(shí),我們就可以創(chuàng)建一個(gè) tag,表示要發(fā)布的生產(chǎn)環(huán)境版本。

比如我要發(fā)一個(gè) v1.2.4 的版本:

$ git tag -a v1.2.4 -m "my version 1.2.4"

然后可以查看:

$ git show v1.2.4
> tag v1.2.4
Tagger: ruims <2218466341@qq.com>
Date:   Sun Sep 26 10:24:30 2021 +0800
my version 1.2.4

最后用 git push 將 tag 推到遠(yuǎn)程:

$ git push origin v1.2.4

這里注意:tag 和在哪個(gè)分支創(chuàng)建是沒(méi)有關(guān)系的,tag 只是提交的別名。因此 commit 的能力 tag 均可使用,比如上面說(shuō)的 git reset,git revert 命令。

當(dāng)生產(chǎn)環(huán)境出問(wèn)題,需要版本回退時(shí),可以這樣:

$ git revert [pre-tag]
# 若上一個(gè)版本是 v1.2.3,則:
$ git revert v1.2.3

在頻繁更新,commit 數(shù)量龐大的倉(cāng)庫(kù)里,用 tag 標(biāo)識(shí)版本顯然更清爽,可讀性更佳。

再換一個(gè)角度思考 tag 的用處。

上面分支管理策略的部分說(shuō)過(guò),release 分支與生產(chǎn)環(huán)境代碼同步。在 CI/CD(下面會(huì)講到)持續(xù)部署的流程中,我們是監(jiān)聽(tīng) release 分支的推送然后觸發(fā)自動(dòng)構(gòu)建。

那是不是也可以監(jiān)聽(tīng) tag 推送再觸發(fā)自動(dòng)構(gòu)建,這樣版本更新的直觀性是不是更好?

諸多用處,還待大家思考。

永久杜絕 443 Timeout

我們團(tuán)隊(duì)內(nèi)部的代碼倉(cāng)庫(kù)是 GitHub,眾所周知的原因,GitHub 拉取和推送的速度非常慢,甚至直接報(bào)錯(cuò):443 Timeout。

我們開(kāi)始的方案是,全員開(kāi)啟 VPN。雖然大多時(shí)候速度不錯(cuò),但是確實(shí)有偶爾的一個(gè)小時(shí),甚至一天,代碼死活推不上去,嚴(yán)重影響開(kāi)發(fā)進(jìn)度。

后來(lái)突然想到,速度慢超時(shí)是因?yàn)楸粔?,比?GitHub 首頁(yè)打不開(kāi)。再究其根源,被墻的是訪問(wèn)網(wǎng)站時(shí)的 http 或 https 協(xié)議,那么其他協(xié)議是不是就不會(huì)有墻的情況?

想到就做。我們發(fā)現(xiàn) GitHub 除了默認(rèn)的 https 協(xié)議,還支持 ssh 協(xié)議。于是準(zhǔn)備嘗試一下使用 ssh 協(xié)議克隆代碼。

用 ssh 協(xié)議比較麻煩的一點(diǎn),是要配置免密登錄,否則每次 pull/push 時(shí)都要輸入賬號(hào)密碼。

總之,生成公鑰后,打開(kāi) GitHub 首頁(yè),點(diǎn) Account -> Settings -> SSH and GPG keys -> Add SSH key,然后將公鑰粘貼進(jìn)去即可。

現(xiàn)在,我們用 ssh 協(xié)議克隆代碼,例子如下:

$ git clone git@github.com:[organi-name]/[project-name]

發(fā)現(xiàn)瞬間克隆下來(lái)了!再測(cè)幾次 pull/push,速度飛起!

不管你用哪個(gè)代碼管理平臺(tái),如果遇到 443 Timeout 問(wèn)題,請(qǐng)?jiān)囋?ssh 協(xié)議!

hook 實(shí)現(xiàn)部署?

利用 git hook 實(shí)現(xiàn)部署,應(yīng)該是 hook 的高級(jí)應(yīng)用了。

現(xiàn)在有很多工具,比如 GitHub,GitLab,都提供了持續(xù)集成功能,也就是監(jiān)聽(tīng)某一分支推送,然后觸發(fā)自動(dòng)構(gòu)建,并自動(dòng)部署。

其實(shí),不管這些工具有多少花樣,核心的功能(監(jiān)聽(tīng)和構(gòu)建)還是由 git 提供。只不過(guò)在核心功能上做了與自家平臺(tái)更好的融合。

我們今天就拋開(kāi)這些工具,追本溯源,使用純 git 實(shí)現(xiàn)一個(gè) react 項(xiàng)目的自動(dòng)部署。掌握了這套核心邏輯,其他任何平臺(tái)的持續(xù)部署也就沒(méi)那么神秘了。

終極應(yīng)用: CI/CD

上面的一些地方也提到了持續(xù)集成,持續(xù)部署這些字眼,現(xiàn)在,千呼萬(wàn)喚始出來(lái),主角正式登場(chǎng)了!

可以這么說(shuō),上面寫(xiě)到的所有規(guī)范規(guī)則,都是為了更好的設(shè)計(jì)和實(shí)現(xiàn)這個(gè)主角 ——— CI/CD。

首先了解一下,什么是 CI/CD ?

核心概念,CI(Continuous Integration)譯為持續(xù)集成,CD 包括兩部分,持續(xù)交付(Continuous Delivery)和持續(xù)部署(Continuous Deployment)

從全局看,CI/CD 是一種通過(guò)自動(dòng)化流程來(lái)頻繁向客戶交付應(yīng)用的方法。這個(gè)流程貫穿了應(yīng)用的集成,測(cè)試,交付和部署的整個(gè)生命周期,統(tǒng)稱為 “CI/CD 管道”。

雖然都是像流水線一樣自動(dòng)化的管道,但是 CI 和 CD 各有分工。

持續(xù)集成是頻繁地將代碼集成到主干分支。當(dāng)新代碼提交,會(huì)自動(dòng)執(zhí)行構(gòu)建、測(cè)試,測(cè)試通過(guò)則自動(dòng)合并到主干分支,實(shí)現(xiàn)了產(chǎn)品快速迭代的同時(shí)保持高質(zhì)量。

持續(xù)交付是頻繁地將軟件的新版本,交付給質(zhì)量團(tuán)隊(duì)或者用戶,以供評(píng)審。評(píng)審?fù)ㄟ^(guò)則可以發(fā)布生產(chǎn)環(huán)境。持續(xù)交付要求代碼(某個(gè)分支的最新提交)是隨時(shí)可發(fā)布的狀態(tài)。

持續(xù)部署是代碼通過(guò)評(píng)審后,自動(dòng)部署到生產(chǎn)環(huán)境。持續(xù)部署要求代碼(某個(gè)分支的最新提交)是隨時(shí)可部署的。

持續(xù)部署與持續(xù)交付的唯一區(qū)別,就是部署到生產(chǎn)環(huán)境這一步,是否是自動(dòng)化。

部署自動(dòng)化,看似是小小的一步,但是在實(shí)踐過(guò)程中你會(huì)發(fā)現(xiàn),這反而是 CI/CD 流水線中最難落實(shí)的一環(huán)。

為什么?首先,從持續(xù)集成到持續(xù)交付,這些個(gè)環(huán)節(jié)都是由開(kāi)發(fā)團(tuán)隊(duì)實(shí)施的。我們通過(guò)團(tuán)隊(duì)內(nèi)部協(xié)作,產(chǎn)出了新版本的待發(fā)布的應(yīng)用。

然而將應(yīng)用部署到服務(wù)器,這是運(yùn)維團(tuán)隊(duì)的工作。我們要實(shí)現(xiàn)部署,就要與運(yùn)維團(tuán)隊(duì)溝通,然而開(kāi)發(fā)同學(xué)不了解服務(wù)器,運(yùn)維同學(xué)不了解代碼,溝通起來(lái)困難重重。

再有,運(yùn)維是手動(dòng)部署,我們要實(shí)現(xiàn)自動(dòng)部署,就要有服務(wù)器權(quán)限,與服務(wù)器交互。這也是個(gè)大問(wèn)題,因?yàn)檫\(yùn)維團(tuán)隊(duì)一定會(huì)顧慮安全問(wèn)題,因而推動(dòng)起來(lái)節(jié)節(jié)受阻。

目前社區(qū)成熟的 CI/CD 方案有很多,比如老牌的 jenkins,react 使用的 circleci,還有我認(rèn)為最好用的GitHub Action等,我們可以將這些方案接入到自己的系統(tǒng)當(dāng)中。

關(guān)于如何分析git的知識(shí)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

git
AI