一些基本的东西
无论何时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
在最后执行一次。或者你什么都不做。但是你在 master 分支上。
稍后,您在 C 中修改文件。然后您提交并尝试推送到 A。记住:您在 C 的主分支上。git push
工作!
然后,您也尝试将 C 推到 B 上。它不起作用。
结果:GIT 将(不会)真正尖叫,警告您正在尝试污染(更新)其 HEAD 指向另一个提交的非裸存储库 B 的主分支!如果他让你推送,你会弄乱 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 的 master:
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 指向它。我使用了较长的方法,因为您也应该知道较长的方法;
- 如前所述,如果您以后要使用它,请不要删除分支。但我确实建议这样做以避免在拉/推甚至合并时两个存储库中的临时分支出现问题。根据需要创建临时分支 - 使用终端历史非常容易 - 然后将其删除;