git init與git init --bare

今天在創(chuàng)建git倉庫時,想到了加不加--bare參數(shù)的問題,之前印象中知道是有區(qū)別的,具體區(qū)別在哪一時還真說不清了,這篇文章就總結(jié)一下。

差分對比

首先,這兩個命令都是初始化一個空的git倉庫,分別用這兩個命令創(chuàng)建兩個示例分析一下:

$ git init repo
$ tree -a repo
repo
└── .git
    ├── branches
    ├── config
    ├── description
    ├── HEAD
    ├── hooks
    │   ├── applypatch-msg.sample
    │   ├── commit-msg.sample
    │   ├── fsmonitor-watchman.sample
    │   ├── post-update.sample
    │   ├── pre-applypatch.sample
    │   ├── pre-commit.sample
    │   ├── prepare-commit-msg.sample
    │   ├── pre-push.sample
    │   ├── pre-rebase.sample
    │   ├── pre-receive.sample
    │   └── update.sample
    ├── info
    │   └── exclude
    ├── objects
    │   ├── info
    │   └── pack
    └── refs
        ├── heads
        └── tags

10 directories, 15 files

$ git init --bare repo.git
$ tree -a repo.git 
repo.git
├── branches
├── config
├── description
├── HEAD
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── prepare-commit-msg.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   └── update.sample
├── info
│   └── exclude
├── objects
│   ├── info
│   └── pack
├── readme
└── refs
    ├── heads
    └── tags

9 directories, 16 files

可以看到,初始化后的目錄結(jié)構(gòu)是不一樣的,加了bare參數(shù)后不會在根目錄創(chuàng)建.git文件夾,而把.git下面的文件直接拿到根目錄里來了。再來看一下配置上有什么不同:

$ cd repo; git config --list | grep core
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true

$ cd repo.git; git config --list | grep core
core.repositoryformatversion=0
core.filemode=true
core.bare=true

可以看到有兩項配置不一樣,從字面意思也基本能猜到代表什么意思。

功能差異

加bare參數(shù)創(chuàng)建的倉庫(repo.git)一般叫“裸倉庫”,里面沒有工作區(qū)的概念,即你不能直接在這樣的倉庫里進(jìn)行正常的git命令操作;反之,不加bare參數(shù)創(chuàng)建的倉庫(repo)就可以直接在上面進(jìn)行g(shù)it操作。如果是這樣的話,那“裸倉庫”還有什么用呢?我們先來看兩個示例,分別clone上面創(chuàng)建的兩個倉庫,然后修改、提交并push到遠(yuǎn)程倉庫:

$ git clone repo c_1

$ cd c_1; touch test.txt; git add -A; g commit -m "test commit"
$ git push origin master
對象計數(shù)中: 3, 完成.
寫入對象中: 100% (3/3), 205 bytes | 205.00 KiB/s, 完成.
Total 3 (delta 0), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: 默認(rèn)禁止更新非純倉庫的當(dāng)前分支,因為您推送的內(nèi)容將導(dǎo)致索引和工作區(qū)
remote: 不一致,并且將需要執(zhí)行 'git reset --hard' 將工作區(qū)匹配到 HEAD。
remote: 
remote: 您可以在遠(yuǎn)程倉庫中設(shè)置 'receive.denyCurrentBranch' 配置變量為
remote: 'ignore' 或 'warn' 以允許推送到當(dāng)前分支。然而不推薦這么做,除非您
remote: 用某種方式將其工作區(qū)更新至您推送的狀態(tài)。
remote: 
remote: 若要屏蔽此信息且保持默認(rèn)行為,設(shè)置 'receive.denyCurrentBranch'
remote: 配置變量為 'refuse'。
To /home/evan/ARM/repo
 ! [remote rejected] master -> master (branch is currently checked out)
error: 無法推送一些引用到 '/home/evan/ARM/repo'

可以發(fā)現(xiàn),并不能推送修改到“非裸倉庫”,提示里也給出了說明。再來試試裸倉庫的情況:

$ git clone repo.git c_2
$ cd c_2; touch test.txt; git add -A; g commit -m "test commit"
$ git push origin master
對象計數(shù)中: 3, 完成.
寫入對象中: 100% (3/3), 204 bytes | 204.00 KiB/s, 完成.
Total 3 (delta 0), reused 0 (delta 0)
To /home/evan/ARM/repo.git
 * [new branch]      master -> master

推送修改到“裸倉庫”就一切正常,這也正是裸倉庫存在的意義, 裸倉庫一般情況下僅作為遠(yuǎn)程倉庫使用。個人理解,這樣主要是為了維護(hù)遠(yuǎn)程倉庫的“干凈”,考慮這個場景,如果有人在遠(yuǎn)程倉庫做了git操作,而你往上提交推送的時候必然會產(chǎn)生很多不必要的沖突。而將遠(yuǎn)程倉庫賦予bare屬性,大家沿著同一個準(zhǔn)線往上提交推送,管理起來就方便多了。所以,我們在GitHub等這樣的網(wǎng)站上看到的項目都是bare倉庫。

總結(jié)

使用git init --bare “repo”可以創(chuàng)建一個裸倉庫,并且這個倉庫是可以被正常clone和push的,裸倉庫不包含工作區(qū),所以不能在裸倉庫上直接提交變更。

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

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

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