Git 本地倉庫和裸倉庫

一般咱們會用 git init 命令來將咱們所在的目錄轉換爲一個 Git 本地倉庫或者初始化一個新的空倉庫。git

用法

  • 將當前目錄轉換爲一個本地倉庫bash

git init

這個命令執行後會在本地生成一個 .git 的文件夾,用來追蹤倉庫的全部變動。效果以下:app

git init

  • 指定某個目錄成爲本地倉庫less

git init <repo>

這個命令執行後, 將建立一個名爲repo且只包含 .git 子文件夾的空目錄。效果以下:ui

git init repo

  • 指定某個目錄成爲中心倉庫(裸倉庫)this

git init --bare <repo>

這個命令執行後,將在本地建立一個名爲 repo 的文件夾, 裏面包含着 Git 的基本目錄, 咱們通常會將這個文件夾命名爲後面加 .git 的形式,如 repo.git (這也是爲何咱們從 GitHub clone 倉庫的時候,地址都是 xxx.git 這樣的形式的緣由)。效果以下:spa

git init --bare repo.git

詳細說一下使用 --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> 能夠建立一個裸倉庫,而且這個倉庫是能夠被正常 clonepush 更新的, 裸倉庫不包含工做區,因此並不會存在在裸倉庫上直接提交變動的狀況。


能夠經過公衆號 TheMoeLove 和我聯繫

TheMoeLove

相關文章
相關標籤/搜索