一般咱們會用 git init
命令來將咱們所在的目錄轉換爲一個 Git 本地倉庫或者初始化一個新的空倉庫。git
將當前目錄轉換爲一個本地倉庫bash
git init
這個命令執行後會在本地生成一個 .git
的文件夾,用來追蹤倉庫的全部變動。效果以下:app
指定某個目錄成爲本地倉庫less
git init <repo>
這個命令執行後, 將建立一個名爲repo且只包含 .git
子文件夾的空目錄。效果以下:ui
指定某個目錄成爲中心倉庫(裸倉庫)this
git init --bare <repo>
這個命令執行後,將在本地建立一個名爲 repo 的文件夾, 裏面包含着 Git 的基本目錄, 咱們通常會將這個文件夾命名爲後面加 .git
的形式,如 repo.git
(這也是爲何咱們從 GitHub clone 倉庫的時候,地址都是 xxx.git 這樣的形式的緣由)。效果以下:spa
詳細說一下使用 --bare
參數的含義,使用 --bare
參數初始化的倉庫,咱們通常稱之爲裸倉庫, 由於這樣建立的倉庫並不包含 工做區
, 也就是說,咱們並不能在這個目錄下執行咱們通常使用的 Git 命令。code
咱們來對比一下直接使用 git init
建立的倉庫和加了 --bare
參數的兩個倉庫。 咱們直接看兩個倉庫的的 config
文件中的內容:orm
直接 git init
建立的倉庫:blog
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true
加了 --bare
建立的裸倉庫:
[core] repositoryformatversion = 0 filemode = true bare = true ignorecase = true precomposeunicode = true
能夠看到最直觀的差別在於 bare
配置項是否爲 true
, 此外不加 --bare
建立的本地倉庫配置中有一項 logallrefupdates = true
, 做用根據名字就能夠看出來, 記錄全部的 ref
(引用) 更新, 關於 ref 的部分以後有時間能夠再寫,這個配置能夠理解爲是 Git 的一道防線。
咱們可使用最簡單的例子演示一下。
# 直接建立本地倉庫 (Tao) ➜ git init repo # 建立裸倉庫 (Tao) ➜ git init --bare repo.git # 分別 clone 兩個倉庫 (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. # 進入 c1 倉庫 (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' # 進入 c2 倉庫重複執行 (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
從裸倉庫 clone 下來的本地倉庫能夠進行正常的 push
操做, 可是從通常倉庫 clone 下來的本地倉庫卻不行。 這也正是裸倉庫存在的意義。 裸倉庫通常狀況下是做爲遠端的中心倉庫而存在的。
使用 git init --bare <repo>
能夠建立一個裸倉庫,而且這個倉庫是能夠被正常 clone
和 push
更新的, 裸倉庫不包含工做區,因此並不會存在在裸倉庫上直接提交變動的狀況。
能夠經過公衆號 TheMoeLove 和我聯繫