【问题标题】:git fetch, FETCH_HEAD and origin/mastergit fetch、FETCH_HEAD 和 origin/master
【发布时间】:2013-02-08 13:00:19
【问题描述】:

我对 git 很陌生,但我在使用简单的 fetch 操作时遇到了麻烦。

我正在尝试从同事的存储库中获取他的进度。起初我做了git fetch HEAD,这促使 git 下载了大约 350MB 的数据,所以我确信它做了一些事情。然而,origin/master 最终仍然指向同一个旧提交(实际上它的名称为 dev 但我将其称为 master - 他没有 master)。

之后我尝试了git fetch origin master,但它似乎没有做任何事情,它只更新了FETCH_HEAD。我标记了FETCH_HEAD 提交,这样我就不会丢失它,但我仍然希望有一个更新的远程分支。

出了什么问题?我无权访问远程存储库。我还能在家修吗?

【问题讨论】:

  • 是“起源”你的同事回购吗?
  • 注意:从 git 1.8.4(2013 年 8 月)开始,你应该不会有任何惊喜:git fetch origin master 将更新 origin/master!见my answer below

标签: git git-fetch


【解决方案1】:

从 git 1.8.4(2013 年 8 月)开始,git fetch 将更新远程跟踪分支!不仅仅是FETCH_HEAD

Jeff King (peff) 看到commit f269048

当我们运行不带参数的常规“git fetch”时,我们会根据配置的参考规范更新跟踪参考。
但是,当我们运行“git fetch origin master”(或“git pull origin master”)时,我们根本不会查看配置的 refspecs,而只是更新FETCH_HEAD

我们错过了更新“refs/remotes/origin/master”(或用户配置的任何内容)的机会。一些用户觉得这很令人困惑,因为他们想进一步与远程主机的旧状态进行比较,例如:

$ git pull origin master
$ git log HEAD...origin/master

但这假设你已经将你的 repo 设置为获取分支:

git config remote.origin.fetch

如果为空:

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

