G

[Git] 普通仓库和bare仓库

RoLingG 其他 2025-12-22

Git普通仓库和bare仓库

普通仓库(Non-bare Repository)

特点:

  • 包含工作目录(Working Directory)
  • 包含 .git 子目录,存储版本历史
  • 可以进行常规的 Git 操作:add、commit、pull、push 等
  • 文件可以直接在文件系统中查看和编辑

结构:

project/
├── .git/          # Git 仓库数据
├── src/           # 工作目录中的文件
├── README.md
└── ...           # 其他项目文件

Bare 仓库(Bare Repository)

特点:

  • 没有工作目录,只有 Git 仓库数据
  • 通常用作中央仓库远程仓库
  • 不能直接编辑文件,只能接收 push 操作
  • 文件名以 .git 结尾(如 project.git

结构:

project.git/
├── HEAD
├── config
├── objects/
├── refs/
└── ...          # 只有 Git 内部文件,没有项目源文件

主要区别总结

特性普通仓库Bare 仓库
工作目录✅ 有❌ 无
直接编辑文件✅ 可以❌ 不可以
用作远程仓库❌ 不推荐✅ 推荐
接收 push❌ 默认不行✅ 可以
用途本地开发服务器/共享仓库

使用场景

普通仓库: 日常开发,在本地进行代码编写和版本控制

Bare 仓库:

  • Git 服务器上的中央仓库
  • 团队成员共享的远程仓库
  • GitHub/GitLab 等平台的仓库结构

创建方式

# 普通仓库
git init

# Bare 仓库
git init --bare

Bare 仓库的设计主要是为了避免冲突:因为没有工作目录,就不会出现有人在服务器上直接修改文件而导致 push 失败的情况。

所以 Github 这些托码平台,实际上就是远端给你建立了一个 裸(bare)仓库,你 clone 下来之后,实际上是经历了 下载阶段(网络传输)重建阶段(本地恢复)

clone 操作就是:

  1. 拿到图纸(下载bare数据)
  2. 按图纸盖房子(重建工作目录)
  3. 给你一套能住的房子(普通仓库)

额外

SSH

我们都知道 Github 上有 ssh 和 http 两种方式 clone 仓库,ssh 就和上面说的那样,Github 服务器上建立了对应的 bare 仓库给你,你能够根据 Github 给的 ssh 链接进行 clone:

git@github.com:<username>/<reposity_name>.git

我们这里看出来,git@github.com 这部分其实就是 <主机名>@<网络IP/域名>。这意味着我们其实创建远端同步仓库,其实也不需要使用托码平台(这貌似是句废话,毕竟本身托码平台就是 Git 的 GUI 便利化操作平台)。

我们可以通过本地虚拟机 + 云服务器进行实现对应操作。我们先在本地虚拟机上创建 ssh 用的公钥和私钥:

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""

然后把本地虚拟机生成的公钥复制给云服务,自己留有对应私钥,保证连接:

ssh-copy-id -i ~/.ssh/id_ed25519.pub ubuntu@cs.example.com

之后 ssh 连接测试一下是否成功就可以了:

ssh ubuntu@cs.example.com

之后我们在云服务器上建立一个 bare 仓库:

cd ~ && mkdir test
cd test
git init hello --bare

创建好之后我们就可以用本地虚拟机克隆该仓库了:

git clone ubuntu@cs.example.com:~/test/hello

运行完之后就会发现本地会多出一个名为 hello 的本地仓库了,这个仓库如之前说的,是遵循远端 bare 仓库生成的本地仓库,在这个仓库里面可以做正常的 Git 流程对应的操作,相当于建立了只供两个机子的单向小 Github

其实早期没有 Github 这些托码平台的时候,或者本地无对外网络需要互相本地协作,就会使用这样的方法进行合作,这也是 Git 早期的用法了吧。只是现在太方便了都没见过(

HTTP

至于 HTTP 的方式,相对来说比较复杂一些。

客户端把 Git 专用的 want/have 和 pack 数据直接塞进 HTTP/HTTPS POST 请求里,Web 服务器调用 git-http-backend(或 GitLab/Gitea 等内置路由) 解包/打包,鉴权靠 HTTP 401 + Token/Basic/OAuth,加密靠 TLS,下行、上行各一次 POST,完成拉取和推送——和 SSH 完全同级,只是跑在 HTTP 协议上

大概流程如下:

clone https://repo.git
  │
  ├─→ GET info/refs?service=git-upload-pack  (拿分支列表)
  ├─→ POST git-upload-pack                   (发 want/have → 收 pack)
  │
push https://repo.git
  │
  ├─→ GET info/refs?service=git-receive-pack (拿旧 ref)
  └─→ POST git-receive-pack                  (发 pack + update → 收结果)
PREV
[Golang] 1.25 encoding/json/v2更新

评论(0)

发布评论