文章目录

  • 前言
  • 普通库和裸仓库
    • 普通库
    • 裸仓库
  • 使用裸仓库
    • 使用 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 addgit 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自动化部署相关推荐

  1. Git裸仓库和非裸仓库

    Git裸仓库创建 使用命令行:git init –bare 使用TortoiseGit:右键菜单git creat repo here,选择Make it Bare 裸仓库可以直接作为服务器仓库供各开 ...

  2. git 裸仓库的使用

    创建裸仓库 git init --bare 初始化裸仓库,用于做为git服务端共享仓库 裸仓不能被clone,需要创建本地初始化一个真实的项目,再添加裸仓为远程推送地址,然后初始化代码推送到远程 mk ...

  3. Maven学习总结(48)——利用wagon-maven-plugin插件自动化部署Jar包/war包到Linux远程服务器

    前言: Maven项目可使用mvn package指令打包,打包完成后包位于target目录下,要想在远程服务器上部署,首先要将包上传到服务器.程序开发完成后部署到线上Linux服务器,可能需要经历打 ...

  4. 删除 git 本地仓库

    删除 git 本地仓库 1. git 本地仓库 2. 利用命令行删除 git 本地仓库 3. 删除成功 1. git 本地仓库 删除 Git 本地仓库的根本原理是删除"Git本地仓库&quo ...

  5. 【Git、GitHub、GitLab】五 git中裸仓库.git下的内容

    上一篇文章学习了git的文件重命名与git -log 的系列命令的使用方法.点击链接查看上一篇文章:[Git.GitHub.GitLab]四 Git文件重命名的简单方法以及使用git log查看版本演 ...

  6. 远端仓库初始化成裸仓库 git init --bare

    1 git init  和 git init –bare 的区别 用"git init"初始化的版本库用户也可以在该目录下执行所有git方面的操作.但别的用户在将更新push上来的 ...

  7. 利用Dropbox搭建Git远程仓库

    Git是一款很好用的分布式版本管理工具,因为它是分布式的,所以跟SVN不同的是,即使离线也能执行版本发布(commit).代码回滚(reset)等操作,因此平时完全可以在脱机的环境下把它作为一个本地的 ...

  8. [Git] 裸代码仓库和镜像代码仓库全解

    1.Git init和clone命令对bare和mirror参数的支持 git命令 –bare参数 –mirror参数 git init 支持 不支持 git clone 支持 支持 2.裸代码仓库与 ...

  9. 利用win10的Linux子系统在PC上搭建git远程仓库

    在win10上搭建一个git远程仓库 在win10上安装ubuntu子系统 在控制面板中开启linux子系统 下载安装Ubuntu子系统 在Ubuntu子系统上安装配置git远程仓库 建立一个git仓 ...

  10. git克隆 不带目录_【第1823期】Git子仓库深入浅出

    前言 前端早读课的朋友,2020年元旦快乐.今日早读文章由涂鸦大前端 @孟浩然投稿分享. 正文从这开始~ 在前端日常开发中,我们经常git来当做代码版本管理工具,使用中基本都是一个项目一个Git仓库的 ...

最新文章

  1. 手机扫一扫,现实物体隔空「复制粘贴」进电脑!北大校友的AI新研究,现在变成AR酷炫应用...
  2. iOS开发教程:Storyboard全解析-第二部分
  3. mysql32位主从复制安装包,MySQL安装-主从复制(5)
  4. java map统计学生名单_Java含自己的总结:集合,学生,遍历,ArrayList,Set,Map,泛型,班级,发牌—诗书画唱...
  5. Springboot,SSM框架的区别
  6. 计算机系统结构专业是什么专业,中国大学计算机系统结构专业排名
  7. 科大讯飞语音识别芯片_科大讯飞造家电专用语音芯片 市场机会在哪里?
  8. 字体系列之文字样式(CSS、HTML)
  9. XJOI一级五段题解(g++,即C++),也可视作C++算法竞赛教程
  10. 4类官网原型设计及模板奉上,助你创意泉涌!
  11. 深圳外包及不考虑公司名单
  12. 卿学姐与诡异村庄(并查集)
  13. Centos7安装普罗米修斯(Prometheus)监控
  14. missing external certificate的解决方案
  15. JavaScript基础知识笔记
  16. 开关电源的电流多大怎么选择
  17. dx12龙书 描述符根参数常量缓冲区
  18. 用DHCP实现交换机全网互ping(路由子接口)
  19. 计算机网络nsi,运行 NSI 服务 Svchost.exe 泄漏内存和非页面缓冲池内存泄漏标记 NSpc...
  20. Python后端工程师学习路线——大学版

热门文章

  1. 认识kata-containers
  2. android console服务,如何使能和关闭android设备上的console功能
  3. 一加6手机图片中的文字如何识别?
  4. github100天python_GitHub - jazeyoung/Python-100-Days: Python - 100天从新手到大师
  5. 南怀瑾讲述99个人生道理
  6. 如何快速转发csdn博客?
  7. xshell 执行脚本API介绍(附带xsh的python包)
  8. 20多岁的生活方式决定了你30岁的打开方式_演讲稿
  9. 进行淘宝商品比价的定向爬虫
  10. 真的有必要读研究生吗?