【问题标题】:git fetch remote branch, but cannot see in local repository or working copygit fetch 远程分支,但在本地存储库或工作副本中看不到
【发布时间】:2021-03-27 22:07:58
【问题描述】:

我当前的分支是 staging_kei20201211,我想从 origin/staging 分支获取最新的代码,我输入以下命令

git fetch origin staging

它说

1) 然后我去visual studio查看我的分支staging_kei20201211的历史,但是我看不到fetch输出中所说的commit c03c99691,为什么?

  1. 获取输出屏幕的含义是什么? 来自 http://XXXXXX/gitea/elm-ha/CFMS
  • 分支暂存 -> FETCH_HEAD c97e1dbb7..c03c99691 暂存 -> 来源/暂存

【问题讨论】:

  • 可以从origin/staging 访问获取的提交。要同时列出此类远程跟踪分支,请使用git branch -a。在您将 origin/staging 合并到 staging_kei20201211 之前,这些提交无法从 staging_kei20201211 访问。

标签: git git-fetch


【解决方案1】:

让我们先从问题 2 开始,因为它对查看问题 1 很有用:

获取输出屏幕的含义是什么?

From http://XXXXXX/gitea/elm-ha/CFMS
 * branch                staging  -> FETCH_HEAD
   c97e1dbb7..c03c99691  staging  -> origin/staging

实际上还有更多的输出,其中大部分以单词remote: 为前缀。 remote:-prefixed 文本是从服务器本身运行的命令输出的。这导致服务器发现他们的 Git 想要发送到您的 Git 的 59 个内部 Git 对象,以便您的 Git 获取他们拥有的一切,而您此时没有但正在要求。然后他们“打包”这些对象,实际上将其进一步压缩到大约 2 KiB 以发送,然后发送;然后你的 Git 解压缩这些数据,并将内部对象放入你的存储库中。

此时,您拥有所有新的提交,但您无法在存储库中找到新的提交。新的提交是From http://...,所以这是From 部分。这些提交是在 other Git 存储库中使用名称 stagingin 找到的其他 Git 存储库。所以你的 Git 写了一个名为FETCH_HEAD 的内部文件,事实上你给git fetch 的分支名称,即staging,对应于提交c03c99691,它现在存在于你的存储库中(但是,到目前为止,still 没有 name 可供您找到)。

last 行告诉你 Git 在你的存储库中做了什么让你能够find commit c03c99691。你自己的 Git 更新了你的名字origin/staging。你的origin/staging 用于查找提交c97e1dbb7。现在它找到了提交c03c99691。就是这样:

 c97e1dbb7..c03c99691  staging -> origin/staging

意味着:他们的staging 变成了你的origin/staging,而你的origin/staging 曾经拥有 c97e1dbb7,但现在拥有c03c99691,和他们的staging 一样。

这里的最终结果是您的origin/staging,它是一个远程跟踪名称而不是一个分支名称,拥有相同的提交哈希ID 作为他们的 分支 名称 staging。因此,您可以使用名称 origin/staging 来查找提交。您也可以使用原始哈希 ID:c03c99691

Git 真的是关于提交

在 Git 中,重要的是 提交。每个提交都有一个唯一的编号。你刚刚从他们那里得到的提交结束,提交的唯一编号是c03c99691。 (这实际上是一种缩短的形式:完整的哈希 ID 更大更丑。Git 有时会缩短它们,只保留前几个字符,以帮助避免压倒单纯的人类。) 这个数字在 每个 Git 存储库您的存储库使用这个编号,他们的也是。

每个提交本身由两部分组成:

  • 提交包含每个文件的完整快照。提交中的文件以特殊的、压缩的、只读的、仅 Git 的和重复数据删除的格式存储。这样一来,当您进行新的提交时,您主要是在重复使用 previous 提交中的文件,因此新的提交不会占用太多空间。只有 更改 文件需要新的内部对象。对于所有未更改的文件,它们的内容与其他提交中的文件相同,因此它们可以共享去重部分。

  • 同时,每个提交还包含一些关于提交本身的信息,例如谁提交、何时提交以及为什么提交。在提交内的此信息中,每个提交都包含用于进行 this 提交的任何 earlier 提交的原始哈希 ID 列表。通常只有一个这样的哈希 ID,我们称之为提交的

