在分支母版上意外执行的“ Git push origin master”

时间:2019-01-31 23:04:34

标签: git github version-control push commit

我在master上创建了一个本地Git分支(我们称其为BranchB)。然后,我在该分支(到BranchB)上提交了更改。但是当需要将其推送到远程存储库时,给我带来了太多咖啡,我写了git push origin master而不是git push来将新分支推送到存储库。

然后我进入GitHub查看master上的提交。我最近不小心推动的更改没有出现在这里?

那当我在分支B上推送到master时到底发生了什么?这是否会推送自我指定master以来在master上所做的提交。

2 个答案:

答案 0 :(得分:3)

您在此处作为推送参数的<refspec>master,其中完整的规范形式为<src>:<dst><src>是推送的来源和<dst>目标参考。省略一个时,git假设它是<src>,并且没有给出<dst>。在这种情况下,并且如果分支具有<repository>.push配置集(因此在大多数情况下),则引用将用作推送的源。

是的,它将主服务器(没有新提交)推送到其远程副本。无害无操作。

(也许用git config -l | grep origin或类似的方法检查您自己的配置。)

用显式的方式将BranchB推送到master上:

git push origin BranchB:master

这是我从文档中了解的内容,即git-push手册页中的the <refspec> paragraph。似乎对您的结果有意义。

答案 1 :(得分:3)

简短的回答:您还好。 Git最有可能说:

Everything up-to-date

,什么也没做。否则,您只会将您在master上提交的提交发送到GitHub Git的master

更长的答案仍然是你还好,但是你可能在对Git分支的一些误解下工作。他们不会咬你...

提交形成向后指向的链

每个Git提交均由其哈希ID唯一标识。给定一个哈希ID,Git可以找到提交。提交内部还有另一个哈希ID,即提交的 parent 提交,即该提交之前的提交。当然,在提交中还包括进行提交的人的姓名和电子邮件地址,他们的日志消息以及(尽管是间接的)构成该提交的所有文件的完整快照。

这意味着从任何给定提交中,我们都可以向后工作到上一个提交。因此,如果我们有一系列的提交:

... <-F <-G <-H

我们只需要 last 这样的提交的哈希ID,例如H。然后,Git将能够读取H并获取其父级G的哈希ID,并读取G并获取F的ID,依此类推。

master这样的分支 name 因此只标识一个提交

Git查找任何分支的 last 提交的哈希ID的方式是通过分支名称。名称本身masterBranchB或其他任何名称仅包含哈希ID:

...--F--G--H   <-- master, BranchB

这两个 名称都存储相同的哈希ID。因此,master上的所有提交也都在BranchB上。

要进行 new 提交,Git将保存快照,保存您的姓名和电子邮件等,并保存 current 提交的哈希ID {{1 }}。这将成为新的提交H,并为其分配新的唯一哈希ID:

I

其中一个名称必须立即更改!

您的...--F--G--H <-- master, BranchB \ I 会记住您所在的分支

为了知道要更新哪个名称,Git将特殊名称HEAD附加到一个分支。如果HEAD附加到HEAD,则Git将更新该名称:

BranchB

就是这么简单。

快进

嗯,“那么简单”并不是那么简单:分支名称​​ do 这样移动,而Git find 通过最晚开始并向后工作来提交。您可以随时要求Git将任何分支名称移至任何现有提交。假设我们强迫Git将...--F--G--H <-- master \ I <-- BranchB (HEAD) 移回提交BranchB。然后我们如何找到提交H

如果我们这样做这样做,则很难找到I。 (有很多机制,但是让我们不必担心它们。)简单的部分是,只要分支名称向前移动 forward -我们就一次进行新的提交,还是我们进行的一堆提交工作都很好,因为从I过去到I的某个地方,我们总是可以回到I。 / p>

这就是Git的特殊术语快进的意思。如果从 new “ last”提交中,我们仍然可以回到旧的“ last”提交,则分支名称更新是一项快速操作。

推(最终!)

这是I的来源。运行git push时,您的Git会通过某个URL调用其他Git。您的Git和他们的Git进行了交谈。您的Git会根据需要将新的提交移交给他们的Git,然后您的Git要求他们的Git设置他们的分支名称之一。

请记住,就像您一样,他们的Git是一个Git存储库。因此,他们的Git有他们自己的分支名称。他们已经有一个git push

master

您的Git会调用他们的Git并询问他们:嘿,为什么不设置...--F--G--H <-- master 指向提交master他们会说: 已经做到了。您会说:哦,好吧,再见!然后您的Git会打印:

H

或者,您可以发送一些新的提交哈希ID。您的Git会向其Git提供您的新提交,以及将这一新提交链接回Everything up-to-date 所需要的数量,或者无论您走到哪里,您的Git和他们的Git都会共享一些较早的提交。然后,您的Git将作为其Git:嘿,如何将H设置为此其他哈希ID?他们可能会说,或者他们会说:< em>不! 这不是一个快进!现在,您知道快进意味着什么,您知道,如果他们拒绝了您的请求,那是因为无论提交他们的 master的名字,当您查看您的 master并向后工作时,就不会出现在向后链中。

也就是说,假设您被殴打了—其他人,在其他地方,向他们发送了新的提交:

master

您的Git进行了一些新的提交(并且您正在...--F--G--H--L <-- master 上):

master

因此您的Git向他们发送了 J--K <-- master (HEAD) / ...--F--G--H <-- origin/master \ I <-- BranchB 链,并要求他们将其J-K设置为master,但这会丢失他们的K-您甚至都不会有。您必须获得他们的L并弄清楚如何保留他们的L

只要他们没有任何您的 L请求会放弃的提交,尽管它们会接受您的请求。因此,如果他们没有拥有git push,并且您运行L,则会发送git push origin master并要求他们将其主文件设置为{{1 }},他们会的。

即使您将J-K重新连接到K,也是如此:

HEAD

BranchB让您的Git调用他们的Git,向他们提供您的提交 J--K <-- master / ...--F--G--H <-- origin/master \ I <-- BranchB (HEAD) ,并要求他们将git push origin master移动到您的K所在的位置。 / p>

master让您的Git调用他们的Git,向他们提供您的提交master,并要求他们在其中移动(或创建)他们的git push origin BranchB

请注意,您也可以I向他们提供两个尖端提交(上图中的BranchBgit push origin master BranchB),并发出两个请求。或者,作为RomainValeri noted,您可以为单词K之后的每个单词设置完整的 refspec 参数,例如Iorigin。它们让您的Git像以前一样发送您的提交,然后请求它们设置目标分支名称(冒号之后的名称)以匹配您源分支的技巧提交(从冒号之前的名称)。通常,混合这样的名称并不是一个好主意-如果没有别的,那就太令人困惑了。但是在某些特殊情况下,它是有用的快捷方式。

相关问题