于是git status回来了
Your branch is ahead of 'origin/Dev-Branch' by 5 commits.
(use "git push" to publish your local commits)
Run Code Online (Sandbox Code Playgroud)
我这样做了,现在git status回来了
Your branch is up to date with 'origin/Dev-Branch'.
Run Code Online (Sandbox Code Playgroud)
但git log显示我的最后一次提交是前一天的:即今天没有任何内容被推送到原点
Git 如何计算后面和前面的提交消息?
如果记住以下几点,对理解 Git 会有很大帮助:
\nGit 就是关于提交。分支 \xe2\x80\x94 或分支名称\xe2\x80\x94 仅在让您(和 Git)查找哈希 ID 方面重要。哈希 ID 是提交的真实名称。哈希 ID 看起来是随机的,因此我们需要名称来查找它们。分支名称(例如master或)保存一个哈希 ID:该分支中最后一次dev提交的哈希 ID 。
这些哈希 ID 是通用的!它们在每个 Git 存储库中始终相同。Git 存储库要么具有该提交,该提交具有该哈希 ID……要么根本没有该提交。任何哈希 ID 都不能重复用于不同的提交。1
\nGit 被称为分布式,但您可能认为它是复制的更好。(不过从技术上来说,分布式是一个更好的词。使用任何你需要的东西,并牢记在心。)
\n每个存储库(通常情况下)都有它所见过的所有提交的完整副本。第一次使用git clone其他存储库时,您将获得其所有提交的完整副本。不过,在那之后,两个克隆体可能会逐渐分开,除非你让一个克隆体呼叫另一个克隆体。
克隆仅在您连接\xe2\x80\x94 时才相互通信,方法是让一个存储库调用另一个存储库(通常通过https://...或ssh://...URL),但通常您会将此 URL 隐藏在一个简单的名称(如origin.
您可以使用git fetch(“获取提交”)和git push(“给予提交”)进行连接。该git pull命令在这里会让人分心:它实际上只是意味着run git fetch,然后运行第二个 Git 命令。 它是git fetch让你的 Git 与另一个 Git 对话的部分。
因此,要使用他们获得或制作的任何新内容更新您的克隆,您可以运行. 你的 Git 调用他们的 Git,你的两个 Git 进行存储库交互,并且由于方向是“从他们那里获取新东西”,所以无论他们拥有什么,你现在也拥有它。但您的 Git会使用您的 Git远程跟踪名称记住它们所拥有的内容。您的 Git 询问他们的. 他们可能会说:我的是 commit。如果您还没有该提交(以及与之相关的任何早期提交),您的 Git 让他们发送该提交(以及您也需要的任何早期提交)。一旦你的 Git 提交了,你的 Git 就会设置你的\xe2\x80\x94 而不是你的!\xe2\x80\x94 以记住他们所说的.git fetchmastermastera123456...origin/mastermaster mastera123456
要使用您获得或制作的任何新内容更新他们的克隆\xe2\x80\x94显然您必须自己制作它,或者从不是他们的地方获得它\xe2\x80\x94您让您的 Git 调用他们的 Git并说:你有承诺吗? 如果没有,你就向他们做出承诺,以及完成工作所需的任何其他承诺。然后你的 Git 会说:现在,如果你愿意的话,请将你的设置为。2 请注意,他们没有设置远程跟踪名称!他们没有类似的东西;他们只是有他们的。b789abc...masterb789abc...brian/masterkevin/master master
如果他们的 Git 返回并说“OK”,我将 my 设置master为b789abc...,那么,现在你的 Git 知道他们的master意思是哈希 ID。所以你的 Git 更新你的 origin/master以记住他们的主人记得b789abc...。
这让我们了解了远程跟踪名称的含义origin/master:这些是您的 Git 的记忆,记录了 Git 所记住的哈希 ID。 这些哈希 ID 可能已过时!运行git fetch会让您的 Git 从其 Git 获取任何新内容,并更新您的远程跟踪名称,因此现在您的 Git 拥有正确的信息。如果您已经有一段时间没有运行了git fetch,那么您的 Git 可能已经过时了。3
1这种唯一性约束实际上稍微宽松一些:如果两个 Git 永远不会互相进行 Git-sex,则两者之一可以重复使用另一个 Git 用于不同内部对象的哈希 ID。除了这个例外, Git 的所有功能都严重依赖于哈希 ID 的唯一性。它们是所有魔法发挥作用的原因。这就是为什么它们看起来如此随机,尽管它们实际上只是严格计算的加密校验和:它们必须是唯一的。
\n2git push即使他们已经这么做了,你也会这样做b789abc...。该git push命令由两部分组成:如果/根据需要发送提交,所有这些都通过唯一的哈希 ID 来工作,后面跟着对其他 Git 的请求或命令:将分支名称 X 设置为哈希 ID H1,将分支名称 Y 设置为哈希 ID H2, 等等。
3 “一会儿”有多长?这取决于其他 Git 存储库的活跃程度。也许他们每天都会收到新的提交。也许只是每年一次。或者也许他们每小时会收到数千个新提交,即使只有半秒,为什么,那几乎是永远的!
\n在 Git 中,一个提交\xe2\x80\x94 具有唯一哈希 ID\xe2\x80\x94 的东西是:
\n最后一点就是 Git 历史的存在方式。提交是一个快照,但具有前一个快照的哈希 ID。也就是说,如果我们有一些丑陋的大哈希 ID\xe2\x80\x94,我们只需将其称为H“哈希”\xe2\x80\x94,它定位一个提交,该提交内部包含前一个提交的哈希 ID。我们将其称为第二个哈希 ID G。然后:
... G <-H\nRun Code Online (Sandbox Code Playgroud)\nH出现在之后G,但指向更早的提交G。当然G里面也保存了一些又大又难看的哈希ID,所以G指向F:
... <-F <-G <-H\nRun Code Online (Sandbox Code Playgroud)\n和F再次指向后面,等等。
有了这样的链,我们可以从任何提交一直追溯到第一次提交。该提交不会指向较早的提交,因为它不能:没有较早的提交。Git 将此称为根提交。假设只有 8 个提交,A一直到H,都在一个很好的线性行中,并且名称保存了 最后一次提交master的哈希 IDH:
A--B--C--D--E--F--G--H <-- master\nRun Code Online (Sandbox Code Playgroud)\n我们说这master指向H. (我将提交之间的箭头切换为线条,因为它们更容易绘制,尤其是在接下来的几张图中!但它们仍然全部指向向后。请记住,Git 向后工作;每隔一段时间,了解一下这一点很有用。在这里,这并不重要。)
现在让我们进行更多提交,但在两个不同的分支上像这样br1进行br2:
I--J <-- br1\n /\n...--G--H <-- master\n \\\n K <-- br2\nRun Code Online (Sandbox Code Playgroud)\n该名称包含 commit :指向br1的哈希 ID 。名字指向.Jbr1Jbr2K
Git 的棘手之处之一是,现在所有三个分支上的提交H都是如此。(其他版本控制系统不会这样做。)如果我们现在进行新的提交,它会获得另一个新的、唯一的哈希 ID,并且名称会移动到指向它:mastermaster
I--J <-- br1\n /\n...--G--H--L <-- master\n \\\n K <-- br2\nRun Code Online (Sandbox Code Playgroud)\n当您将提交添加到存储库时,现有提交不会以任何方式发生更改。(它们实际上无法更改,因为它们唯一的哈希 ID 只是其内容的校验和。如果您更改任何提交的任何内容,您得到的只是一个新的、不同的、唯一的提交,具有新的、不同的、唯一的哈希 ID。 )但是分支名称动了!根据定义,分支名称始终指向分支中的最后一次提交。
\n让我们转到您的Git 存储库,或者靠近它的存储库。我不知道你总共有多少提交\xe2\x80\x94可能比我可以使用的26个大写字母\xe2\x80\x94多得多,但是让我们这样画:
\n...--G <-- origin/Dev-Branch\n \\\n H--I--J--K--L <-- Dev-Branch (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n这里HEAD表示这是您现在已经签出的分支。如果你有很多分支\xe2\x80\x94,甚至只有两个\xe2\x80\x94,我们需要知道你在“哪个”,这样就git status可以说on branch Dev-Branch,这样当你进行新的提交时,Git 就知道要移动的分支名称。
我们origin/Dev-Branch输入的是远程跟踪名称。你的 Git 已经与他们的 Git\xe2\x80\x94 进行了对话origin,这个名称保存了你的 Git 用来与他们对话的 URL\xe2\x80\x94 在某个时刻,他们说我的Dev-Branch名字提交了G,所以你的 Git 有你的origin/Dev-Branch指向(共享)提交G.
同时,你Dev-Branch要承诺的要点L。
提交总是向后指向。新提交指向您进行提交时所做的任何提交,因此L指向K,指向J,依此类推。
如果从 开始计数L,并在到达指定的提交时停止,那么有多少次提交origin/Dev-Branch?
现在,假设要运行git fetch ,并且他们有一个新的提交\xe2\x80\x94,让我们称之为它N,M由于某种原因跳过提交后立即出现的\xe2\x80\x94H,你最终会在存储库中得到这个:
...--G-----------N <-- origin/Dev-Branch\n \\\n H--I--J--K--L <-- Dev-Branch (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n那是因为你的 Git 会询问他们的 Git Dev-Branch,他们会说“哦,那是提交N”。您的 Git 将获得提交N,然后看到您已经提交G并完成了该阶段,然后您的 Git 将更新您origin/Dev-Branch以指向N.
现在,如果您有git status计数提交,那么您的提交中有多少Dev-Branch未共享? 您有多少提交origin/Dev-Branch未共享? (请注意,此处共享意味着这两个名称之间。因此,提交G- 和之前的内容是共享的,但 H 和之后的内容不是共享的。我们不关心另一个 Git 中的实际内容,只关心我们的 Git 记住它们的内容吉特。)
假设这是他们存储库中的实际情况(他们有 commit N)。N即使您自己的存储库中没有/没有,您现在也可以运行git push. 你的 Git 会调用他们的 Git 并向他们发送你的H-I-J-K-L链,现在他们将拥有与我们这里相同的绘图(但使用他们的名字,而不是你的名字)。然后你的 Git 会要求他们 更改Dev-Branch指向 commit L:
...--G-----------N <-- Dev-Branch [in origin]\n \\\n H--I--J--K--L <-- proposed new Dev-Branch\nRun Code Online (Sandbox Code Playgroud)\n如果他们将自己的Dev-Branch名字移动到所指向的位置L,会发生什么情况N?答案是:它实际上什么也没发生,但现在,他们没有它的名字,也找不到它了。箭头只能向后移动:没有办法从G到N,只能从N到G。所以如果你这样做,他们只会说不,我不会移动我的Dev-Branch. (他们会称之为非快进。)
此时,您需要在自己的存储库中进行合并提交,或者确保它们不会丢失提交N。此类合并可能如下所示:
...--G--------------N <-- origin/Dev-Branch\n \\ \\\n H--I--J--K--L--M <-- Dev-Branch (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n您的新合并提交 M将引用您现有的提交L,但也会引用他们的(现在也是您的)提交N。(如果您还没有N,则需要git fetch先获得,才能获得 N。)
git push,更新您的图纸我们再回到这张图:
\n...--G <-- origin/Dev-Branch\n \\\n H--I--J--K--L <-- Dev-Branch (HEAD)\nRun Code Online (Sandbox Code Playgroud)\n你跑git push(或git push origin Dev-Branch)。你的 Git 调用他们的 Git,H-I-J-K-L如果他们没有的话给他们提交\xe2\x80\x94如果他们有的话,你的 Git 发送他们仍然需要的那些\xe2\x80\x94,然后要求他们将其设置Dev-Branch为点提交L。他们说“好吧,我做到了”,所以你的 Git 更新你的 origin/Dev-Branch以记住他们接受了你的请求:
...--G\n \\\n H--I--J--K--L <-- Dev-Branch (HEAD), origin/Dev-Branch\nRun Code Online (Sandbox Code Playgroud)\n现在,当git status计算提交时,它将找出您的 上有多少提交Dev-Branch未与您共享origin/Dev-Branch(您的 Git 对其的内存) Dev-Branch,以及您的 上有多少提交origin/Dev-Branch未与您自己的共享Dev-Branch。由于这两个名称完全匹配,因此前面没有提交,后面也没有提交。
这一切都基于您在当地拥有的任何信息。 此时他们的 Git 有什么并不重要。他们的 Git 拥有的内容在你运行时git fetch和运行时很重要git push,但在你运行时并不重要git status。
当您查看各种提交时,例如L,Git 会向您显示该提交中的内容。任何元数据都无法更改。任何快照都无法更改。元数据表明提交是昨天进行的,所以这就是您将看到的内容。
(为了显示快照,Git 实际上会检索 中的快照L 及其直接父级中的快照K。然后 Git 会比较两个快照以查看发生了什么变化。 一般来说,发生变化的内容比所有内容更有用,当你想查看这样的提交时。但每个提交仍然是完整的快照。)
| 归档时间: |
|
| 查看次数: |
3387 次 |
| 最近记录: |