从另一个分支获取文件的内容而不检查它

Get contents of a file from another branch without checking it out

我正在尝试从另一个分支获取文件的内容。
我正在执行以下操作:

git checkout branchB some_specific_file.cc  

当前分支不受影响。我怀疑原因是即使我做了 git pull 我也从未在本地检查过 branchB
如果我刚刚在回购协议中完成了一个 pull 但从未真正检查过另一个分支,这个命令有没有办法工作?
是否有等同于:

git pull  
git checkout branchB  
git checkout branchA  
git checkout branchB some_specific_file.cc 

实际上不必切换到分支,所以最后一个命令有效?

您可以运行 git fetch同步远程分支然后直接从origin/branchB

检出文件
git checkout origin/branchB some_specific_file.cc 

从远程分支获取特定文件的内容。
(假设 origin 是遥控器的名称)

TL;DR

我想你想要的是:

$ git fetch
$ git checkout origin/branchB -- some_specific_file.cc

背景

您在这里犯的根本错误是认为分支是有意义的。 :-) 或者更确切地说,分支名称 具有某种全球意义——但它没有!

git pull 命令是一种方便的操作:它首先 运行 是 git fetch,然后是 运行 第二个 Git 命令。默认的第二个命令通常是 git merge,但是 (a) 您可以更改它并且 (b) 有一些特殊情况。据说(但实际上)这很方便的原因是 git fetch 获得新提交 。它不会影响你的任何分支(它们是你的,它们不属于像origin这样的远程分支!)。 =83=]

通常,在您从 origin 等远程服务器获得新提交后,您会希望 将这些提交 (其中一些)合并到您的(某些)自己的分支机构。为此,您需要第二个 Git 命令,例如 git mergegit rebase。不过这里有很多小问题,比如:

  • 你怎么知道是合并、变基还是完全做其他事情?
  • 如果您想对 多个 分支进行操作怎么办?

git pull 便利命令将所有这些抛在一边,并向您保证,无论 git fetch 做了什么,您都 100% 确定立即 git xxx——您填写在 xxx 部分 before you fetch—是正确的答案!如果不是——根据我的经验,实际上 经常 ,那么 git pull 是错误的命令。

你在上面做什么

你上面这两个命令的顺序:

git pull
git checkout branchB

如果您还没有 branchB将为自己创建 新的 (本地)分支名称 branchB,指向 与现有 remote-tracking 名称 相同的 提交origin/branchB。那么:

git checkout branchA

让你回到你的(可能是现有的)分支 A,关于它我们稍后有更多要说的。最终命令:

git checkout branchB -- some_specific_file.cc

然后从名称 branchB 标识的提交中提取该特定文件。 (我在这里添加了 --——如果文件名类似于 git checkout 选项或分支名称,最好通过反射使用它;some_specific_file.cc 不会,所以它是安全的无论哪种方式。)

git pull = git fetch + git merge

git fetch 步骤让您的 Git 调用另一个 Git,通常是在您存储在 origin 下的 URL。他们的 Git 列出了 他们的 分支名称,以及哪些提交哈希 ID 与这些分支名称一致。你的 Git 然后确保你有这些提交,一旦你这样做,设置 你的 origin/* 名称 remember那些哈希 ID。

origin/*名字就是我所说的remote-tracking名字;Git称他们为remote-tracking分支名称。他们记得,对你来说,在你自己的 Git 存储库中,远程的分支名称所在的地方,是你的 Git 上次与他们的 Git.

交谈的地方

因此,由于 git pull 运行s git fetch,这具有更新您的 remote-tracking 名称的副作用。但是有一个问题:git pull,为了方便起见,限制了 git fetch 获取的名称集。

通常 git fetch 获取 all 它们的分支名称,更新 all 相应的 remote-tracking 名称。但是,当 git pull 中的 运行 时,Git 查看您的 当前分支的 so-called upstream 环境。通常 master 的上游是 origin/masterbranchA 的上游是 origin/branchA,依此类推。这些是您为他们的分支机构命名的名称。当git pull 运行s git fetch时,它说:只更新这个remote-tracking名字。

这最终意味着 git pullnotbranchB 上不会更新您的 origin/branchB,这(最终)是个大问题。 您需要颠倒命令的顺序:先检查 branchB,然后 然后 拉。 (或者,更好的是,避免 git pull,但稍等片刻。)

创建(本地)分支

git checkout 命令会将您切换到您已有的某个现有分支:

git checkout master
例如

会将您切换到您可能已经拥有的 master。但是,如果您还没有git checkout 将扫描您的 origin/* 个名字——remote-tracking (not-exactly-a-branch) 个名字——去掉 origin/ 部分后,看看是否有匹配的。

如果是这样,您的 Git 将 创建 具有 origin/ 版本的 new 本地分支名称本身就是它的 "upstream".

git merge 始终且仅在 当前分支上运行

git pull的最后一步通常是运行git merge。如果你 运行:

git checkout branchB
git pull

这意味着Git 应该:

  • 检查您现有的 branchB,或根据需要从 origin/branchB;
  • 创建它
  • 获取并更新 origin/branchB(仅限);
  • 运行 git merge 更新您当前的分支——branchB——使用其上游 origin/branchBgit fetch 刚刚更新。

合并步骤将使您的本地分支 branchB 得到更新。

所以一般来说,在git pull之前你必须git checkout branchB才能确保origin/branchB是(单身) remote-tracking fetch 更新的名称,然后您自己的本地 branchB 也会更新。

你不需要那个

但是您的任务不需要 任何。如果你只是 运行 git fetch,更新 all 你的 origin/* 名字,然后使用 origin/branchB 来识别包含你想要的 some_specific_file.cc 版本,你很好。因此我在顶部建议的最后一组命令。

git checkout target_branch -- file.cpp

这对我很有帮助,它使我免于签出整个分支然后重建项目。只需签出我需要的文件。避免了不必要的重建。非常感谢!