Git 实现自动化部署项目
Git 实现自动化部署项目
- 应用场景
在本地开发、调试后想部署到服务器上,那么一般做法是先将本地的代码全部提交到 github 仓库,这时候要让服务器上的代码更换成最新提交的,那就得登录到服务器做一次 git pull origin master 的操作,前提是已经在服务器的项目目录下初始化好项目仓库。
此文探讨 Git 如何实现自动化部署项目,避免每次 git pull origin master 的繁琐操作。
- Git 钩子
官网解释:和其它版本控制系统一样,Git 能在特定的重要动作发生时触发自定义脚本。
有两组这样的钩子:
1、客户端的。客户端钩子由诸如提交和合并这样的操作所调用。
2、服务器端。服务器端钩子作用于诸如接收被推送的提交这样的联网操作。你可以随心所欲地运用这些钩子。
简单来说就是一个在特定环境下触发的脚本。也就是说我们可以把服务器拉取更新的代码这一步设置为自动触发,自动拉取到最新。
部署过程
以 root 用户为例,若不是 root 用户,可以看最底下的非 root 用户操作说明
-
第一步:检查家目录下是否有.ssh 文件夹
.ssh 中应有id_rsa
、id_rsa.pub
、authorized_keys
三个文件,若没有则用touch
创建。 -
第二步:配置 git 并获取公钥
- 如果用了 --global 选项,那么以后该用户下所有的 git 项目都会使用这个全局配置的用户信息。
#在本地配置用户名和邮箱 git config --global user.name "your name" git config --global user.email "your email"
- 如果要在某个特定的项目中使用特定名字或邮箱,只需在该项目目录下执行:
git config user.name "your name" git config user.email "your email"
-
接下来获取公钥,请先查看你的用户下的.ssh 文件夹中是否之前就含有公钥和私钥,我们需要寻找一对以 id_dsa 或 id_rsa 命名的文件(第一步已说明),其中一个带有 .pub 扩展名。.pub 文件是你的公钥,另一个则是私钥。如果没有请运行 ssh-keygen。
ssh-keygen -t rsa -C "your_email@example.com"
-
注意:执行
ssh-keygen
命令后,会出现Enter file in which to save the key (/root/.ssh/id_rsa):
的提示,直接回车即可,表明该用户想在/root/.ssh/id_rsa
默认路径下创建。然后会提示Enter passphrase (empty for no passphrase):
,输入密码,然后会提示Enter same passphrase again:
,再次输入密码,最后会提示Your identification has been saved in /root/.ssh/id_rsa.
说明公钥已经生成。 -
查看公钥,执行命令:
cat ~/.ssh/id_rsa.pub
-
使用
cat ~/.ssh/id_rsa.pub
命令可以获取公钥,复制它,使用 vi 或者 vim 命令把它粘贴到我们创建的authorized_keys
文件中,使用:wq 保存。
-
第三步:初始化仓库 (这个仓库用作中转)
-
中转的作用?是指在服务器上创建的裸仓库,本地项目仓库会克隆该裸仓库到本地,具有向远程裸仓库 push、pull 的能力,服务器上的项目仓库也会克隆一份裸仓库,那么在这三者中,本地仓库向远程裸仓库 git push 最新代码后,这个裸仓库会执行我们使用 git 钩子编写的自动化脚本,然后命令服务器上的项目仓库 git pull 裸仓库中最新的代码,从而实现自动化部署。
-
进入项目文件目录
cd /your_work_dir
,或者也可以创建一个存放 git 仓库的文件夹(此文示例只展示直接在项目目录中直接添加一个裸仓库且 your_work_dir 为 node 的情况):#创建一个存放 git 仓库的文件夹 mkdir /your_work_dir/git cd /your_work_dir/git
-
初始化仓库:
#初始化一个裸仓库(强烈建议): # - 当只使用 git init 时,会将执行命令时所在的文件夹初始化为一个 git 仓库 # - 当 git init 后加 gitResigterName 时,会在所在文件夹下创建一个新文件夹,此时该新文件夹为 git 仓库 #如下命令是在 /node 目录下执行,即创建 /node/bare.git 仓库 git init --bare bare.git
- 关于裸仓库和普通仓库的区别简单来说就是裸仓库看不到项目文件,普通仓库和你的项目目录一样,只是多了一个
.git
文件夹。
-
-
第四步:生成项目仓库
-
在服务器上进行
cd /your_work_dir #克隆仓库 git clone /your_work_dir/bare.git
-
==注意!一定要注意上面的路径!git 仓库是 /your_work_dir/bare.git, 项目仓库是 /your_work_dir/bare,即 bare 仓库目录下可存放自己的项目代码(此处存放的代码需要拉取中转仓库 bare.git 中的代码,自动化脚本就是执行这个自动拉取步骤)。==
-
-
第五步:克隆到本地
-
在你自己的电脑上进行
# 通过ip地址从配置好的线上仓库拉取下来 git clone git@your_server_ip:/your_work_dir/bare.git # 如果有配置域名的话也可以通过域名拉取 git clone git@your_server_domain_name:/your_work_dir/bare.git
-
因为公钥的原因,这里是不需要密码的,如果需要,那么就输入远程 SSH 连接需要的密码。
-
git clone 成功的话,你的电脑上会出现一个 bare 的文件夹,如果报错请检查后再进行下面的操作。
-
上述两次 git clone 得到的 bare 文件夹是可以改名的。
-
-
第六步:上传代码(git push)
- 打开刚才克隆下来的本地仓库
cd bare # 创建README.md文件 touch README.md git add . git commit -m"创建README.md文件" git push
- 不出意外已经正常上传了,如果报错请检查权限和 git 仓库情况。
-
第七步:添加钩子
-
回到线上的服务器,下面的命令是在线上服务器操作的:
#切换到这个目录 cd /your_work_dir/bare.git/hooks # 生成post-receive文件 touch post-receive # 使用vim编辑 vim post-receive
-
在 post-receive 文件里面输入(下面所列的未注释命令除 echo 外,都需要添加进自己的脚本中):
#!/bin/sh # 打印输出 echo '======上传代码到服务器======' # 打开线上项目文件夹 cd /your_work_dir/bare # 这个很重要,如果不取消的话将不能在cd的路径上进行git操作 unset GIT_DIR git pull origin master # 在 /your_work_dir/code/bare 下需要执行的命令 # 如npm run build、nodemon index.js # 输出 git 自动化脚本执行的日期日志到 /your_work_dir/logs/hook.log echo $(date) >> /your_work_dir/logs/hook.log # 以上仅为示例,有需要者可自行参考 git 钩子和根据需要扩展相关命令
-
保存后给 post-receive 文件加上运行权限
chmod +x post-receive
-
-
测试
在本地修改部分内容,然后提交推送 git push,可以看到已经实现了自动化部署。
非 root 用户操作说明
- 上面提到的部署过程仅为 root 用户示例,若为非 root 用户,大致步骤也一样,需要特别注意的是文件/文件夹的权限问题,比如在 /your_work_dir/git/bare.git 目录,当没有写入权限时,git pull 将会报错。
文章参考: 如何使用 Git 实现自动化部署你的项目
一些细枝末节的唠叨
-
上述部署过程中使用到了三个仓库,bare 本地仓库、bare.git 中转仓库和 bare 线上项目仓库,为区分三者,先将本地仓库改为 dev,线上仓库改为 server 后,再做如下讲解:
-
真正能 git push / pull 的仓库其实是 dev,它 push / pull 的对象是远程仓库 bare.git,而 server 仓库只是 git pull,一直自动拉取 bare.git 最新的更新情况
-
==当手动修改了 server 仓库中的代码时,==,每次从 dev 本地仓库 push 到远程仓库后的自动更新可能会失败,其原因在于自动化脚本执行了
git pull origin master
,它会自动执行一次合并,但是当合并失败时需要在 server 中手动解决合并。合并修改后的文件再重新添加到 server 的本地仓库,再次进行 git pull 从而得到 bare.git 中最新的一次提交