了解git裸仓库并利用post-receive自动化部署
文章目录
- 前言
- 普通库和裸仓库
- 普通库
- 裸仓库
- 使用裸仓库
- 使用 git remote add 方式关联
- 使用 git clone 直接克隆
- 为什么要使用裸仓库
- 自动化部署
- 需求
- 操作步骤
- 服务端远端操作
- 客户端本地操作
- 与远端裸仓库建立关联
- 快速回顾
- 总结
前言
【裸仓库】指的是使用 git init --bare
命令得到的仓库,是对这种操作结果的一种直译,这个词对于刚接触 git 软件的小伙伴来说可能是第一次听说,而我也是最近实际操作了几次才渐渐理解,下面解释一下什么是裸仓库,以及为什么要使用它,有理解不对的地方还请大家指正。
普通库和裸仓库
普通库
在解释裸仓库之前,还是先来看看 git init
命令创建一个普通仓库的目录结构:
[root@VM-0-3-centos data]# git init simple
Initialized empty Git repository in /data/simple/.git/
[root@VM-0-3-centos data]# cd simple/
[root@VM-0-3-centos simple]# touch README.md
[root@VM-0-3-centos simple]# cd ..
[root@VM-0-3-centos data]# tree -a simple/
simple/
|-- .git
| |-- branches
| |-- config
| |-- description
| |-- HEAD
| |-- hooks
| | |-- applypatch-msg.sample
| | |-- commit-msg.sample
| | |-- post-update.sample
| | |-- pre-applypatch.sample
| | |-- pre-commit.sample
| | |-- prepare-commit-msg.sample
| | |-- pre-push.sample
| | |-- pre-rebase.sample
| | `-- update.sample
| |-- info
| | `-- exclude
| |-- objects
| | |-- info
| | `-- pack
| `-- refs
| |-- heads
| `-- tags
`-- README.md10 directories, 14 files
通过上述命令操作后可以看到,git init simple
操作之后,创建了一个名为 simple
的库,simple
目录下还有一个 .git
子目录,其中包含了git系统常用的文件,在 .git
目录外是我们的工作区,可以存放我们库中待更新的文件,修改之后可以通过 git add
,git commit
等命令更新 .git
中的内容,简单来说普通库就是在工作目录 simple
中还包括一个 .git
目录,下面添加一个文件试试。
[root@VM-0-3-centos simple]# git add README.md
[root@VM-0-3-centos simple]# git commit -m"add readme file"
[master (root-commit) 9a9b255] add readme file1 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 README.md
[root@VM-0-3-centos simple]# tree . -a
.
|-- .git
| |-- branches
| |-- COMMIT_EDITMSG
| |-- config
| |-- description
| |-- HEAD
| |-- hooks
| | |-- applypatch-msg.sample
| | |-- commit-msg.sample
| | |-- post-update.sample
| | |-- pre-applypatch.sample
| | |-- pre-commit.sample
| | |-- prepare-commit-msg.sample
| | |-- pre-push.sample
| | |-- pre-rebase.sample
| | `-- update.sample
| |-- index
| |-- info
| | `-- exclude
| |-- logs
| | |-- HEAD
| | `-- refs
| | `-- heads
| | `-- master
| |-- objects
| | |-- 9a
| | | `-- 9b255b81e994fa9af2b9c7ecbd852eb716ad6c
| | |-- e6
| | | `-- 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
| | |-- f9
| | | `-- 3e3a1a1525fb5b91020da86e44810c87a2d7bc
| | |-- info
| | `-- pack
| `-- refs
| |-- heads
| | `-- master
| `-- tags
`-- README.md16 directories, 22 files
[root@VM-0-3-centos simple]#
添加文件之后,.git
目录中的内容发生了变化,多了3个新的object。
裸仓库
还是先从目录结构入手,我们使用 git init --bare
命令创建一个裸仓库,目录结构如下:
[root@VM-0-3-centos data]# git init --bare bare.git
Initialized empty Git repository in /data/bare.git/
[root@VM-0-3-centos data]# tree bare.git/ -a
bare.git/
|-- branches
|-- config
|-- description
|-- HEAD
|-- hooks
| |-- applypatch-msg.sample
| |-- commit-msg.sample
| |-- post-update.sample
| |-- pre-applypatch.sample
| |-- pre-commit.sample
| |-- prepare-commit-msg.sample
| |-- pre-push.sample
| |-- pre-rebase.sample
| `-- update.sample
|-- info
| `-- exclude
|-- objects
| |-- info
| `-- pack
`-- refs|-- heads`-- tags9 directories, 13 files
[root@VM-0-3-centos simple]#
从目录结构来看裸仓库和普通库很像,但是仔细对比你会发现,这个裸仓库相比普通库少了一层目录,库目录 bare.git
内直接就是之前普通库 .git
目录下的内容,也就是说在 git
目录外层没有了工作目录来进行文件的增删改操作,那么我们仿照普通库操作在这个目录下提交一个文件会怎样呢?
[root@VM-0-3-centos data]# cd bare.git/
[root@VM-0-3-centos bare.git]# touch README.md
[root@VM-0-3-centos bare.git]# git add README.md
fatal: This operation must be run in a work tree
[root@VM-0-3-centos bare.git]# git status
fatal: This operation must be run in a work tree
[root@VM-0-3-centos bare.git]#
通过操作发现这个裸仓库不允许增删改库内的文件,甚至连 git status
这种命令都无法使用,统一提示了 fatal: This operation must be run in a work tree
这句话,告诉用户这些命令都必须在工作区内操作,既然不能修改,那么这个裸仓库就是“只读”的,那么它还有什么用呢?
虽然裸仓库不允许直接修改,但是可以作为服务端远程仓库,在本地克隆这个远程仓库之后再进行修改,这也是最常见的应用方式,总结来说,普通库和裸仓库的区别就是:普通库拥有工作目录,并且工作目录中可以存放正常编辑和提交的文件,而裸库只存放这些文件的commit记录,不允许用户直接在上面进行各种git操作。
使用裸仓库
前面提到裸仓库不能直接修改,但是我们可以采取修改克隆后库文件的方式达到更新的目的,下面列举两种常见的方式:
使用 git remote add 方式关联
这种方式需要我们先在本地初始化一个普通库,再使用 git remote add
命令建立关联(PowerShell命令行操作,git命令是相同的):
PS-Win D:\data\maingit\test> git init barebyremote
Initialized empty Git repository in D:/data/maingit/test/barebyremote/.git/
PS-Win D:\data\maingit\test> cd .\barebyremote\
PS-Win D:\data\maingit\test\barebyremote> git remote add origin root@82.156.125.196:/data/bare.git
PS-Win D:\data\maingit\test\barebyremote> new-item README.md目录: D:\data\maingit\test\barebyremoteMode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2022/6/12 16:51 0 README.mdPS-Win D:\data\maingit\test\barebyremote> git add .\README.md
PS-Win D:\data\maingit\test\barebyremote> git commit -m"add readme file"
[master (root-commit) f1c41db] add readme file1 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 README.md
PS-Win D:\data\maingit\test\barebyremote> git push -u origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 223 bytes | 223.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To 82.156.125.196:/data/bare.git* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
PS-Win D:\data\maingit\test\barebyremote> git log -3
commit f1c41db4699f71e9750d8d6aa2c01875ac6d4a14 (HEAD -> master, origin/master)
Author: albert <albert@163.com>
Date: Sun Jun 12 16:51:34 2022 +0800add readme file
PS-Win D:\data\maingit\test\barebyremote>
使用 git clone 直接克隆
使用克隆方式时,按照普通库来操作就可以(PowerShell命令行操作,git命令是相同的):
PS-Win D:\data\maingit\test> git clone root@82.156.125.196:/data/bare.git barebyclone
Cloning into 'barebyclone'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
PS-Win D:\data\maingit\test> cd .\barebyclone\
PS-Win D:\data\maingit\test\barebyclone> git log -3
commit f1c41db4699f71e9750d8d6aa2c01875ac6d4a14 (HEAD -> master, origin/master, origin/HEAD)
Author: albert <albert@163.com>
Date: Sun Jun 12 16:51:34 2022 +0800add readme file
PS-Win D:\data\maingit\test\barebyclone> ls目录: D:\data\maingit\test\barebycloneMode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2022/6/12 16:57 0 README.md
为什么要使用裸仓库
既然裸仓库相比于普通库只是少了工作目录,那么我们直接用普通库作为远程仓库可不可以呢?结论是可以,但是不建议,我们来实际操作一下,利用刚刚的建立的 simple
作为远端库,我们在本地clone后修改,再上传看看会遇到什么问题。
PS-Win D:\data\maingit\test> git clone root@82.156.125.196:/data/simple simple
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
PS-Win D:\data\maingit\test> cd .\simple\
PS-Win D:\data\maingit\test\simple> git log -3
commit 9a9b255b81e994fa9af2b9c7ecbd852eb716ad6c (HEAD -> master, origin/master, origin/HEAD)
Author: albert <albert@example.com>
Date: Sun Jun 12 15:53:30 2022 +0800add readme file
PS-Win D:\data\maingit\test\simple> new-item .gitignore目录: D:\data\maingit\test\simpleMode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2022/6/12 17:20 0 .gitignorePS-Win D:\data\maingit\test\simple> git add .\.gitignore
PS-Win D:\data\maingit\test\simple> git commit -m"add gitignore file"
[master b5a679f] add gitignore file1 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 .gitignore
PS-Win D:\data\maingit\test\simple> git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 263 bytes | 263.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To 82.156.125.196:/data/simple! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'root@82.156.125.196:/data/simple'
PS-Win D:\data\maingit\test\simple>
克隆之后正常的修改和提交都没有问题,但是 git push
的时候报错,原因提示 ! [remote rejected] master -> master (branch is currently checked out)
,提示当前的 master
分支是检出状态,不允许直接推送。
仔细想想就会有些思路,普通库实际上包含两份数据的,一份在 .git
目录中以object形式存在,一份在工作目录中以源文件形式存在,我们每次使用 git
命令,可以保证工作目录内文件和 .git
目录数据是一致的,但是如果将普通库作为远端时,在下游提交数据时,远端库中的 .git
目录会直接更新,但是工作区却不知道此时谁在用,不能直接更新覆盖,这就造成了数据不一致的情况。
如果非得使用普通库作为服务端仓库,那么可以参照上面报错的建议,在采用额外方式保证一致性的同时,修改服务端库的 receive.denyCurrentBranch
这个git配置项,或者将服务端分支切换到一个无人使用的分支上,这样下游端就可以直接推送了。
[root@VM-0-3-centos data]# cd simple/
[root@VM-0-3-centos simple]# git checkout -b unless
Switched to a new branch 'unless'
[root@VM-0-3-centos simple]# git branch -amaster
* unless
[root@VM-0-3-centos simple]#
PS-Win D:\data\maingit\test\simple> pwdPath
----
D:\data\maingit\test\simplePS-Win D:\data\maingit\test\simple> git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 263 bytes | 263.00 KiB/s, done.
Total 2 (delta 0), reused 0 (delta 0)
To 82.156.125.196:/data/simple9a9b255..b5a679f master -> master
PS-Win D:\data\maingit\test\simple>
自动化部署
利用 post-receive
进行自动化部署的原理就是,git
本身提供了一些脚本接口,在某些 git
操作发生时,会调用预定脚本执行命令,相当于给 git
用户开放了接口,我们可以修改 post-receive
脚本,在修改提交后自动部署最新内容,进一步实现自动化集成。
因为前面已经介绍了很多有关裸仓库的知识,接下来我只叙述操作步骤,看了之前的介绍,这部分内容应该没什么难度了。
需求
服务端建立裸仓库,在接收到新的提交时,自动将项目部署到/data/publish/game
目录下
操作步骤
服务端远端操作
建立裸仓库 /data/repo/game.git
,对应部署目录是 /data/publish/game
[root@VM-0-3-centos data]# mkdir -p /data/repo
[root@VM-0-3-centos data]# mkdir -p /data/publish/game
[root@VM-0-3-centos data]# cd repo/
[root@VM-0-3-centos repo]# git init --bare game.git
Initialized empty Git repository in /data/repo/game.git/
[root@VM-0-3-centos repo]#
新建 /data/repo/game.git/hooks/post-receive
脚本,可以拷贝 post-receive.sample
进行修改,脚本内编写内容如下:
# 指定部署目录
DIR=/data/publish/game
git --work-tree=${DIR} clean -fd
# 强制检出
git --work-tree=${DIR} checkout --force
# 运行启动脚本
cd ${DIR}
chmod 755 start.sh
./start.sh
客户端本地操作
本地项目普通库目录结构如下,启动脚本为 start.sh
:
albert@home-pc MINGW64 /d/data/maingit/test/game (master)
$ tree game/ -a
game/
├── .git
│ ├── COMMIT_EDITMSG
│ ├── config
│ ├── description
│ ├── HEAD
│ ├── hooks
│ │ ├── applypatch-msg.sample
│ │ ├── commit-msg.sample
│ │ ├── fsmonitor-watchman.sample
│ │ ├── post-update.sample
│ │ ├── pre-applypatch.sample
│ │ ├── pre-commit.sample
│ │ ├── pre-merge-commit.sample
│ │ ├── prepare-commit-msg.sample
│ │ ├── pre-push.sample
│ │ ├── pre-rebase.sample
│ │ ├── pre-receive.sample
│ │ └── update.sample
│ ├── index
│ ├── info
│ │ └── exclude
│ ├── logs
│ │ ├── HEAD
│ │ └── refs
│ │ └── heads
│ │ └── master
│ ├── objects
│ │ ├── 53
│ │ │ └── dd8b65afe02329eb73cbe142b9359ffd2c4c70
│ │ ├── 68
│ │ │ └── 31f81503989c192a10b47ecf48bc6bfe7c2cf4
│ │ ├── 81
│ │ │ └── aaa9093e1d32996c53766fa5f943e3ea6c79b0
│ │ ├── e6
│ │ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ │ ├── info
│ │ └── pack
│ └── refs
│ ├── heads
│ │ └── master
│ └── tags
├── README.md
└── start.sh16 directories, 27 files
albert@home-pc MINGW64 /d/data/maingit/test/game (master)
$ cat start.sh
cp README.md test.txt
与远端裸仓库建立关联
albert@home-pc MINGW64 /d/data/maingit/test/game (master)
$ git remote add origin root@82.156.125.196:/data/repo/game.gitalbert@home-pc MINGW64 /d/data/maingit/test/game (master)
$ git push -u origin master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (4/4), 286 bytes | 286.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0)
To 82.156.125.196:/data/repo/game.git* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
至此自动化部署环境已建立,当本地 game 仓库推送更新时,远端服务器会自动更新部署
快速回顾
文中主要命令收于此节,方便自己后期快速查找操作
- 服务端远程新建裸仓库
cd /data/repo
git init --bare game.git
- 本地库与远端库建立关联
git remote add origin root@82.156.125.196:/data/repo/game.git
- 新建或修改
hooks
目录下post-receive
脚本
DIR=/data/publish/game
git --work-tree=${DIR} clean -fd
git --work-tree=${DIR} checkout --force
cd ${DIR}
chmod 755 start.sh
./start.sh
总结
- 裸仓库是一个只包含提交记录,没有工作目录的仓库,适合用来做服务端远程仓库
- 裸仓库不能直接在仓库中执行修改文件的git命令,可以在客户端克隆之后修改之后再进行提交
- 自动化部署利用了git服务器提供的脚本接口,当新的推送达到时会调用
post-receive
脚本 - 配置自动化部署环境时需要注意,如果没有配置ssh免密码登陆,需要在push代码的时候输入密码
- 另外自动化部署时要注意各个文件及目录的权限,因为要运行脚本,要保证推送用户有足够的运行权限
==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==
每个人都有自己的选择,很多看似突如其来的决定,往往都是深思熟虑后的结果,每个人在自己的旅途中不断的分类、选择、分类、选择,无法逃离的坚持到最后一刻~
了解git裸仓库并利用post-receive自动化部署相关推荐
- Git裸仓库和非裸仓库
Git裸仓库创建 使用命令行:git init –bare 使用TortoiseGit:右键菜单git creat repo here,选择Make it Bare 裸仓库可以直接作为服务器仓库供各开 ...
- git 裸仓库的使用
创建裸仓库 git init --bare 初始化裸仓库,用于做为git服务端共享仓库 裸仓不能被clone,需要创建本地初始化一个真实的项目,再添加裸仓为远程推送地址,然后初始化代码推送到远程 mk ...
- Maven学习总结(48)——利用wagon-maven-plugin插件自动化部署Jar包/war包到Linux远程服务器
前言: Maven项目可使用mvn package指令打包,打包完成后包位于target目录下,要想在远程服务器上部署,首先要将包上传到服务器.程序开发完成后部署到线上Linux服务器,可能需要经历打 ...
- 删除 git 本地仓库
删除 git 本地仓库 1. git 本地仓库 2. 利用命令行删除 git 本地仓库 3. 删除成功 1. git 本地仓库 删除 Git 本地仓库的根本原理是删除"Git本地仓库&quo ...
- 【Git、GitHub、GitLab】五 git中裸仓库.git下的内容
上一篇文章学习了git的文件重命名与git -log 的系列命令的使用方法.点击链接查看上一篇文章:[Git.GitHub.GitLab]四 Git文件重命名的简单方法以及使用git log查看版本演 ...
- 远端仓库初始化成裸仓库 git init --bare
1 git init 和 git init –bare 的区别 用"git init"初始化的版本库用户也可以在该目录下执行所有git方面的操作.但别的用户在将更新push上来的 ...
- 利用Dropbox搭建Git远程仓库
Git是一款很好用的分布式版本管理工具,因为它是分布式的,所以跟SVN不同的是,即使离线也能执行版本发布(commit).代码回滚(reset)等操作,因此平时完全可以在脱机的环境下把它作为一个本地的 ...
- [Git] 裸代码仓库和镜像代码仓库全解
1.Git init和clone命令对bare和mirror参数的支持 git命令 –bare参数 –mirror参数 git init 支持 不支持 git clone 支持 支持 2.裸代码仓库与 ...
- 利用win10的Linux子系统在PC上搭建git远程仓库
在win10上搭建一个git远程仓库 在win10上安装ubuntu子系统 在控制面板中开启linux子系统 下载安装Ubuntu子系统 在Ubuntu子系统上安装配置git远程仓库 建立一个git仓 ...
- git克隆 不带目录_【第1823期】Git子仓库深入浅出
前言 前端早读课的朋友,2020年元旦快乐.今日早读文章由涂鸦大前端 @孟浩然投稿分享. 正文从这开始~ 在前端日常开发中,我们经常git来当做代码版本管理工具,使用中基本都是一个项目一个Git仓库的 ...
最新文章
- 手机扫一扫,现实物体隔空「复制粘贴」进电脑!北大校友的AI新研究,现在变成AR酷炫应用...
- iOS开发教程:Storyboard全解析-第二部分
- mysql32位主从复制安装包,MySQL安装-主从复制(5)
- java map统计学生名单_Java含自己的总结:集合,学生,遍历,ArrayList,Set,Map,泛型,班级,发牌—诗书画唱...
- Springboot,SSM框架的区别
- 计算机系统结构专业是什么专业,中国大学计算机系统结构专业排名
- 科大讯飞语音识别芯片_科大讯飞造家电专用语音芯片 市场机会在哪里?
- 字体系列之文字样式(CSS、HTML)
- XJOI一级五段题解(g++,即C++),也可视作C++算法竞赛教程
- 4类官网原型设计及模板奉上,助你创意泉涌!
- 深圳外包及不考虑公司名单
- 卿学姐与诡异村庄(并查集)
- Centos7安装普罗米修斯(Prometheus)监控
- missing external certificate的解决方案
- JavaScript基础知识笔记
- 开关电源的电流多大怎么选择
- dx12龙书 描述符根参数常量缓冲区
- 用DHCP实现交换机全网互ping(路由子接口)
- 计算机网络nsi,运行 NSI 服务 Svchost.exe 泄漏内存和非页面缓冲池内存泄漏标记 NSpc...
- Python后端工程师学习路线——大学版
热门文章
- 认识kata-containers
- android console服务,如何使能和关闭android设备上的console功能
- 一加6手机图片中的文字如何识别?
- github100天python_GitHub - jazeyoung/Python-100-Days: Python - 100天从新手到大师
- 南怀瑾讲述99个人生道理
- 如何快速转发csdn博客?
- xshell 执行脚本API介绍(附带xsh的python包)
- 20多岁的生活方式决定了你30岁的打开方式_演讲稿
- 进行淘宝商品比价的定向爬虫
- 真的有必要读研究生吗?