git 普通库与裸库
创建一个 git 仓库的时候,有两种方式:
和
这两个有什么区别呢?
使用git init
创建的仓库被称为普通库,使用git init --bare
创建的库被称为裸库。
普通库不仅包含了版本控制信息,还含了项目所有的源文件,而裸库只包含了版本控制信息。
举例如下:
在/tmp 目录下创建一个普通库 test
查看文件:
结果:
查看.git 中的文件:
结果:
./ ../ branches/ config description HEAD hooks/ info/ objects/ refs/
复制代码
创建一个文件,加入版本控制,提交:(普通库是可以直接操作的)
cd /tmp/test
touch a
git add a
git commit -m "first commit"
复制代码
将仓库克隆到/tmp/test2
git clone skyfire@localhost:/tmp/test /tmp/test2
复制代码
在 test2 下建立一个新文件,加入版本控制,并且提交:
cd /tmp/test2
touch b
git add b
git commit -m "add b"
复制代码
尝试推送:
此时会报出如下错误:
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 226 bytes | 226.00 KiB/s, done.
Total 2 (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: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote:
remote: You can set the 'receive.denyCurrentBranch' configuration variable
remote: to 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote:
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To localhost:/tmp/test
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'skyfire@localhost:/tmp/test'
复制代码
因为 remote 仓库当前也在 master 分支,并且是可以直接操作的,所以如果此时向 remote 的当前分支 push 代码,可能会将正在修改的代码覆盖掉。因此只能向非当前分支 push 修改:
git branch dev
git push origin dev
复制代码
这样就可以正常 push 了。如果实在需要 push 到 master 怎么办呢?可以将远程的当前分支切换到非 master 分支:
cd /tmp/test
git checkout dev
cd /tmp/test2
git checkout master
git push origin master
复制代码
接下来说说裸库的情况。
先将刚才建立的仓库删除:
创建裸库:
查看文件:
结果:
./ ../ branches/ config description HEAD hooks/ info/ objects/ refs/
复制代码
可以看到,test 下的文件与普通库 test/.git 下的文件一样。
尝试建立一个文件,并将其加入版本控制:
此时会报错:
fatal: this operation must be run in a work tree
复制代码
说明裸库并不具备直接操作的能力。
将仓库克隆到/tmp/test2
git clone skyfire@localhost:/tmp/test /tmp/test2
复制代码
在 test2 下建立一个新文件,加入版本控制,并且提交:
cd /tmp/test2
touch b
git add b
git commit -m "add b"
复制代码
尝试推送:
推送成功。
总结
裸库与普通库的总结如下:
由版本控制文件组成,不能直接操作,可以在远端直接推送,通常用于多人协作,版本库放在远端服务器。
由源代码+裸库组成,可以直接操作,但是不能在远端直接推送代码到当前分支,通常用于本地版本控制。
评论