把Git代码部署到服务器,最直接的方式就是SSH登录服务器,用git clone或git pull拉取最新代码,然后安装依赖、重启服务。 整个流程不算复杂,但很多人在权限、分支、自动部署这几个环节容易卡住,下面我会按实际操作的顺序,把从克隆代码到自动部署的每个步骤拆开讲清楚。
先搞清楚git代码部署服务器的两种方式
部署Git代码到服务器,业内专家指出主要有两条路:手动登录服务器执行git pull,以及利用Git Hook或Webhook实现自动部署,手动方式适合小项目、个人站点,改动少,出问题容易排查,自动方式适合团队协作、更新频繁的生产环境,一次配置好之后,本地git push完代码就自动同步到服务器。
手动部署:git pull拉取代码到服务器
这是最基础的办法,你需要在服务器上保留一个代码仓库的拷贝,每次更新时在服务器上执行拉取命令,第一次部署时,用git clone把仓库克隆下来,之后每次更新就进入项目目录执行git pull。
手动部署的好处是逻辑清晰,坏处是如果忘了拉取,服务器上的代码就会落后,实际操作中,很多人会写个脚本,或者用crontab定时拉取,但定时拉取不是真自动,存在延迟。
自动部署:git hook自动部署配置
自动部署的核心是利用Git自带的Hook机制,在服务器仓库的hooks目录下,有一个post-receive文件,当收到git push推送后,Git会执行这个脚本,你可以在脚本里写git --work-tree=/网站目录 --git-dir=/仓库目录 checkout -f,或者cd /项目目录 && git pull,以此实现代码自动同步。
这种方式配置一次就能长期生效,是现在比较标准的服务器部署做法,行业共识认为,中小型项目用post-receive钩子配合www用户,就能解决大部分自动化需求。
git pull部署代码到服务器前,要确认这几个条件
不能直接上手就git pull,很多问题提前避免比事后排查省力得多,我按踩坑频率排序,列一下需要确认的基础条件。
- 服务器已安装Git,且版本不低于2.0
- 仓库地址是SSH形式,而不是只读HTTPS
- 当前登录用户对项目目录有写权限
- 本地和服务器拉取的是同一个分支
- 服务器上的本地改动不会和远程代码冲突
SSH密钥配置
绝大多数服务器仓库,比如GitHub、Gitee,都支持通过SSH协议拉取代码,你需要把服务器的公钥添加到仓库的Deploy Keys里,具体操作是:在服务器上执行ssh-keygen -t rsa -b 4096,一路回车生成密钥,然后cat ~/.ssh/id_rsa.pub查看公钥,粘贴到代码平台的仓库设置中。
配置好之后,先用ssh -T git@github.com测试连通性,再执行git clone,这一步能避免反复让你输入密码,也方便后续自动化脚本执行。
目录权限和用户身份
很多人在git pull时报错Permission denied,基本就是目录属主问题,web服务器运行用户一般是www-data或nginx,但你的登录用户是root或者其他账号,你需要把项目目录的属主改成web运行用户,或者至少让web用户有读取权限。
比如在Ubuntu系统上,可以执行:
sudo chown -R www-data:www-data /var/www/htmlsudo chmod -R 755 /var/www/html
然后把当前用户加入www-data组,或者直接用sudo -u www-data git pull执行拉取。
实战:从clone到部署的完整命令流程
我以一台全新的Ubuntu服务器为例,假设项目是Node.js写的,代码托管在GitHub私有仓库,整个流程按顺序执行,基本不会出错。
首次部署:git clone代码
登录服务器后,先更新系统包,安装Git:
sudo apt update && sudo apt install git -y
然后生成SSH密钥并添加到GitHub,步骤上面讲过,接着创建项目存放目录:
sudo mkdir -p /var/www/myappsudo chown -R $USER:$USER /var/www/myappcd /var/www/myapp
现在克隆代码:
git clone git@github.com:yourname/myapp.git .
注意最后有一个点,表示克隆到当前目录,克隆完成后检查一下:
ls -la
后续更新:git pull拉取代码
以后每次发布新版本,你在服务器上执行:
cd /var/www/myappgit pull origin main
为了保险,建议先看下有没有本地改动:
git status
如果有未提交的改动,先git stash暂存,拉取完成后再git stash pop恢复。
安装依赖并重启服务
代码拉取下来只是第一步,部署还包含依赖安装和进程重启,Node.js项目需要执行:
npm install --productionpm2 restart app
如果改了环境变量,还要更新.env文件,这些步骤可以写进一个deploy.sh脚本里,下次只跑脚本就行。
常见坑:git部署代码时遇到权限不足怎么办
权限问题是部署过程中遇到最多的异常,几乎有一半的报错都跟权限相关,我举两个真实场景。
clone成功但git pull失败
之前有个用户,用root身份克隆了代码,之后切换成普通用户去git pull,结果提示无法写入.git/FETCH_HEAD,原因很简单,.git目录的所有者是root,普通用户没有写权限。
解决办法是调整目录属主:
sudo chown -R www-data:www-data /var/www/myapp
然后始终用同一个用户操作项目目录。
post-receive钩子执行失败
自动部署脚本里执行git pull时提示Unable to pull,通常是钩子脚本的运行用户和仓库目录属主不一致,Git在执行钩子时,用的是当前推送用户的身份,你需要在钩子脚本开头切换用户,或者把仓库目录统一交给www-data管理。
一个典型的post-receive脚本写法是:
#!/bin/bash
export GIT_WORK_TREE=/var/www/myapp
export GIT_DIR=/var/www/myapp/.git
cd $GIT_WORK_TREE
git pull origin main
然后给脚本加执行权限即可。
Git代码部署到服务器并不神秘,手动部署记住clone加pull,自动部署记住post-receive钩子,只要先保证SSH通、目录属主对、分支一致,整个流程就能跑得很顺畅,把这些步骤固化成一个部署脚本,以后发版本就只需要在本地按一下push。
git代码部署服务器的常见问题,这里一次性说清
Q:服务器上git clone和git pull有什么区别?
A:git clone是首次把远程仓库完整下载到本地,会创建.git目录。git pull是在已有本地仓库的基础上,拉取远程的新提交并合并到当前分支,部署时通常只用一次clone,之后反复pull。
Q:git hook自动部署会不会影响本地代码?
A:不会。post-receive钩子只在服务器仓库收到推送时触发,运行环境是服务器,和本地开发环境完全隔离,只要钩子脚本里的--work-tree路径指向正确的网站目录,就不会影响本地仓库。
Q:用git部署代码到服务器,需要开放哪些端口?
A:SSH方式只需要开放服务器的22端口,代码仓库的域名解析正常即可,如果走HTTPS方式拉取,需要允许出站443端口,但内部服务器到GitHub的访问一般不受防火墙影响。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/751308.html