这个 父哈希 ID 技巧是 Git 工作的原因。假设我们有一系列提交,所有提交都在一个简单的行中,没有进行分支和合并。此序列中的 last 提交有一些丑陋的哈希 ID,但我们将其称为提交 H。提交 H 在其自身内部有其 parent 提交的大而丑陋的哈希 ID;我们将该提交称为G

我们说子提交指向父提交,我们可以画出:

        <-G <-H

您可以看到从H 出来的箭头,指向G。当然,G 也有一个箭头。它向后指向G 之前的提交,我们称之为F

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

和以前一样,F 也指向后面。这个向后看的链让我们——或 Git——从 last 提交开始并找到历史。 存储库中的历史无非就是存储库中的提交。 仅此而已,但也仅此而已。每个提交都向后指向更早的提交。

分支名称和其他名称发生变化;哈希 ID 保持不变

这是分支名称进入我们图片的地方。为了find所有提交,我们需要last提交的哈希ID。以上是提交H。所以我们把 last 提交的 hash ID 放到一个名字中,比如分支名。如果分支名称master包含提交G的hash ID,分支名称staging_kei20201211包含提交H的hash ID,我们可以画成这样:

...--F--G   <-- master
         \
          H   <-- staging_kei20201211

在这里,commit H 指向之前的 commit G。名称master 也指向提交G。这意味着直到G 的提交都在两个分支上,而提交H 仅在staging_kei20201211 上。

(在 your 存储库中是否是这种情况,我不知道。请注意,我们还使用符号名称 GH 来表示提交;它们的真实名称是大而丑陋的哈希 ID。要查找哈希 ID,请使用 git rev-parse

git rev-parse master

会告诉你 master 指向的提交的真实哈希 ID,例如。)

考虑到这一点,让我们看看当您将 new 提交添加到某个分支时会发生什么。让我们从git switch mastergit checkout master 开始,这样当前分支名称master当前提交 是提交G

...--F--G   <-- master (HEAD)
         \
          H   <-- staging_kei20201211

这张图与上一张的不同之处在于,我们在名字master后面加上了特殊的名字HEAD,告诉我们哪个分支名称是当前分支。 (git branch 命令现在会将这个名称打印为绿色,而不是白色,正如您在 staging_kei20201211 中看到的那样。)

我们现在可以创建一个也指向G 的新名称,然后切换到它:

git switch -C temp-branch

得到:

...--F--G   <-- master, temp-branch (HEAD)
         \
          H   <-- staging_kei20201211

如果我们现在以通常的方式(修改文件、git addgit commit)进行 new 提交,我们将获得一个新的提交,并带有一个新的、唯一的哈希 ID .这个大而丑陋的哈希 ID 将是一个不在任何其他 Git 存储库中的一个(这就是为什么它们必须像它们一样大而丑陋),但我们将其称为 commit @ 987654391@,然后画成这样:

          I   <-- temp-branch (HEAD)
         /
...--F--G   <-- master
         \
          H   <-- staging_kei20201211

注意 name temp-branch 是如何改变的:它现在指向 新提交。旧的提交仍然存在,通过G 的提交现在位于所有三个分支上。 name 已移动,但提交保持不变。我们刚刚添加了一个 new 提交,它现在是分支 temp-branch 上的 last 提交。

如果我们检查其他分支名称,例如staging_kei20201211,并删除名称temp-branch,我们会得到:

          I   ???
         /
...--F--G   <-- master
         \
          H   <-- staging_kei20201211 (HEAD)

提交I仍然存在,但是如果你没有在任何地方保存它的提交哈希ID,它将很难找到。 Git 将在提交上挂起一段时间,以防你想要它回来,但你必须找到它的哈希 ID。如果您不以某种方式将其收回,Git 最终将完全丢弃提交 I。 (如果我们想这样做,这就是我们进行临时提交然后放弃的方式。)

Git 的 fetchpush 处理 散列 ID 以传输提交

