存储库没有文件。存储库有提交。然后提交有文件,所以你可能会说这只是一个语义上的小问题,但这对答案至关重要,因为提交是包交易。
在这种情况下你可以做什么——注意我假设你已经用更新的文件提交了——是:
- 从另一个 Git 存储库 (
git fetch) 获取 提交;
- 使用
git merge 合并整个提交;然后
- 进行提交,主要使用合并结果,但保持您的特定文件完整。
在此过程中,您可以使用许多小调整。特别是,中间步骤——使用git merge——可以使用--no-commit 来完成,这样Git 会完成合并工作,但在进行合并提交之前会停止。通过像这样在合并过程中停止 Git,您可以让 Git 在由于无法自动执行合并而停止时的行为。您现在处于 Git 有一个未完成的合并的状态,而您的工作就是完成它。这使您可以完全控制作为合并结果进入合并的内容。
然而,通常情况下,最好只允许 Git 将此合并作为正常的日常合并,然后在恢复您的一个文件的合并之后构建一个新的提交。这会产生一个提交,在签出时,它的结果与修改后的合并相同,但将实际合并保留在历史记录中。 (请记住,Git 的提交是文件中的历史记录。您所做的任何提交都是历史记录。您不进行的提交(您先修改,然后仅进行修改后的提交)不会留下任何痕迹,因为 Git 存储库中的 only 历史记录是您可以在存储库中找到的一组提交。1)
换句话说,只要跑步就足够安全了:
git fetch
git merge
git checkout <commit-hash> -- path/to/C
git commit
如果您喜欢git pull,您可以使用git pull 通过便捷的git pull 命令组合获取和合并。 (这假设您尚未将 git pull 配置为运行 git rebase 作为其第二个命令。)
git checkout <em>hash</em> -- <em>path</em> 命令要求您找到一些历史提交,其中包含所需格式的文件。您可以使用git log 找到它。如果你的 Git 是 2.23 或更高版本,你可以使用git restore 代替git checkout;那么语法是:
git restore --staged --worktree --source=<hash> -- <path>
或者如果您喜欢输入更少的字符:
git restore -SW --source=<hash> -- <path>
如果您使用git merge --no-commit 方法,您仍然可以使用相同类型的git checkout 或git restore 命令替换文件,然后再使用git merge --continue 或git commit 完成合并。请注意,这种合并称为“邪恶合并”;见Evil merges in git?。
1这有一些技术例外,涉及 Git 的 reflogs 和“悬空”(未引用)提交。这些在普通的git log 命令中找不到,但可以找到一段时间。但这些最终会过期,只留下正常的提交。