在Git上如何強推代碼規(guī)范關(guān)注微信公眾號:大轉(zhuǎn)轉(zhuǎn)FE。 一個有趣的前端團(tuán)隊~ 關(guān)注她 6 人贊同了該文章 引言最近參加了“前端規(guī)范制定topic”小組,小組成員一起制定了html、css、js、es6、vue和react等規(guī)范,但規(guī)范制定好了怎么進(jìn)行推廣去強制執(zhí)行呢,已知我們的項目都是用git做管理的,所以馬上想到在git上做文章,本文講述的就是如何在git上推行代碼強校驗。 git知識點說到git,我們先來了解下平時項目中不是很關(guān)注的幾個git概念. git倉庫 git是分布式版本管理系統(tǒng),可以有多個代碼倉庫,所有參與項目的開發(fā)者都可以擁有自己的本地倉庫,每一個本地倉庫都是一個完整的版本庫,即使不聯(lián)網(wǎng),也可以任意的進(jìn)行開發(fā)、創(chuàng)建分支、commit和查看版本的歷史提交記錄等。 但每個人都在自己的本地倉庫開發(fā),怎么做到代碼共享和同步呢?在我們的項目中,通常都會建立一個大家都可以訪問的共享倉庫,這個共享倉庫放在一個專門的線上服務(wù)器上,我們也叫它遠(yuǎn)程倉庫。遠(yuǎn)程倉庫和本地倉庫的唯一差別就在于它是裸倉庫,就是不包含任何工作目錄,僅僅是由 “.git” 目錄組成的。它作為服務(wù)器倉庫供各開發(fā)者push、pull數(shù)據(jù),實現(xiàn)數(shù)據(jù)共享和同步,不保存文件,只保存歷史提交的版本信息等。 ![]() git存儲方式 說完git倉庫,我們來了解下git的存儲方式。git存儲數(shù)據(jù)更像是把數(shù)據(jù)看作是對小型文件系統(tǒng)的一組快照,每次提交更新或者是保存項目狀態(tài)時,它主要對現(xiàn)有的文件制作一個快照并保存這個快照的索引。這個“快照”就是git對象,而“快照的索引”就是對象名。所有用來表示項目歷史信息的文件,都是通過一個40字符的(40-digit)“對象名”來索引的。對象名看起來像這樣的:26e5847434caa7597c4088de8ecab9cd567957d1。 在git里,每一個“對象名”都是對“對象”內(nèi)容做 SHA-1哈希計算得來的, SHA-1是一種密碼學(xué)的hash算法,這樣在每個倉庫中不同內(nèi)容的對象就會有不同的對象名。git有四種類型的對象:"blob"、"tree"、 "commit" 和”tag”:
所以下面所描述的獲取文件信息基本上都是通過各種git命令操作hash對象名來獲取的,這也是為什么在這里介紹“git存儲方式”的原因,方便大家更深刻的了解git命令。 作用域 由git倉庫的定義可以看出,本地倉庫因為是本地的,任何能接觸得到倉庫的人都可以進(jìn)行修改、刪除等,所以本地倉庫不適合做代碼強校驗。那只能考慮遠(yuǎn)程倉庫了,可以當(dāng)用戶push推送的時候,校驗代碼,如果不符合規(guī)范,就拒絕這次提交,雖然你不能阻止開發(fā)者寫出糟糕的代碼,但可以防止這些代碼流入官方的代碼庫。 git鉤子 好了,確定了規(guī)范在服務(wù)端倉庫上來強推行,但怎么做到當(dāng)用戶push動作觸發(fā)的時候去做一下代碼強校驗?zāi)兀?jīng)過調(diào)研發(fā)現(xiàn),git鉤子正好解決了我們的這個問題。 什么是git鉤子呢?git鉤子是在git倉庫中特定重要動作發(fā)生時自動運行的腳本,它可以讓你自定義git內(nèi)部的行為,在開發(fā)周期中的關(guān)鍵點觸發(fā)自定義的行為。這樣來說,git鉤子就可以幫我們來推行規(guī)范了。 git鉤子到底什么樣呢,它存在于每個git倉庫的.git/hooks目錄中,當(dāng)你觀察.git/hooks時,你會看到下面這樣的文件: ![]() hooks目錄下展示的鉤子并不全,這里帶simple后綴的只是git的大部分鉤子,.sample拓展名防止它們默認(rèn)被執(zhí)行,想要運行一個鉤子,去掉后綴名或者在git官網(wǎng)查看相應(yīng)鉤子名稱添加新文件即可。 鉤子分類
鉤子語言
git服務(wù)端鉤子由上面的git知識點一步步看下來,我們就可以確定了代碼校驗合適的地方是在服務(wù)端鉤子上,但服務(wù)端鉤子也有好多,我們的代碼規(guī)范要在哪個鉤子做比較合適呢,接來下就具體介紹下服務(wù)端最有用的3個鉤子,并找出一個適合我們的鉤子。
這個腳本在git push向遠(yuǎn)程倉庫推送操作時,最先被調(diào)用。它沒有參數(shù),但是可以從標(biāo)準(zhǔn)輸入獲取一系列的推送引用。如果它以非零值退出,所有的推送內(nèi)容都不會被接受,所以這是強制推行開發(fā)規(guī)范的好地方。
update腳本和pre-receive腳本十分類似,不同之處在于它會為每一個準(zhǔn)備更新的分支各運行一次。假如推送者同時向多個分支推送內(nèi)容,pre-receive只運行一次,相比之下update則會為每一個被推送的分支各運行一次。它不會從標(biāo)準(zhǔn)輸入讀取內(nèi)容,而是會接受三個參數(shù),這三個參數(shù)信息和pre-receive在標(biāo)準(zhǔn)輸入讀取信息相同。如果update腳本以非零值退出,只有相應(yīng)的那一個引用會被拒絕;其余的依然會被更新。
post-receive腳本在成功推送后被調(diào)用,可以用來更新其他系統(tǒng)服務(wù)或者通知用戶,它接受與 pre-receive相同的標(biāo)準(zhǔn)輸入數(shù)據(jù)。它的用途包括給某個郵件列表發(fā)信,通知持續(xù)集成(continous integration)的服務(wù)器,或者更新問題追蹤系統(tǒng)(ticket-tracking system)等。 服務(wù)端推送成功后調(diào)用的鉤子不止post-receive這一個,如上面.git/hooks圖中的post-update也是其中之一,但是為什么不介紹post-update呢?原因是它的輸入獲取值太單一,post-receive更像是post-update的超級集合,所以推送成功后的調(diào)用我們一般用post-receive。 我們經(jīng)常用到的gitlab中的web hook就綁定了這個鉤子,當(dāng)然web hook是綁定了好幾個不同的鉤子的,post-receive只是其中一個,如下圖的web hook的中的Push events事件觸發(fā)的就是.git/hooks中的post-receive腳本 ![]() 分析這三個鉤子,我們顯然選push成功前調(diào)用的鉤子,那到底是選pre-receive還是update呢?考慮到我們的項目很少有一次push多個分支的場景,最終選了pre-receive鉤子來做我們的代碼強校驗。 在pre-receive鉤子里做代碼校驗鉤子選擇好了,接下來就是怎么做了,下面是一個簡單的流程圖,具體為從標(biāo)準(zhǔn)輸入中獲取三個值,分別是推送前的引用指向內(nèi)容的SHA-1值,用戶準(zhǔn)備推送內(nèi)容的SHA-1值和分支名,我再代碼里分別用變量oldhash,newhash和branch來表示這三個值,下面有用到。根據(jù)這三個值用git命令分別獲取用戶信息和提交的增量文件,把這些文件推送到eslint服務(wù)上進(jìn)行代碼校驗,校驗成功就直接push通過;不成功則在客戶端返回校驗結(jié)果,push不通過。 ![]() 根據(jù)上面的描述,重點介紹下怎么獲取用戶信息和增量文件
獲取用戶信息的目的是傳給eslint服務(wù)端,在服務(wù)端可以給分析用戶的行為及給用戶發(fā)送郵件等 這個命令可以定制化格式只獲取用戶的信息
定制化后運行的結(jié)果是下面這樣的,可以獲取提交者的信息: ![]()
增量文件取得是本次推送引用指向內(nèi)容的SHA-1值和推送前的引用指向內(nèi)容的SHA-1值中間的差值。命令如下,其中 --name-status是只取差異文件的名字和狀態(tài)值 為什么不直接取本次推送引用指向內(nèi)容的SHA-1值而取差值呢,原因是上次推送和本次推送中間可能隔了好幾個commit,每一個commit對象都會生成一個唯一的SHA-1哈希字串的。
運行后得到的結(jié)果是: ![]() 后面的就是怎么獲取文件及和eslint服務(wù)通訊的問題了,在這里不是重點就略過了... 總結(jié)本文可以說是我接到任務(wù)后,從只了解git的git pull、git clone、git push等幾個常用命令到怎么在git上實現(xiàn)我們的需求的一個探索過程,希望里面的介紹對不是很熟悉git的同學(xué)有點幫助,另外也簡單介紹了下我們強推規(guī)范的大致流程。后續(xù)會繼續(xù)研究下gitlab和git鉤子的關(guān)聯(lián)關(guān)系。 |
|
來自: bananarlily > 《IT》