为什么我不能推送到非裸存储库的签出分支?

问题描述 投票:3回答:2

我对我创建的场景很困惑。我在Github上创建了一个存储库(让我们称之为A)并将代码推送到它。之后,我将该存储库克隆到我的本地(让我们称之为B),这样我本地的来源就是远程回购A.

现在我从我的本地B克隆来创建另一个本地实例C.现在我有远程起源的C作为repo B而C的上游是A.

A → B → C

这类似于分叉,但在这里我在客户端而不是服务器端创建了克隆。

现在,如果我尝试使用从C到其原点B的推送:

git push origin 

然后我收到一个错误,指出我无法推送到非裸存储库。我知道推送到非裸存储库可能会导致本地远程不存在的提交丢失。

但是,这种情况与我将代码从B推送到A的情况类似吗?

我很困惑,如果B到A是可能的,那么为什么C到B.

为了合并到A,我们可以推送到上游:

git push upstream
git github dvcs git-bare git-non-bare-repository
2个回答
7
投票

一些基本的东西

  • 从开发人员的角度来看,无论何时你git clone,你都希望处理刚刚克隆的代码。所以GIT为你提供了一个“工作树”。它被称为树,因为当你考虑所做的所有提交和分支并将其放在图表上时,它就像一棵树。
  • 克隆的存储库称为非裸存储库。要创建一个非裸存储库,您可以执行一个简单的git init - 这是原始程序员用GIT开始跟踪克隆代码所做的工作。你也可以将它克隆到一个裸存储库中,但它的细节和用处应该是一个关于它的正确问题的答案。
  • 裸存储库不包含工作树。它仅用于存储您的代码 - 如果您愿意,可以存储由GIT管理的代码的服务器。要创建一个裸存储库,你可以做一个简单的git init --bare name_of_repository.git。它将创建一个名为name_of_repository.git的目录,其中包含GIT所需的所有文件。 git扩展只是一个使用的约定;它不是必需的,可以是任何东西或什么也不是。
  • 在GIT中有类似于指针的东西叫做HEAD。它指向您正在处理的分支中处于活动状态的最新提交,无论是裸存储库还是非裸存储库。
  • 分支就像您刚从远程存储库中提取的代码的“不同副本”(可能有不同的修改或不同)。它有开发人员认为合适的任何名称。它们非常有用,因为您可以处理不同的功能或修复不同的问题,而无需担心您或其他人正在开发的当前代码。之后,您始终可以将所有内容合并到主分支 - 通常是master - 然后删除那些不再需要的合并分支。
  • GIT尽力避免不同位置或分支的文件版本之间出现问题。因此,在某些情况下,他不会允许你使用git push,至少可以说它是混乱的。 GIT永远不会错,因为它会要求您检查,更改或强制执行您正在执行的操作。所以任何错误都不是GIT的错,而只是你的错。

了解情况

我们考虑以下几点:

  • A存储库是一个裸存储库。 B和C存储库都是非裸存储库。这意味着A没有工作目录,仅用于存储。 B和C用于您需要做的工作。
  • 一般来说,你(通常)有分支机构。通常情况下,初学者不会创建分支,因为他正在学习,甚至可能不知道分支 - 尽管它们有很多原因。所以他几乎总是在'主'分支 - 默认分支。

话虽这么说,让我们说你修改了B中的一些文件。你可以多次执行git commit,最后甚至是git push。或者你什么都不做。但你在主分支机构。

稍后,你修改C中的文件。你确实提交并尝试推送到A.记住:你是C的主分支.git push工作!

然后,您也尝试将C推送到B.它不起作用。

结果:GIT将(不)字面上尖叫,警告您正试图玷污(更新)非裸存储库B的主分支,其HEAD指向另一个提交!如果他允许你进行推送,你将把GIT跟踪的历史记录弄乱在存储库B上。它不会再知道B发生了什么!您甚至可能使用驻留在B上的相同名称覆盖该分支上的修改!所以不,如果两者都是非裸存储库,你不能从C推送到B!

现在怎么办?!我的世界会这样结束吗?!我能做的伟大的事情是什么?! GIT怎么可能忽视他主人的意愿?!这是纯粹的异端邪说!

1 - B上有两个分支 - 主分支和临时分支。并将头指向临时分支。例:

cd B                  # change to B's working directory
git branch temp       # create 'temp' branch
git checkout temp     # change from master branch to branch temp

2 - 现在,转到C工作目录(简称wd)并使用B的内容拉。注意我正在考虑B是C的远程(正如您在案例中提到的):

cd ../C               # change to C's working directory
git pull B master     # pulls B's modifications to C

3 - 用C修改你的文件。注意你在C的主分支上。然后,在提交C的修改后,将其推送给B的主人:

git push B master     # pushes C's mods to B's master branch

4 - 现在回到B wd并将HEAD指向主分支:

cd ../B               # change to B's working directory
git checkout master   # change from temp branch to branch master

5 - 如果您不再使用它,可以删除临时分支:

git branch -d temp    # delete branch temp

6 - 如果要在C中进行新的修改,则不需要同时执行步骤4和5.如果这样做,只要您希望在C中进行修改,就需要事先执行步骤1和2。

这解决了你的问题!大概...

澄清和增援

  • git branch name_of_the_branch创建了一个新分支;
  • git checkout name_of_the_branch让HEAD指向这个新的分支;
  • git checkout -b name_of_the_branch创建一个分支,并在一个命令中使HEAD指向它。我使用较长的方法,因为你应该知道更长的方法;
  • 如前所述,如果您以后要使用它,请不要删除该分支。但我建议这样做,以避免在拉/推或甚至合并时两个存储库中的临时分支出现问题。根据需要创建临时分支 - 使用终端历史记录非常容易 - 然后删除它;

0
投票

如果你使用

git clone --bare http://github.com/xxx/A B

那么你可以从C推到B.你当然不能用B来工作,因为它是裸露的。

我仍然不明白为什么你想要“额外”B回购?

© www.soinside.com 2019 - 2024. All rights reserved.