首页 > 解决方案 > 如果我使用相同的提交哈希,我使用“git log”的分支是否重要?

问题描述

看哪!我有以下 Git 结构:

A-...-C-D-E      (develop branch)
         \
          X-Y    (feature1 branch)

其中 A、B、C、D 和 E 是开发分支上的提交,X 和 Y 是名为 feature1 的分支上的提交。提交 A 和 C 由未知数量的提交分隔。假设提交 A 有(部分)提交哈希b0a710ad5,提交 Y 有(部分)提交哈希0fc0d3

现在,有两个感兴趣的场景。我结帐开发和运行的地方

git log --oneline b0a710ad5..0fc0d3

而在第二种情况下,我改为签出 feature1,并执行相同的命令:

git log --oneline b0a710ad5..0fc0d3

如果我不得不猜测这些场景返回了什么,我会说第一个会给我一个错误,因为开发分支上不存在提交 Y。我猜想第二种情况会给我一个合法的 Git 日志。然而,我大错特错了。我在哪个分支似乎并不重要:两个命令都给了我完全相同的日志。似乎git log可以看到来自其他分支的提交,这是我从未想过的

可以git log在本地存储库的任何分支上找到提交吗?如果在任何本地分支上都找不到提交,它是否会远程搜索和查找提交?git log ..当我使用提交哈希运行时,我在哪个分支上真的无关紧要吗?哦,可能性。

标签: gitgit-checkoutgit-log

解决方案


正如评论中提到的光谱,散列在任何地方都有效。

大多数情况下,Git 只是使用名称来查找哈希。也就是说,一个类似于developor的分支名称feature1只是一个人类可读的——而且,重要的是,它是可更改的——用于某些特定哈希 ID 的名称。该哈希 ID 主要是 Git 关心的。类似的命令git log将从名称转换为哈希 ID,然后开始处理提交。提交本身包含另一个哈希 ID,用于其父提交,git log并将查看提交,该提交还有另一个哈希 ID,依此类推。

我们可以以向后指向的方式链接这些提交中的每一个,使用分支名称来查找最后一个提交,如下所示:

... <-grandparent <-parent <-0fc0d3   <--branchname

这基本上就是 Git 所做的。

当使用像这样的范围操作时b0a710ad5..0fc0d3,Git 直接获取哈希 ID:0fc0d3是一个正引用,因此 Git 会找到该提交。由于..它们之间有两个点,第一个哈希 ID , b0a710ad5, 在语法上等价于^b0a710ad5: 它是一个负引用。Git 也会找到该提交,但它使用它来抑制显示某些提交。如果b0a710ad5它自己在链中,Git到达b0a710ad5. 如果b0a710ad5 不在链中——例如,如果提交链看起来更像这样:

    b0a710ad5  ...   <--somename
        /
great-...-grandparent <-... <-parent <-0fc0d3   <--branchname

然后b0a710ad5抑制Git通过从 向后走来找到的曾n次祖父母b0a710ad5

这个从后面的提交开始向后走的过程是 Git 如何确定提交的可达性的。如果我们从较晚的提交开始并向后工作并到达较早的提交,则可以从稍后的提交或从某个名称访问较早的提交。

名字有时重要

请注意,当您进行的提交时,通常是在“在”某个分支上时进行的。位于分支上意味着Git 将名称附加HEAD到该分支,因此,如果我们使用右侧的分支名称绘制提交,指向提示(最近的)提交,其中一个名称已HEAD附加:

...--F--G--H   <-- develop
         \
          I--J   <-- feature1 (HEAD)

(这里的单个大写字母代表实际的哈希 ID,这太笨拙了,无法打扰。)

如果我们现在进行新的提交,Git 会将新提交设置为当前提交的哈希 ID J,然后将新提交的哈希 ID写入 namefeature1中。HEAD附加到feature1并且feature1当前名称为 commit的事实J就是这一切的工作方式。Git 进行新的提交K

...--F--G--H   <-- develop
         \
          I--J   <-- feature1 (HEAD)
              \
               K   [make new commit: parent is HEAD]

然后写入K得到feature1

...--F--G--H   <-- develop
         \
          I--J
              \
               K   <-- feature1 (HEAD)

我们可以在更少的行上重绘:

...--F--G--H   <-- develop
         \
          I--J--K   <-- feature1 (HEAD)

请注意,在整个操作过程中HEAD保持连接;feature1feature1本身会发生变化,以存储新的哈希 ID。

(当您使用 时git push,您还使用这些名称来标识要发送到其他 Git 存储库的提交。您要求他们根据您的名称设置名称您使用时git fetch其他一些Git 存储库具有指向提交的名称具有哈希 ID,您的 Git 会复制提交(保持相同的哈希 ID),然后将新origin/*名称写入您的存储库,以便记住它们的名称而不会与您的分支名称冲突。所以名称在这里也很重要——但是哈希 ID 至少和实际提交的“真实姓名”一样重要。)


推荐阅读