Git 支持在不同操作上执行的钩子。这些钩子在服务器上运行,可用于根据存储库的状态强制执行特定的提交策略或执行其他任务。
Git 支持以下钩子:
pre-receive
post-receive
update
服务器端 Git 钩子可以配置为:
这里需要注意服务器端的git钩子必须在 GitLab 服务器的文件系统上配置.
如果您没有使用 hashed storage,,则项目的存储库目录则应该是下面:
/home/git/repositories/<group>/<project>.git
./var/opt/gitlab/git-data/repositories/<group>/<project>.git
.这里我们是rpm安装的gitlab,默认是使用了hashed storage,要先去查找项目的哈希路径,我们需要用如下方式为git仓库设置服务端git钩子:
image-20210809170728289
image-20210809170835766
custom_hooks的
目录custom_hooks
目录中,创建一个名称与钩子类型匹配的文件。例如,对于预接收钩子,文件名应该pre-receive
,没有扩展名且pre-receive文件要有可执行权限并将属主属组设置为 git在进行 push 操作时,GitLab 会调用这个钩子文件,并且从 stdin 输入三个参数,分别为 之前的版本 commit ID、push 的版本 commit ID 和 push 的分支;根据 commit ID 我们就可以很轻松的获取到提交信息,从而实现进一步检测动作;根据 GitLab 的文档说明,当这个 hook 执行后以非 0 状态退出则认为执行失败,从而拒绝 push;同时会将 stderr 信息返回给 client 端;
我们下面创建一个pre-receive,只允许包含build=(yes|no) deploy=(yes|no)的commit message 提交
package main
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"strings"
)
type CommitType string
const CommitMessagePattern = `(.*build=(yes|no).*deploy=(yes|no).*)|^Merge\ branch(.*)`
const checkFailedMeassge = `GL-HOOK-ERR:##############################################################################
GL-HOOK-ERR:##
GL-HOOK-ERR: Commit message 格式检查失败!
GL-HOOK-ERR:
GL-HOOK-ERR: Commit message 格式应符合下面的正则表达式:
GL-HOOK-ERR: (.*build=(yes|no).*deploy=(yes|no).*)|^Merge\ branch(.*)
GL-HOOK-ERR:##
GL-HOOK-ERR: Commit message Example:
GL-HOOK-ERR: Update date.html build=no,deploy=yes
GL-HOOK-ERR:##
GL-HOOK-ERR:##############################################################################`
// 是否开启严格模式,严格模式下将校验所有的提交信息格式(多 commit 下)
const strictMode = false
var commitMsgReg = regexp.MustCompile(CommitMessagePattern)
func main() {
input, _ := ioutil.ReadAll(os.Stdin)
param := strings.Fields(string(input))
// allow branch/tag delete
if param[1] == "0000000000000000000000000000000000000000" {
os.Exit(0)
}
commitMsg := getCommitMsg(param[0], param[1])
for _, tmpStr := range commitMsg {
commitTypes := commitMsgReg.FindAllStringSubmatch(tmpStr, -1)
if len(commitTypes) != 1 {
checkFailed()
} else {
fmt.Println(" ")
}
if !strictMode {
os.Exit(0)
}
}
}
func getCommitMsg(odlCommitID, commitID string) []string {
getCommitMsgCmd := exec.Command("git", "log", odlCommitID+".."+commitID, "--pretty=format:%s")
getCommitMsgCmd.Stdin = os.Stdin
getCommitMsgCmd.Stderr = os.Stderr
b, err := getCommitMsgCmd.Output()
if err != nil {
fmt.Print(err)
os.Exit(1)
}
commitMsg := strings.Split(string(b), "\n")
return commitMsg
}
func checkFailed() {
fmt.Fprintln(os.Stderr, checkFailedMeassge)
os.Exit(1)
}
[root@node-02 ~]# cd /var/opt/gitlab/git-data/repositories/
[root@node-02 repositories]# cd @hashed/2c/62/2c624232cdd221771294dfbb310aca000a0df6ac8b66b696d90ef06fdefb64a3.git
[root@node-02 ~]# mkdir custom_hooks/
[root@node-02 ~]# chowm git:gitcustom_hooks
[root@node-02 2c624232cdd221771294dfbb310aca000a0df6ac8b66b696d90ef06fdefb64a3.git]# cd custom_hooks/
[root@node-02 custom_hooks]# mv /root/pre-receive ./
[root@node-02 custom_hooks]# ls
pre-receive
[root@node-02 custom_hooks]# chmod +x pre-receive
[root@node-02 custom_hooks]# chowm git:git pre-receive
这里我们验证一下
[root@node-02 ~]# git clone https://gitlab.lishuai.fun/argocd/argocd-demo.git
正克隆到 'argocd-demo'...
Username for 'https://gitlab.lishuai.fun': lishuai
Password for 'https://lishuai@gitlab.lishuai.fun':
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 82 (delta 0), reused 0 (delta 0), pack-reused 79
Unpacking objects: 100% (82/82), done.
[root@node-02 ~]# cd argocd-demo/
[root@node-02 argocd-demo]# date>date.html
[root@node-02 argocd-demo]# git add date.html
[root@node-02 argocd-demo]# git commit -m "update date.html"
[master 1befbd0] update date.html
1 file changed, 1 insertion(+)
create mode 100644 date.html
[root@node-02 argocd-demo]# git push origin master
Username for 'https://gitlab.lishuai.fun': lishuai
Password for 'https://lishuai@gitlab.lishuai.fun':
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 317 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: GL-HOOK-ERR:##############################################################################
remote: GL-HOOK-ERR:##
remote: GL-HOOK-ERR: Commit message 格式检查失败!
remote: GL-HOOK-ERR:
remote: GL-HOOK-ERR: Commit message 格式应符合下面的正则表达式:
remote: GL-HOOK-ERR: (.*build=(yes|no).*deploy=(yes|no).*)|^Merge\ branch(.*)
remote: GL-HOOK-ERR:##
remote: GL-HOOK-ERR: Commit message Example:
remote: GL-HOOK-ERR: Update date.html build=no,deploy=yes
remote: GL-HOOK-ERR:##
remote: GL-HOOK-ERR:##############################################################################
To https://gitlab.lishuai.fun/argocd/argocd-demo.git
! [remote rejected] master -> master (pre-receive hook declined)
error: 无法推送一些引用到 'https://gitlab.lishuai.fun/argocd/argocd-demo.git'
这里我们看到我们提交的commit信息不符合要求,push时候被拒绝了,而如下,我们使用正确的commit信息就能正常push
##修改我们当前提交的commit信息
[root@node-02 argocd-demo]# git commit --amend
[master 9af865e] update date.html [build=no,deploy=no]
1 file changed, 1 insertion(+), 5 deletions(-)
##查看修改后的commit 信息,此时已经是 update date.html [build=no,deploy=no]
[root@node-02 argocd-demo]# git log
commit 9af865ee888513229cf7a6959e9afb2e654b35cb
Author: lishuai <lishuai@liangla.mobi>
Date: Thu Sep 9 16:23:34 2021 +0800
update date.html [build=no,deploy=no]
[root@node-02 argocd-demo]# git push origin master
Username for 'https://gitlab.lishuai.fun': lishuai
Password for 'https://lishuai@gitlab.lishuai.fun':
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 345 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
To https://gitlab.lishuai.fun/argocd/argocd-demo.git
237a1df..9af865e master -> master
pre-receive代码里不匹配发送的消息中我们使用GL-HOOK-ERR这个参数是为了可以在gitlab ui生成消息
image-20210909163113334
要创建适用于实例中所有存储库的 Git 挂钩,请设置全局服务器挂钩。默认的全局服务器端钩子目录在 GitLab Shell 目录中。在那里添加的任何钩子都适用于所有存储库。
全局服务器钩子目录:
/home/git/gitlab-shell/hooks
./opt/gitlab/embedded/service/gitlab-shell/hooks
.要为全局服务器挂钩使用不同的目录,请custom_hooks_dir
在 Gitaly 配置中设置:
gitlab.rb
.gitlab-shell/config.yml
.gitaly/config.toml
在[hooks]
部分下设置。按照以下步骤为所有存储库设置全局服务器钩子:
pre-receive.d
,post-receive.d
或update.d
目录。扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有