虽然我们通过名称​​查找提交,但实际提交本身由哈希 ID 标识。要查看我们是否已经有一些提交,当我们将两个 Git 相互连接时,它们只是交换原始哈希 ID。由于这些在每个 Git 中都是唯一的,因此一个 Git 可以通过它是否具有具有相同哈希 ID 的提交来判断另一个 Git 是否具有相同的提交。如果没有,发送的 Git 只是将其发送过来。所有 Gits 编号都以相同的方式提交,1 因此接收 Git 将使用相同的随机编号。


1为了完成这项工作,Git 使用了强大的加密哈希函数。 “加密强”部分对 Git 本身来说不是必不可少的,但对其他目的很有用。当前的算法 SHA-1 不再足够强大,Git 正在转向新的哈希算法,但这是一个长期的转变,预见到许多问题;当 Git 开始进行转换时,会出现无法预料的情况。 ?


一旦获得,receiving Git 需要有一个 name

在您的情况下,您将 git fetch 运行到一个 Git,其联系 URL 以名称 origin 被记住。你的 Git 在那个 URL 调用了服务器。该服务器调用了一个连接到存储库的 Git,其中有一个分支名称 staging,其​​包含哈希 ID c03c99691。为简单起见,我将此提交称为K

您的 Git 之前曾与另一个 Git 进行过通信。事实上,给定名称origin,您的 Git 可能通过将其他 Git 存储库的所有提交复制到您自己的新 Git 存储库中来启动。所以从那时起,这个提交就被添加到了origin。他们移动了他们的分支名称staging。他们可能有:

...--G   <-- master
      \
       J   <-- staging

当您执行原始 git clone 时,您可以在 您的 存储库中说:

       H   <-- staging_kei20201211 (HEAD)
      /
...--G   <-- origin/master
      \
       J   <-- staging, origin/staging

(或者可能是具有不同结构的不同图表,但从您的git branch 名称和git fetch 输出来看,我怀疑您有一个origin/master,我知道您有一个origin/staging)。您的 origin/* 名称来自您的 Git 复制 他们的 Git 存储库的 分支 名称。

无论如何,他们现在有了一些新的提交。我猜他们有一个新的提交,而你的 git fetch 带来了那个:

       H   <-- staging_kei20201211 (HEAD)
      /
...--G   <-- origin/master
      \
       J   <-- staging
        \
         K   <-- origin/staging

如果这张图是准确的,J 真的是c97e1dbb7K 真的是c03c99691

现在回答问题 1

我去 Visual Studio 查看我的分支 staging_kei20201211 的历史记录,但我看不到 fetch 输出中所述的提交 c03c99691,为什么?

我不知道也不使用 Visual Studio,但一般来说,要让任何 Git 查看器向您显示一些提交,您必须告诉他们最后一次此类提交的原始哈希 ID,或者给他们一个名称这允许他们使用 Git 来查找最后一次这样的提交。

正如您现在所知道的,名称origin/staging 根据定义将找到以该提交结尾的链中的最后一个提交。那是因为你的 Git 更新了你的 origin/staging 以匹配另一个 Git 正在查看的 Git 存储库中的名称 staging

从 bash 风格的命令行:

$ git log origin/staging

会向您展示一些提交,从 c03c99691 开始,由 origin/staging 找到。命令:

$ git show origin/staging

会找到提交c03c99691,找到它的父级——可能是c97e...,但如果你刚刚从origin 获得了两个或更多提交,也许还有其他提交——然后比较两个提交中的快照。对于每个完全相同的文件,git show 不会显示任何内容。对于每个不同的文件,git show 会告诉您发生了什么变化。所有这些都将以提交c03c99691 中的日志消息 为前缀,以及存储在提交c03c99691 中的名称和电子邮件地址以及日期和时间戳信息。

【讨论】:

    【解决方案2】:

    请注意,获取只会更新本地 tracking 分支。在这种情况下,您的 fetch 更新了以下分支:

    origin/staging_kei20201211
    

    要更新实际的本地分支staging_kei20201211,您需要执行以下附加步骤:

    # from staging_kei20201211
    git merge origin/staging_kei20201211
    

    不过,通常情况下,您会检查您的本地分支机构并执行git pull

    git checkout staging_kei20201211
    git pull origin staging_kei20201211
    

    【讨论】:

      猜你喜欢
      • 2011-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-09
      • 2017-12-28
      • 2012-01-05
      • 2013-06-09
      • 2011-03-03
      相关资源
      最近更新 更多