<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          手寫 git hooks 腳本

          共 7940字,需瀏覽 16分鐘

           ·

          2023-08-22 00:32

          34baea035e7d07dd7f48b3d0181d7cfe.webp

          我們的 Git 倉(cāng)庫(kù)中包含了編譯后的代碼,所以每次修改了源碼,都需要運(yùn)行一下編譯命令,然后把源碼和編譯后的代碼一起提交到 Git 倉(cāng)庫(kù),這個(gè)流程沒什么問題。但是,人腦不是電腦,總會(huì)有疏忽的時(shí)候,經(jīng)常會(huì)出現(xiàn)這樣一種情況:修改了源碼,卻忘記了運(yùn)行編譯命令,最后只把源碼提交到了 Git 倉(cāng)庫(kù),導(dǎo)致線上倉(cāng)庫(kù)的源碼和編譯產(chǎn)物不一致、


          這個(gè)問題雖然不是特別嚴(yán)重,但老是出現(xiàn)也總歸不好。所以我們就想了一個(gè)辦法,不再手動(dòng)編譯,把編譯任務(wù)交給 CI 去做,這樣就不存在這樣的問題。類似一些自動(dòng)化管理version版本,tag 操作, hooks腳本管理 version文件等。


          git hooks 可以幫助我們做到這些工作,在 Git 中也有許多的事件(commit、push 等等),每個(gè)事件也是對(duì)應(yīng)了有不同的鉤子的(如 commit 前,commit 后),那么我們就可以在這些鉤子這里配置一些自己需要執(zhí)行的操作來實(shí)現(xiàn)各種各樣的需求。


          下面來分享git hooks 腳本:https://git-scm.com/docs/githooks

          0a17ebd4d1bb033f1ace091389612cf6.webp


          簡(jiǎn)介

          Git 能在特定的重要?jiǎng)幼靼l(fā)生時(shí)觸發(fā)自定義腳本,其中比較常用的有:pre-commit、commit-msg、pre-push 等鉤子(hooks)。我們可以在 pre-commit 觸發(fā)時(shí)進(jìn)行代碼格式驗(yàn)證,在 commit-msg 觸發(fā)時(shí)對(duì) commit 消息和提交用戶進(jìn)行驗(yàn)證,在 pre-push 觸發(fā)時(shí)進(jìn)行單元測(cè)試、e2e 測(cè)試等操作。

          Git 在執(zhí)行 git init 進(jìn)行初始化時(shí),會(huì)在 .git/hooks 目錄生成一系列的 hooks 腳本:

          6d0f92b288dbb1b4454ef113a12aead7.webp

          從上圖可以看到每個(gè)腳本的后綴都是以 .sample 結(jié)尾的,在這個(gè)時(shí)候,腳本是不會(huì)自動(dòng)執(zhí)行的。我們需要把后綴去掉之后才會(huì)生效,即將 pre-commit.sample 變成 pre-commit 才會(huì)起作用。

          本文主要是想介紹一下如何編寫 git hooks 腳本,并且會(huì)編寫兩個(gè) pre-commit、commit-msg 腳本作為示例,幫助大家更好的理解 git hooks 腳本。當(dāng)然,在工作中還是建議使用現(xiàn)成的、開源的解決方案 husky[1]

          正文

          用于編寫 git hooks 的腳本語言是沒有限制的,你可以用 nodejsshell、python、ruby等腳本語言,非常的靈活方便。

          下面我將用 shell 語言來演示一下如何編寫 pre-commit 和 commit-msg 腳本。另外要注意的是,在執(zhí)行這些腳本時(shí),如果以非零的值退出程序,將會(huì)中斷 git 的提交/推送流程。所以在 hooks 腳本中驗(yàn)證消息/代碼不通過時(shí),就可以用非零值進(jìn)行退出,中斷 git 流程。

                
                  exit 1
                
              

          pre-commit

          在 pre-commit 鉤子中要做的事情特別簡(jiǎn)單,只對(duì)要提交的代碼格式進(jìn)行檢查,因此腳本代碼比較少:

                
                  
                    #!/bin/sh
                  
                
                
                  npm run lint
                
                
                  
                    
          # 獲取上面腳本的退出碼 exitCode="$?" exit $exitCode

          由于我在項(xiàng)目中已經(jīng)配置好了相關(guān)的 eslint 配置以及 npm 腳本,因此在 pre-commit 中執(zhí)行相關(guān)的 lint 命令就可以了,并且判斷一下是否正常退出。

                
                  
                    // 在 package.json 文件中已配置好 lint 命令
                  
                
                
                  "scripts": {
                
                
                      "lint": "eslint --ext .js src/"
                
                
                   },
                
              

          下面看一個(gè)動(dòng)圖,當(dāng)代碼格式不正確的時(shí)候,進(jìn)行 commit 就報(bào)錯(cuò)了:

          c5da9c69b2af65901f8d77c1a77d3c95.webp

          在修改代碼格式后再進(jìn)行提交,這時(shí)就不報(bào)錯(cuò)了:

          e762216d3fdf8dad2e3075e721915885.webp

          從動(dòng)圖中可以看出,這次 commit 已正常提交了。

          commit-msg

          在 commit-msg hooks 中,我們需要對(duì) commit 消息和用戶進(jìn)行校驗(yàn)。

                
                  
                    #!/bin/sh
                  
                
                
                  
                    
          # 用 `` 可以將命令的輸出結(jié)果賦值給變量 # 獲取當(dāng)前提交的 commit msg commit_msg=`cat $1`
          # 獲取用戶 email email=`git config user.email` msg_re="^(feat|fix|docs|style|refactor|perf|test|workflow|build|ci|chore|release|workflow)(\(.+\))?: .{1,100}"
          if [[ ! $commit_msg =~ $msg_re ]] then echo "\n不合法的 commit 消息提交格式,請(qǐng)使用正確的格式:\ \nfeat: add comments\ \nfix: handle events on blur (close #28)\ \n詳情請(qǐng)查看 git commit 提交規(guī)范:https://github.com/woai3c/Front-end-articles/blob/master/git%20commit%20style.md"
          # 異常退出 exit 1 fi

          在 commit-msg 鉤子觸發(fā)時(shí),對(duì)應(yīng)的腳本會(huì)接收到一個(gè)參數(shù),這個(gè)參數(shù)就是 commit 消息,通過 cat $1 獲取,并賦值給 commit_msg 變量。

          驗(yàn)證 commit 消息的正則比較簡(jiǎn)單,看代碼即可。如果對(duì) commit 提交規(guī)范有興趣,可以看看我另一篇文章[2]。

          對(duì)用戶權(quán)限做判斷則比較簡(jiǎn)單,只需要檢查用戶的郵箱或用戶名就可以了(假設(shè)現(xiàn)在只有 abc 公司的員工才有權(quán)限提交代碼)。

                
                  email_re="@abc\.com"
                
                
                  if [[ ! $email =~ $email_re ]]
                
                
                  
                    then
                  
                
                
                      echo "此用戶沒有權(quán)限,具有權(quán)限的用戶為:[email protected]"
                
                
                  
                    
          # 異常退出 exit 1 fi

          下面用兩個(gè)動(dòng)圖來分別演示一下校驗(yàn) commit 消息和判斷用戶權(quán)限的過程:

          94379db8bb89033926460b6aa417ffe6.webp

          74c4b908ae57dd6c1573b0e48248444d.webp

          設(shè)置 git hooks 默認(rèn)位置

          腳本可以正常執(zhí)行只是第一步,還有一個(gè)問題是必須要解決的,那就是如何和同一項(xiàng)目的其他開發(fā)人員共享 git hooks 配置。因?yàn)?nbsp;.git/hooks 目錄不會(huì)隨著提交一起推送到遠(yuǎn)程倉(cāng)庫(kù)。對(duì)于這個(gè)問題有兩種解決方案:第一種是模仿 husky 做一個(gè) npm 插件,在安裝的時(shí)候自動(dòng)在 .git/hooks 目錄添加 hooks 腳本;第二種是將 hooks 腳本單獨(dú)寫在項(xiàng)目中的某個(gè)目錄,然后在該項(xiàng)目安裝依賴時(shí),自動(dòng)將該目錄設(shè)置為 git 的 hooks 目錄。

          接下來詳細(xì)說說第二種方法的實(shí)現(xiàn)過程:

          1.在 npm install 執(zhí)行完成后,自動(dòng)執(zhí)行 git config core.hooksPath hooks 命令。 2.git config core.hooksPath hooks 命令將 git hooks 目錄設(shè)置為項(xiàng)目根目錄下的 hooks 目錄。

                
                  "scripts": {
                
                
                   "lint": "eslint --ext .js src/",
                
                
                   "postinstall": "git config core.hooksPath hooks"
                
                
                  },
                
              

          踩坑

          demo 源碼在 windows 上是可以正常運(yùn)行的,后來?yè)Q成 mac 之后就不行了,提交時(shí)報(bào)錯(cuò):

                
                  hint: The 'hooks/pre-commit' hook was ignored because it's not set as executable.
                
              

          原因是 hooks 腳本默認(rèn)為不可執(zhí)行,所以需要將它設(shè)為可執(zhí)行:

                
                  chmod 700 hooks/*
                
              

          為了避免每次克隆項(xiàng)目都得修改,最好將這個(gè)命令在 npm 腳本上加上:

                
                  "scripts": {
                
                
                   "lint": "eslint --ext .js src/",
                
                
                   "postinstall": "git config core.hooksPath hooks && chmod 700 hooks/*"
                
                
                  },
                
              

          當(dāng)然,如果是 windows 就不用加后半段代碼了。


          nodejs hooks 腳本

          為了幫助前端同學(xué)更好的理解 git hooks 腳本,我用 nodejs 又重寫了一版。

          pre-commit

                
                  
                    #!/usr/bin/env node
                  
                
                
                  const childProcess = require('child_process');
                
                
                  
                    
          try { childProcess.execSync('npm run lint'); } catch (error) { console.log(error.stdout.toString()); process.exit(1); }

          commit-msg

                
                  
                    #!/usr/bin/env node
                  
                
                
                  const childProcess = require('child_process');
                
                
                  const fs = require('fs');
                
                
                  
                    
          const email = childProcess.execSync('git config user.email').toString().trim(); const msg = fs.readFileSync(process.argv[2], 'utf-8').trim(); // 索引 2 對(duì)應(yīng)的 commit 消息文件 const commitRE = /^(feat|fix|docs|style|refactor|perf|test|workflow|build|ci|chore|release|workflow)(\(.+\))?: .{1,100}/;
          if (!commitRE.test(msg)) { console.log(); console.error('不合法的 commit 消息格式,請(qǐng)使用正確的提交格式:'); console.error('feat: add \'comments\' option'); console.error('fix: handle events on blur (close #28)'); console.error('詳情請(qǐng)查看 git commit 提交規(guī)范:https://github.com/woai3c/Front-end-articles/blob/master/git%20commit%20style.md。'); process.exit(1); }
          if (!/@qq\.com$/.test(email)) { console.error('此用戶沒有權(quán)限,具有權(quán)限的用戶為:[email protected]'); process.exit(1); }

          總結(jié)

          其實(shí)本文適用的范圍不僅僅局限于前端,而是適用于所有使用了 git 作為版本控制的項(xiàng)目。例如安卓、ios、Java 等等。只是本文選擇了前端項(xiàng)目作為示例。

          最近附上項(xiàng)目源碼:https://github.com/woai3c/git-hooks-demo

          參考資料

          ? 自定義 Git - 使用強(qiáng)制策略的一個(gè)例子[3] ? Shell 教程[4]

          References

          [1] husky: https://github.com/typicode/husky
          [2] 文章: https://github.com/woai3c/Front-end-articles/blob/master/git%20commit%20style.md
          [3] 自定義 Git - 使用強(qiáng)制策略的一個(gè)例子: https://git-scm.com/book/zh/v2/%E8%87%AA%E5%AE%9A%E4%B9%89-Git-%E4%BD%BF%E7%94%A8%E5%BC%BA%E5%88%B6%E7%AD%96%E7%95%A5%E7%9A%84%E4%B8%80%E4%B8%AA%E4%BE%8B%E5%AD%90
          [4] Shell 教程: https://www.runoob.com/linux/linux-shell.html


                                            ????????????????  END  ????????????????


          推薦閱讀

          【1】jetson nano開發(fā)使用的基礎(chǔ)詳細(xì)分享

          【2】Linux開發(fā)coredump文件分析實(shí)戰(zhàn)分享

          【3】CPU中的程序是怎么運(yùn)行起來的 必讀

          【4】cartographer環(huán)境建立以及建圖測(cè)試

          【5】設(shè)計(jì)模式之簡(jiǎn)單工廠模式、工廠模式、抽象工廠模式的對(duì)比

          本公眾號(hào)全部原創(chuàng)干貨已整理成一個(gè)目錄,回復(fù)[ 資源 ]即可獲得。



          瀏覽 79
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩欧美视频青青 | 香蕉成人在线 | jk自慰网站| 国产色哟哟 | 影音先锋av成人网 |