Git裸仓库有什么用途?

3
在远程机器上,我使用以下命令创建一个裸仓库:
git init --bare $HOME/bare/My-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

现在的想法是在远程机器上创建另一个仓库,该仓库应从裸仓库中获取一些内容。我通过在远程机器上执行以下命令来创建此仓库:

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

现在,我在远程机器上的$HOME/My-Repo做了一些更改(请注意,这不是裸库),然后我进行了git addgit 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(或 scp)将本地仓库复制到远程机器上并从远程机器上复制回来? 补充说明 这就是为什么我提出问题而不是搜索的原因。我已经搜索了我的问题,第一个链接在这里:http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/ 我在那里读到:
用 git init 命令创建的仓库称为工作目录。在仓库的顶级文件夹中,您会发现两件事情:
- 一个 .git 子文件夹,其中包含您的仓库的所有 git 相关修订历史记录 - 工作树,或已检出的项目文件的副本。
用 git init --bare 命令创建的仓库称为裸仓库。它们与工作目录略有不同。首先,它们不包含源文件的任何工作或已检出的副本。其次,裸仓库将您的仓库的 git 修订历史记录存储在仓库的根文件夹中,而不是在 .git 子文件夹中。注意…裸仓库通常带有 .git 扩展名。
因此,现在要理解这一点,我需要知道:
1. "修订历史记录" 是什么? 2. "工作树" 是什么? 3. "已检出的副本" 是什么?
这只是第一部分。我知道,回答会是:去读 git 教程或 git 简介。好吧,我做到了。它的第一个问题是术语的使用是“循环”的。A 通过 B 表达,B 又通过 A 表达。其次,我没有时间读一本书来找到我的问题的答案。第三,我百分之百肯定,我的问题的答案可以用简单的术语表达。实际上,这是微不足道的。

3
我提出的有关Git的问题几乎都被关闭和投票否决,但其他主题的问题就没有这种情况。问有关Git的问题是件坏事吗?使用教程阅读Git相关内容比提问更好吗?虽然有很多教程,但我理解不了它们,可能是因为我不够聪明,无法掌握Git极其复杂的概念。 - Roman
1
“询问git是一件坏事吗?” - 不,有许多备受好评的[标签:git]问题。但这个问题非常广泛;你在第一个草稿中就提出了三个问题。鉴于你不知道答案,不清楚为什么你确定它是微不足道的,并且正如你所指出的,有一些相关的概念需要理解。已经有许多现有的资源,如果你“没有时间”,那么在提问之前你没有进行必要的研究。例如,你是否查看了https://dev59.com/ZWsz5IYBdhLWcg3w0rZC? - jonrsharpe
@jonrsharpe,你提供的链接问题与我的不同。那里的用户询问如何推送到裸仓库。而我知道如何做到这一点。 - Roman
我并没有说这是重复的,我也不会投票关闭。但那里的答案确实谈到了裸仓库是什么,我的观点仍然是有现有资源可供使用。如果你没有时间进行初步研究,就不应该期望别人花时间为你综合。例如,请参见 https://meta.stackoverflow.com/q/261592/3001761 - jonrsharpe
@jonrsharpe,我从未说过我没有时间进行初步研究,我只是说现在没有时间阅读完整的教程或甚至介绍。无论如何,这可以应用于任何问题:为什么你要问问题?难道你没有时间自己找答案吗?为什么你期望别人浪费时间来回答你的问题? - Roman
1个回答

8
如果我理解正确,你的主要问题归结为:为什么需要一个中介裸仓库在两个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 将报告不应提交的修改。
这听起来很复杂和混乱,这也是为什么默认情况下不允许向非裸库推送的原因。如果你真的想做到,你 可以 这样做,如果你始终保持清洁的工作树,它可能是相当安全的,但它容易出错(你可能会忘记),没有人需要这样的不确定性和心理负担。最好只使用一个裸库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接