【问题标题】:git fetch not working - but checkout workinggit fetch 不工作 - 但结帐工作
【发布时间】:2017-06-12 19:28:22
【问题描述】:

我是 git 的初学者,并在 Windows 上尝试使用它。

我在 Bitbucket 上创建了一个存储库。通过 Bitbucket online 将三个文件(SAY A、B、C)添加到 master 分支。

现在我的本地 PC 上有文件夹,我使用 git fetch 获取这三个文件。三个文件现在位于本地存储库中。

现在,我在 bitbucket 上添加了另一个文件(SAY D),并更改了所有三个文件(A、B、C)的内容。

现在,如果我尝试通过 git fetch MY_REMOTE master 获取更改,我的本地没有任何更改。但是

  • 使用 git pull MY_REMOTE master ,我可以看到更改。

  • 使用 git checkout MY_REMOTE/master ,我可以看到更改。

    所以我有疑问,

  • git fetch 只需将不在本地的更改复制到本地存储库,除非本地存储库更改了相同的副本。为什么git fetch 在这里不起作用?

  • 我不明白在 Local 上执行 git checkout MY_REMOTE/master 的目的。我为什么要这样做?

【问题讨论】:

    标签: git git-pull git-checkout git-fetch


    【解决方案1】:

    Git 的 fetch 不获取文件——好吧,反正不是直接获取。

    在某种程度上,Git 根本不关心文件。 Git 关心的是提交。不过,在我们进一步探讨这个想法之前,我们可能应该回顾一些基本的 Git 定义。

    存储库中有什么

    Git 存储库 包含三个主要部分:commitsindexwork-tree。 (一些 Git 存储库会省略工作树,在较新版本的 Git 中,您可以拥有多个工作树,其中每个工作树都有自己的索引。但通常您从每个工作树开始。)

    commit 是一个快照:一个完整​​的set 文件。它不仅仅是 a 文件,也不是某些文件中的 差异:它是一个独立的东西,您决定保存在该提交中的所有文件,在保存它们时的形式。提交也是永久且不变的。像所有 Git 对象一样,它有一个唯一标识符:例如3313b78c145ba9212272b5318c111cde12bfef4a。一旦存储,您将永远无法在提交中更改 任何内容。如果您尝试,您将获得提交的副本,其中包含更改,并且副本具有新的不同 ID。您可以(有时)完全删除一个提交,但不能更改它,只能将其复制——嗯,大部分,当然,除了更改的部分之外——复制到一个新的不同 ID 提交.

    Git 真的,真的 关心提交。确保你永远不会失去一个非常努力。它不太关心索引和工作树:它们既不是永久的,也不是不变的。提交的优点是显而易见的,但它们的缺点也很明显:它们以计算机上其他任何东西都无法处理的形式存储在 Git 中——存储库中。

    工作树与此相反:它的形式是计算机上的所有东西都可以处理,而且它是无常且多变的。这是你做所有工作的地方。它有文件,而不是神秘的 Git 对象。这是您读取、写入和编辑文件的地方。

    Git 的 index 最初对大多数人来说是相当神秘的(对我来说是这样),它有很多你最终会遇到的复杂的曲折。一些软件试图完全隐藏索引,但这不是一个好主意。一方面,索引实际上非常简单:它是 Git 让您构建下一次提交的地方。索引开始匹配 current 提交,然后你 git add 现有文件的新版本或全新文件到索引,以复制新文件。然后当你运行 @987654324 @,Git 会根据您现在在索引中的任何内容进行新的提交。这会生成永久的、不变的快照。索引,也称为暂存区,只是您排列(或“暂存”)文件的位置,以使它们在快照中尽可能漂亮。

    每个提交还记录其直接前任或提交的 ID。一旦您开始处理历史,这将变得至关重要。历史记录由提交本身形成,通过“我的父母是……”信息。

    master 这样的分支名称仅通过其 ID 标识该分支上的 最新 提交。 Git 将此称为分支的 tip。这个最新的提交会记住它的父级,而那个父级会记住它自己的父级(最新提交的祖父级),依此类推。 Git 也有其他实体做同样的事情:记住一个特定提交的 ID。最重要的两个是标签远程跟踪分支

    总结

    存储库包含 commits,其中包含 snapshots,并形成了所有提交的历史记录。 分支名称 mastermaster 上找到最新 提交。而且,虽然提交包含文件,但它们本身并不是文件:它们包含整套文件,全部作为一个集合。

    存储库有一个索引,它是内部 Git 提交表单和工作树表单之间的中介,并且大多数存储库都有一个工作树,它可以让您获取提交的文件as文件。

    git checkout 做了什么

    git checkout 命令主要将提交复制到索引和工作树中,以便您可以在所有提交的历史记录中移动并在工作树中查看相应的快照。它还调整了 Git 调用的 HEAD

    名称HEAD,在 Git 中,总是通过其 ID 引用当前提交——但它以两种不同的方式之一这样做。您可以“在一个分支上”,在这种情况下,名称 HEAD 只包含分支的名称。然后是分支名称获取 Git 当前提交的 ID。或者,您可以有一个“分离的 HEAD”,在这种情况下,名称 HEAD 记录了当前提交的 ID。

    如果你给git checkout 一个分支名称——比如git checkout master——它会将你放在“分支上”:它会检查提示提交,因为这是存储在分支名称中的 ID,然后它会将分支放在HEAD 中的名称。如果你给 git checkout 一个原始的提交 ID、标签名称或远程跟踪分支名称,它会找到相应的 ID,检查该提交,并将 ID 放入 HEAD

    git fetch——和git push——做什么

    以上所有步骤都完全适用于您自己的存储库。不过,Git 并不将您限制在一个存储库中。在选择的明确时间,您可以告诉您的 Git 调用另一个 Git,通常是通过 Internet,并与另一个 Git 进行某种对话。

    git fetchgit push 都是这样做的。他们在某个 URL 的另一端调用其他 Git。 URL 通常存储在一个名为 remote 的名称下。最常见的——通常是任何给定存储库中唯一的远程——是origin(因为git clone为你设置了一个)。

    但请记住,Git 最关心的是提交。所以当你的 Git 调用另一个 Git 时,他们的对话主要是关于提交。当然,他们确实需要一种方法来查找这些提交的 ID,为此他们通常以一些分支名称开头。这通常是 Git 开始一切的方式:取一个分支名称,或者可能只是名称 HEAD,然后找到一个提交 ID。使用该提交。然后,如果合适,请转到该提交的父级并使用 that 提交执行某些操作,依此类推。

    fetch 进程尤其会获取另一个 Git 中所有分支的列表。然后,它会获取那些分支中的所有 commits,而这些分支在它自己的存储库中还没有。这些提交带有任何必要的快照文件,几乎是一种副作用。最后,您的 Git 获取其 Git 的分支名称并重命名它们,将这些分支名称转换为您自己的远程跟踪分支名称。

    如果遥控器被命名为origin,他们的(来源)主人将成为你的origin/master。你得到了他们所有的提交,除了你已经拥有的。你已经拥有的,你已经拥有了。您的 Git 可以确定您拥有它们,因为您拥有 ID。每个提交的 ID 对于该提交都是唯一的,并且该提交是永久且不变的——因此,如果您拥有他们所拥有的 相同 ID,那么你们俩必然拥有相同的 commit .

    你的 Git 和他们的 Git 使用 git push 非常相似,但在另一个方向上,并且有一个转折:你的 Git 给他们你的提交——你拥有的那些,他们没有,然后问他们设置他们的 master,或者你正在推送的任何分支,设置为它的提示提交,与你的 master 的提示相同的提交。这里没有重命名:您要求他们将master 与您的master 完全相同。

    当您 git fetch 时,您的 Git 重命名它们的分支名称,因此将它们全部使用是安全的。不管他们对他们的 分支做了什么,这不能影响你自己的分支名称。但是当您git push 时,您的 Git 会要求他们设置他们的分支名称,根本不需要重命名。如果他们不喜欢请求的设置,他们可以说“不,我不会设置”:他们可以拒绝您的推送。 fetch 不会发生这种情况,这就是您最初的问题所在。

    git pull = git fetch + 其他东西

    获取只是让您获得他们的新提交。 因为git fetch从不接触自己的分支,所以你经常想要第二步。

    这里的主要问题是 正确 采取的第二步取决于您引入了哪些提交,以及您已经拥有哪些提交。有两个主要选项:git mergegit rebase。您可以对 Git 进行编程以使 git pull 执行任一操作。默认是git merge

    同样,“正确”命令取决于您在分支中拥有的内容、获取时从远程获取的内容以及您希望如何工作。在实践中,大多数人在这里大多想要git rebase,但git pull 默认运行git merge。在许多情况下,两个命令最终都会做同样的事情,因此默认是 wrong 命令并不重要。但我建议新手避免使用git pull,因为它确实默认是大多数人想要的命令,而且因为当事情出错时——他们总是最终会这样做——通往的方法从问题中恢复取决于您是否知道自己运行了git rebasegit merge。如果你真的直接使用它们,你就会知道。

    【讨论】:

      【解决方案2】:

      使用“git pull --rebase”将您的更改从远程同步到本地。

      这是 git fetch 的答案 git fetch 实际上只从远程存储库下载新数据 - 但它不会将任何这些新数据集成到您的工作文件中。 Fetch 非常适合让您重新了解远程存储库中发生的所有事情。

      Git checkout ,用于切换存储库的分支。 只需谷歌,您就会获得大量信息:。

      【讨论】:

      • 但它不会将任何这些新数据集成到您的工作文件中然后我对现有文件中的这三个更改感到满意。但是 GIT FETCH 应该在本地提供一个新创建的文件。不是吗?
      【解决方案3】:

      正如您所提到的,git fetch 只是将更改从远程获取到您的本地计算机。它不适用于它们。

      git checkout MY_REMOTE/master 将获取的更改应用于文件的本地副本。 警告:如果您的本地文件已被修改(且未提交),您的本地更改将在您键入 git checkout MY_REMOTE/master 时丢失。

      同时应用远程和本地更改

      • 提交您的本地更改:git commit -a -m "my commit"
      • 应用远程更改:git pull origin master

      这将合并两个变更集(本地和远程)

      或者,您可以使用pull --rebase origin master 首先应用本地提交,然后应用远程提交。

      另见this answer

      【讨论】:

      • GIT FETCH :您通过 fetch 将更改下载到本地分支。 Fetch 向远程仓库询问其他人已提交但您在本地仓库中没有的所有提交。 Fetch 下载这些提交并将它们添加到本地存储库。 这正是我要问的问题。如果我在远程仓库中添加了一个新文件,为什么当我执行 GIT FETCH MY_REMOTE master 时它没有显示在我的本地仓库中?
      • 最好说git fetch 获得commits,而不是changes。 Git 存储快照,而不是变更集。 (区别有点技术性,只有有时重要,但当它很重要时,它可能会变得非常重要,所以最好从正确的想法开始。)跨度>
      【解决方案4】:

      确保添加所有文件并提交。 git add . && git commit -m "<your_message>"

      同时检查 coc-setting.json 中的任何设置

      【讨论】:

        猜你喜欢
        • 2014-02-14
        • 1970-01-01
        • 2022-01-24
        • 2021-07-04
        • 2019-07-18
        • 1970-01-01
        • 2010-11-27
        相关资源
        最近更新 更多