git裸存储库有什么用?

时间:2018-03-17 10:54:37

标签: git git-bare

在远程计算机上,我使用以下命令创建一个裸存储库:

git init --bare $HOME/bare/My-Repo

在我的本地计算机上,我克隆了一个repo(但是不是我在远程计算机上创建的那个):

git clone ssh://something.com/My-Repo

在我的本地计算机上,在我刚刚克隆的存储库中,我创建了一个"引用"到上面提到的位于远程机器上的裸存储库:

git remote add my_remote ssh://remote.com/${USER}/bare/My-Repo

我不知道它是否与我的问题相关,但我也在我的本地存储库中执行以下操作:

git config remote.my_remote /some/path/git-receive-pack
git config remote.my_remote /some/path/git-upload-pack

现在,我可以从本地存储库推送到远程计算机上的裸存储库:

git push my_remote master

现在,我们的想法是在远程计算机上创建另一个存储库,该存储库应该从裸存储库中获取一些内容。我通过在远程计算机上执行类似的操作来创建此repo:

some_script.sh $HOME/bare/My-Repo $HOME/My-Repo

现在,我对远程计算机上的$HOME/My-Repo进行了一些更改(请注意,它不是存储库),然后是我git add和{{1然后我推动:

git commit

结果我推送到裸存储库(位于同一台远程计算机上)。之后我去了我的本地机器"采取"来自远程计算机的更改(来自裸存储库):

git push origin my-dev-branch

所以,我的问题是:为什么我们需要这个裸存储库?为什么我们只能拥有一个远程存储库并直接在本地存储库和远程存储库之间交换内容?或者,为什么我们只能git fetch my_remote git checkout -b my-dev-branch my_remote/my-dev-branch git fetch origin git rebase origin/master (或rsync)本地存储库进出远程计算机?

ADDED

这就是为什么我问问题而不是谷歌搜索。我用谷歌搜索了我的问题,第一个链接在这里:http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/

我在那里读到:

  

使用git init命令创建的存储库称为工作   目录。在存储库的顶级文件夹中,您将找到   两件事情:   一个.git子文件夹,包含你的所有git相关的修订历史记录   repo工作树,或签出项目文件的副本。   使用git init --bare创建的存储库称为裸存储库。他们   结构与工作目录略有不同。首先,   它们不包含源文件的工作或签出副本。和   第二,裸repos存储git修订根目录中的repo历史   存储库的文件夹而不是.git子文件夹。注意......裸露   存储库通常被赋予.git扩展名。

所以,现在要明白我需要知道:

  1. 什么是"修订历史"?
  2. 什么是"工作树"?
  3. 什么是"签出副本"?
  4. 这只是第一部分。我知道,响应将是:去阅读git教程或git简介。好吧,我做到了。它的第一个问题是术语的使用是"循环"。 A个术语用术语B表示,术语B用术语A表示。其次,我没有时间阅读一本书只是为了找到我的问题的答案。第三,我100%确定我的问题的答案可以用简单的术语表达。这实际上是微不足道的。

1 个答案:

答案 0 :(得分:3)

如果我理解正确,你的主要问题归结为:为什么我们需要一个中间裸存储库来同步两个Git存储库?

在您的具体示例中,您有一个本地Git存储库,我们称之为X,两个远程存储库,一个裸设备称为B,非裸设备,让我们称之为Y.

此时我希望你看到X和Y可以在任何地方。它们既可以是本地的,也可以是远程的,在与B相同的服务器上。无论它们在哪里,重要的是你想要在它们之间进行同步,为此你需要B,在某个地方,任何地方。你的问题是为什么

首先,你实际上并不是需要 B.这是推荐的,默认行为将指导您朝这个方向发展。

为什么建议在存储库之间使用裸仓库? 答案与工作树有关。 工作树是您拥有所处理文件的地方。 工作树的Git存储库位于.git子目录中。 您在工作树中执行的Git命令与Git存储库通信,查询其内容,并与工作树中的内容进行比较。 裸存储库就像.git目录一样,没有工作树。

要揭开裸存储库的神秘面纱,试试这个以查看裸存储库和非存储存储库之间的区别:

$ cd /tmp/
$ git init --bare bare.git
Initialized empty Git repository in /private/tmp/bare.git/
$ git init regular
Initialized empty Git repository in /private/tmp/regular/.git/
$ diff -r bare.git/ regular/.git/
diff -r bare.git/config regular/.git/config
4c4,5
<   bare = true
---
>   bare = false
>   logallrefupdates = true

从技术上讲,区别在于几个配置标志。 我可以将bare.git目录移动到文件系统中的任何目录,将其重命名为.git,编辑config文件,然后我会将裸存储库转换为常规存储库。

回到问题:为什么建议在两个想要彼此同步的非裸存储库之间建立一个裸存储库? 默认情况下,Git禁止推送到非裸存储库。 如果没有怎么办? 如果git push将更新远程.git的内容, 对应的工作树会发生什么? 接下来会有很多问题:

  • 工作树的当前分支是什么?如果推送没有改变那个分支,那么一切都很好。
  • 如果推送影响工作树的当前分支会发生什么? Git应该更新工作树吗?
    • 如果工作树不干净,则无法安全更新。未提交的更改可能会丢失。
    • 即使工作树是干净的,如果对.gitignore进行了更改,或者如果使用强制推送重写了分支的历史记录,则可能会发生冲突。
    • 如果我们不更新工作树,它将与存储库不同步,因此git status将报告不应提交的修改。

这听起来复杂而令人困惑吗?那是因为它是。 这就是为什么默认情况下不允许推送到非裸存储库的原因。如果您真的想要,can可以做到这一点,如果您始终保持清理您推送的仓库的工作树,那么可以是合理安全的,但它会容易出错(您可能会忘了),没有人需要这样的不确定性和精神负担。最好只在中间使用裸存储库。