如何仅检出特定提交的内容?

How to checkout to the contents of a specific commit only?

我有一个 old_branch,我只在代码中的几个文件上做一些原型设计。我的 master 分支远远领先于 old_branch,所以当我

git checkout old_branch -- .

master我得到了很多对我的索引的中间提交。我知道如何使用语法提取我需要的文件:

git checkout old_branch -- file1
git checkout old_branch -- file2
...
git checkout old_branch -- fileN

但是当这些文件的数量很大时,任务就变得相当繁琐。

那么我怎样才能从 master 中获取这个特定提交的内容(old_branch 的提示),而不会在索引中看到中间的其他更改提交?

我可能会为此使用 cherry-pick

git cherry-pick old_branch --no-commit

--no-commit 选项会将 old_branch 引用的提交引入的更改应用到您的索引和工作目录,但它不会在 master 上创建提交。

在继续此操作之前,您需要在头脑中清楚几个 git 概念:

  • 一次提交包含当时存储库的完整快照,而不是一组更改
  • 分支只是指向提交(以及从那里到该提交的历史)的方便指针,而不是一组实际的提交

考虑到这一点,我们可以更明确地定义需求:

  • 从分支 old_branch(分支的“提示”)当前指向的提交中检出
  • ...那些被任何提交更改的文件...(更迂腐地说,那些与其父提交不同的文件)
  • ... 可从 old_branch 访问但无法从 master 访问(我们直观地理解为 old_branch 分支“上”的提交)

可能有多种方法可以做到这一点,但根据上述定义,我们可以将一些东西串在一起:

  • 正如您在问题中所说,git checkout old_branch -- 让我们检出选定的文件;重要的是为了我们的目的,它可以接受任意数量的参数
  • git diff --name-only 将为我们提供在某些提交之间更改的文件列表
  • 传递给 git diff 的特殊符号 master...old_branchas the manual puts it“查看包含和直到第二个的分支上的更改,从两者的共同祖先开始”;在这种情况下,它将找到 old_branchmaster 分支的点,并将其与 old_branch
  • 的当前尖端进行比较

最后一块拼图是 Unix 命令 xargs,它可以获取一个命令生成的值列表并将其转换为另一个命令的参数。所以我们最终得到这个:

git diff --name-only master...old_branch | xargs git checkout old_branch --

顺便说一句,这将用 old_branch 中的版本完全覆盖那些文件。我想你有充分的理由想要这个,但更常见的是想要应用 old_branch 中的 changes,这很简单:

git merge old_branch