git本地仓库和裸仓库

➡️git 初始化

1
2
3
4
git init #git目录初始化
git init <repo> #本地初始化,并且建立一个名为repo的空仓库
git init --bare #git裸仓库初始化
git init --bare <repo> #指定某个目录成为中心仓库(裸仓库)

git init这个命令执行后会在本地生成一个 .git 的文件夹,用来追踪仓库的所有变更。
--bare: 使用 --bare 参数初始化的仓库,我们一般称之为裸仓库, 因为这样创建的仓库并不包含 工作区 , 也就是说,我们并不能在这个目录下执行我们一般使用的 Git 命令。

➡️对比
  • 直接 git init 创建的仓库:
1
2
3
4
5
6
7
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
  • 加了--bare创建的裸仓库:
1
2
3
4
5
6
[core]
repositoryformatversion = 0
filemode = true
bare = true
ignorecase = true
precomposeunicode = true

可以看到最直观的差异在于bare配置项是否为true, 此外不加--bare创建的本地仓库配置中有一项logallrefupdates = true, 作用根据名字就可以看出来, 记录所有的ref(引用) 更新, 关于ref的部分之后有时间可以再写,这个配置可以理解为是 Git 的一道防线。

➡️功能差异

我们可以使用最简单的例子演示一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 直接创建本地仓库
git ➤ git init repo
# 创建裸仓库
git ➤ git init --bare repo.git
# 分别 clone 两个仓库
git ➤ git clone repo test1
正克隆到 'test1'...
warning: 您似乎克隆了一个空版本库。
完成。
git ➤ git clone repo.git test2
正克隆到 'test2'...
warning: 您似乎克隆了一个空版本库。
完成。
git ➤

# 进入 test1 仓库
git ➤ cd test1
test1 ➤ touch test git:master
test1 ➤ git add . git:master*
test1 ➤ git commit -m '测试提交' git:master*
[master(根提交) 456cf23] 测试提交
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test
test1 ➤ git push origin master git:master
Counting objects: 3, done.
Writing objects: 100% (3/3), 217 bytes | 0 bytes/s, done.
Total 3 (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 /home/git/repo
! [remote rejected] master -> master (branch is currently checked out)
error: 无法推送一些引用到 '/home/git/repo'

# 进入 test2 仓库重复执行
test1 ➤ cd ../test2 git:master
test2 ➤ touch test git:master
test2 ➤ git add . git:master*
test2 ➤ git commit -m '再次测试提交' git:master*
[master(根提交) c56efe8] 再次测试提交
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test
test2 ➤ git push origin master git:master
Counting objects: 3, done.
Writing objects: 100% (3/3), 223 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/git/repo.git
* [new branch] master -> master
test2 ➤

从裸仓库中clone下来的本地仓库可以正常的push操作,这也正是裸仓库的存在意义

原文链接:
Git 本地仓库和裸仓库