【讨论】:

  • Git 1.9/2.0(2014 年第一季度):git push 具有对称行为:github.com/git/git/commit/…
  • 如果远程跟踪分支更新了,那么现在 FETCH_HEAD 是不是没用了?
  • @BreakingBenjamin 不,您仍然可以在两个月前在github.com/git/git/commit/… (git fetch something && git merge --allow-unrelated-histories FETCH_HEAD) 中看到它。更一般地说,在合并情况下仍然需要它(github.com/git/git/commit/…
【解决方案2】:

你想做的是:

  • 为您的同事添加遥控器
  • 从他的存储库中获取更改
  • 创建一个引用他的远程分支的本地分支

大概您已经完成了第 1 步。但为了完整起见,它是:

git remote add coworker git://path/to/coworkers/repo.git

其中 URL 可以是 git 支持的任何 URL 格式。

现在您已经添加了遥控器,您想要获取他的更改:

git fetch coworker

这为您提供了他的每个分支的远程分支。假设他的分支叫做“仓鼠”。现在,为了完成工作,您创建自己的远程分支的本地副本

git checkout -b hamster coworker/hamster

这会创建并切换到一个名为 hamster 的分支。

从那时起,你可以在仓鼠身上工作,然后把它推给他

git push coworker hamster

第一次,然后只是git push

任何时候你想拉下并合并他的更改,你都可以这样做:

git pull

【讨论】:

    【解决方案3】:

    我对你使用的命令有点困惑。 HEAD 通常是 git 用来跟踪当前在工作目录中的提交的标签。 git fetch 命令需要 remoteremote commit 配置来了解您想要获取的内容。使用git fetch HEAD 将表明HEAD 是您存储库中的远程。该命令正常运行很奇怪。

    例如:git fetch HEAD 在我当前正在工作的存储库中导致以下错误

    fatal: 'HEAD' does not appear to be a git repository
    fatal: Could not read from remote repository.
    
    Please make sure you have the correct access rights
    and the repository exists.
    

    命令git remote 将列出所有遥控器,而git remote --verbose 将包括遥控器的地址。你能用它来看看你是否有一个远程定义为HEAD 以及你的朋友存储库的远程地址是什么?

    不过,我的问题放在一边,以帮助消除您的困惑。 git fetch ... 命令只更新远程引用——而不是你的本地引用。

    为了清楚起见,请查看存储库中的 .git 文件夹(默认情况下它是隐藏的,因此您可能需要取消隐藏它)。你会发现类似下面的文件夹结构

    working directory
    |=>.git
    |  |=>objects           <= contains data for each commit
    |  |=>refs
    |     |=>heads
    |        |-master       <= file containing current commit of local master branch
    |     |=>remotes
    |        |=>origin
    |           |-master    <= file containing current commit of remote origin's master branch
    |-FETCH_HEAD            <= file updated by `git fetch`, contains info of what was fetched
    

    假设您签出 master 分支,git checkout master -- git 将更改您的工作目录以匹配 'objects' 文件夹中的提交数据,该数据与 '.git/refs/heads/master' 文件中的提交值匹配.

    如果您随后git fetch origin master,“.git/refs/remotes/origin/master”文件将更新为远程源上主分支的提交——并且该提交所需的所有提交数据都已下载并放置在“对象”文件夹中。

    这里的重点是git fetch 不会更新您的工作目录,反映已签出的本地分支,git fetch 永远不会更新本地分支。

    需要使用git merge ...git rebase ... 来使用origin/master 中的更改更新本地master 分支。 git pull ... 同时执行 git fetch ...git merge ...git rebase ...,具体取决于选项和配置(git merge ... 是默认设置)。

    在所有这些解释之后,您希望能够查看从您的朋友存储库中获取的内容(如果有的话)。 git branch -avv 命令将列出所有本地和远程分支,以及提交号,如果是本地分支,则列出它正在跟踪的远程分支。

    要查看分支如何相互关联,我发现使用工具绘制存储库树图很有帮助。有几个可供选择,但我发现git log 命令就足够了;如git log --all --graph --oneline --decorate。公平的警告,对于大型存储库来说,这可能会很长并且令人费解。通过添加--simplify-by-decoration 参数可以获得更短的输出。

    总结一下:是否可以在家修复它取决于存储库中的信息。上述命令; git remote --verbosegit branch -avvgit log ... 应该让您了解存储库的当前状态。从那里您可以确定是否需要做更多的事情来使用git mergegit rebase 获取本地分支中的数据。

    与往常一样,如果您遇到麻烦,请将您学到的内容发回。

    【讨论】:

    • 你是对的。我实际上做的是 git fetch origin HEAD。我这样做是因为我不知道他是否正在更新他的 master 分支,所以我认为 HEAD 会引用他正在处理的任何分支。我还没有找到问题所在,但感谢您的帮助。
    • 赞成对细节的出色关注。“git pull ... git fetch ... 和 git merge ... 或 git rebase ...,取决于选项和配置 (git合并 ... 是默认值)。”
    【解决方案4】:

    git fetch 实际上并没有触及您的工作目录。它仅从远程获取最新更改。要实际更新您的当前状态,请使用git mergegit rebase。此外,您可以使用git pull,它的作用类似于git fetch + git merge 的快捷方式。

    merge 和 rebase 的主要区别在于,在某些情况下,merge 会创建一个具有累积状态的新提交(非快进合并)。恕我直言,这很糟糕,这让我想起了我使用 SVN 的时代。 Rebase 只是在指定提交的顶部重放您的更改,因此您的历史记录始终是线性的。请务必使用与您的同事相同的流程。

    我建议你阅读一些关于 git 和 git flow 的内容:must-read booka good article

    【讨论】:

      猜你喜欢
      • 2020-07-27
      • 2014-02-27
      • 2012-08-11
      • 2011-02-22
      • 2014-10-11
      • 2014-01-18
      • 1970-01-01
      • 2012-05-22
      相关资源
      最近更新 更多