Git 本地倉(cāng)庫(kù)和裸倉(cāng)庫(kù)

通常我們會(huì)用 git init 命令來將我們所在的目錄轉(zhuǎn)換為一個(gè) Git 本地倉(cāng)庫(kù)或者初始化一個(gè)新的空倉(cāng)庫(kù)。

用法

  • 將當(dāng)前目錄轉(zhuǎn)換為一個(gè)本地倉(cāng)庫(kù)
git init

這個(gè)命令執(zhí)行后會(huì)在本地生成一個(gè) .git 的文件夾,用來追蹤倉(cāng)庫(kù)的所有變更。效果如下:

git init
  • 指定某個(gè)目錄成為本地倉(cāng)庫(kù)
git init <repo>

這個(gè)命令執(zhí)行后, 將創(chuàng)建一個(gè)名為repo且只包含 .git 子文件夾的空目錄。效果如下:

git init repo
  • 指定某個(gè)目錄成為中心倉(cāng)庫(kù)(裸倉(cāng)庫(kù))
git init --bare <?repo> 

這個(gè)命令執(zhí)行后,將在本地創(chuàng)建一個(gè)名為 repo 的文件夾, 里面包含著 Git ?的基本目錄, 我們一般會(huì)將這個(gè)文件夾命名為后面加 .git 的形式,如 repo.git (這也是為什么我們從 GitHub clone 倉(cāng)庫(kù)的時(shí)候,地址都是 xxx.git 這樣的形式的原因)。效果如下:

git init --bare repo.git

詳細(xì)說一下使用 --bare 參數(shù)的含義,使用 --bare 參數(shù)初始化的倉(cāng)庫(kù),我們一般稱之為裸倉(cāng)庫(kù), 因?yàn)檫@樣創(chuàng)建的倉(cāng)庫(kù)并不包含 工作區(qū) , 也就是說,我們并不能在這個(gè)目錄下執(zhí)行我們一般使用的 Git 命令。

對(duì)比

我們來對(duì)比一下直接使用 git init 創(chuàng)建的倉(cāng)庫(kù)和加了 --bare 參數(shù)的兩個(gè)倉(cāng)庫(kù)。 我們直接看兩個(gè)倉(cāng)庫(kù)的的 config 文件中的內(nèi)容:

  • 直接 git init 創(chuàng)建的倉(cāng)庫(kù):
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true

  • 加了 --bare 創(chuàng)建的裸倉(cāng)庫(kù):
[core]
    repositoryformatversion = 0
    filemode = true
    bare = true
    ignorecase = true
    precomposeunicode = true

可以看到最直觀的差異在于 bare 配置項(xiàng)是否為 true , 此外不加 --bare 創(chuàng)建的本地倉(cāng)庫(kù)配置中有一項(xiàng) logallrefupdates = true , 作用根據(jù)名字就可以看出來, 記錄所有的 ref (引用) 更新, 關(guān)于 ref 的部分之后有時(shí)間可以再寫,這個(gè)配置可以理解為是 Git 的一道防線。

功能差異

我們可以使用最簡(jiǎn)單的例子演示一下。


# 直接創(chuàng)建本地倉(cāng)庫(kù)
(Tao) ?  git init repo

# 創(chuàng)建裸倉(cāng)庫(kù)
(Tao) ?  git init --bare repo.git

# 分別 clone 兩個(gè)倉(cāng)庫(kù)
(Tao) ?  git clone repo c1
Cloning into 'c1'...
warning: You appear to have cloned an empty repository.
done.
(Tao) ?  git clone repo.git c2
Cloning into 'c2'...
warning: You appear to have cloned an empty repository.
done.

# 進(jìn)入 c1 倉(cāng)庫(kù)

(Tao) ?  cd c1
(Tao) ?  c1 git:(master) touch test
(Tao) ?  c1 git:(master) ? g add -A
(Tao) ?  c1 git:(master) ? g commit -m "test commit"
[master (root-commit) b1e32ad] test commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test
(Tao) ?  c1 git:(master) git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 200 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 /Users/tao/repo
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to '/Users/tao/repo'

# 進(jìn)入 c2 倉(cāng)庫(kù)重復(fù)執(zhí)行

(Tao) ?  c1 git:(master) cd ../c2
(Tao) ?  c2 git:(master) touch test
(Tao) ?  c2 git:(master) ? git add -A
(Tao) ?  c2 git:(master) ? git commit -m "test commit"
[master (root-commit) 7aacc58] test commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test
(Tao) ?  c2 git:(master) git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 201 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /Users/tao/repo.git
 * [new branch]      master -> master

從裸倉(cāng)庫(kù) clone 下來的本地倉(cāng)庫(kù)可以進(jìn)行正常的 push 操作, 但是從一般倉(cāng)庫(kù) clone 下來的本地倉(cāng)庫(kù)卻不行。 這也正是裸倉(cāng)庫(kù)存在的意義。 裸倉(cāng)庫(kù)一般情況下是作為遠(yuǎn)端的中心倉(cāng)庫(kù)而存在的。

總結(jié)

使用 git init --bare <repo> 可以創(chuàng)建一個(gè)裸倉(cāng)庫(kù),并且這個(gè)倉(cāng)庫(kù)是可以被正常 clonepush 更新的, 裸倉(cāng)庫(kù)不包含工作區(qū),所以并不會(huì)存在在裸倉(cāng)庫(kù)上直接提交變更的情況。


可以通過下面二維碼訂閱我的文章公眾號(hào)【MoeLove】

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容