git init
和git init --bare
有什么不同?我发现很多博客要求在Git服务器上使用--bare
。
从手册页面中可以看到:
--bare
创建一个裸仓库。如果GIT_DIR环境变量未设置,则设置为当前工作目录。
但实际上它意味着什么?在Git服务器设置中是否需要使用
--bare
?
git init
和git init --bare
有什么不同?我发现很多博客要求在Git服务器上使用--bare
。
从手册页面中可以看到:
--bare
创建一个裸仓库。如果GIT_DIR环境变量未设置,则设置为当前工作目录。
但实际上它意味着什么?在Git服务器设置中是否需要使用
--bare
?
这个选项会创建一个带有工作目录的仓库,你可以在其中进行操作(git clone
)。创建后,你会看到该目录下包含一个.git
文件夹,其中存放着历史记录和所有的Git基础架构。你的操作都在.git
所在的级别进行。
而另一个选项则会创建一个没有工作目录的仓库(git clone --bare
),你无法在其中进行操作。该目录中的所有内容都与上面情况下的.git
文件夹中的内容相同。
需要不带工作目录的Git仓库是因为你可以将分支推送到其中,它不关心其他人正在干什么。你仍然可以向非空仓库推送,但可能会被拒绝,因为你可能会移动某些人正在工作的分支。
因此,在没有工作目录的项目中,你只能看到Git存储对象的方式。它们被压缩和序列化,并以其内容的SHA1哈希值来存储。要在空仓库中获取一个对象,你需要使用git show
命令并指定你想要查看的对象的SHA1哈希值。你将无法看到像你的项目所显示的结构。
空仓库通常是中央仓库,所有人都将自己的工作推送到其中。不需要直接操作实际的工作内容。它是在多个人之间同步努力的一种方式。你将无法直接看到你的项目文件。
如果你是唯一在项目上工作的人,或者不需要“逻辑中央”仓库,则可能不需要任何空仓库。在这种情况下,可以从其他仓库中使用git pull
命令进行更新。这可以避免Git在向非空仓库推送时产生的问题。
裸仓库是一个没有工作拷贝的git仓库,因此.git文件夹中的内容对于该目录来说是顶层的。
使用非裸仓库在本地工作,使用裸仓库作为中央服务器/中心集线器与他人共享变更。例如,当你在github.com上创建一个仓库时,它会被创建为一个裸仓库。
所以,在你的电脑上:
git init
touch README
git add README
git commit -m "initial commit"
在服务器上:
cd /srv/git/project
git init --bare
然后在客户端上,你执行推送操作:
git push username@server:/srv/git/project master
您可以通过将其作为远程仓库添加来避免输入该命令。
服务器端的存储库将通过 pull 和 push 获得提交,而不是您在服务器机器上编辑文件然后进行提交,因此它是一个裸库。
您可以推送到非裸存储库,Git 会发现那里有一个 .git 存储库,但由于大多数“中心”存储库不需要工作副本,因此通常使用裸存储库,并且建议使用这种类型的存储库没有必要拥有工作副本。
但是,如果您向非裸存储库推送,则会使工作副本不一致,并且 Git 会发出警告:
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'.
你可以忽略这个警告。但是推荐的设置是:使用非裸库在本地工作,并使用裸库作为中央服务器或中心服务器进行推送和拉取。
如果您想直接与其他开发人员的工作副本共享工作,可以从彼此的存储库中拉取而不是推送。
默认的 Git 存储库假定您将使用它作为工作目录。通常,在服务器上,您不需要工作目录,只需要存储库。在这种情况下,您应该使用 --bare
选项。
git init
时创建的就是非裸库,或者当你从服务器克隆(没有使用bare
选项)时得到的也是非裸库。.git
的隐藏目录中。.git
中的Git数据。 裸库恰好是.git
目录,没有用于修改和提交文件的工作区域。.git
目录中拥有所需的所有信息来创建你的工作副本。git init --bare
创建了第一个存储库(名称:git-bare)。它是服务器。它在左侧,没有远程分支,因为这是远程存储库本身。git clone
从第一个存储库创建了第二个存储库(名称:git-working-tree)。它在右侧。它具有与远程分支链接的本地分支。git push --delete origin greek)和在git-working-tree本地(命令: git branch -D greek)。 树的外观如下:
< p > git-bare 仓库会删除分支和所有引用的提交。在图片中,我们可以看到由于这个原因,它的树被减少了。
另一方面, git-working-tree 仓库相当于一个常用的本地仓库,不会删除提交,现在只能通过哈希直接引用,使用 git checkout 7fa897b7
命令。这就是为什么它的树没有修改后的结构。
简而言之:在工作树仓库中永远不会丢弃提交,在bare仓库中会删除提交。
在实际操作中,如果服务器上存在本地仓库,则只能从本地仓库恢复已删除的分支。
但很奇怪的是,bare 仓库在删除远程分支后,磁盘大小并不会减小。也就是说,文件还在某种程度上存在。要通过删除不再引用或永远无法引用的内容(后一种情况)来卸载仓库,请使用 git gc --prune
命令。