在 Git 中,日期并不重要。提交是真正重要的事情——更准确地说,是提交及其关系(不是日期,而是提交父/子关系)。
这里有一些措辞问题,因为“克隆”和“拉取”是具有精确(或半精确)含义的技术 Git 术语。让我们按照出现的顺序来看看:
所以我做了一个 git pull 来克隆最新的 repo ...
这没有意义。您可以克隆一个存储库:
git clone <url>
买一个新的;或者您可以进入您已有的存储库,并要求它更新内容:
cd existing-repo
git ... # many use pull here, but that's a mistake, in my opinion
猜猜#1
对于这一部分,我猜你的意思是你运行了git clone 并创建了一个新的存储库,它是给定<url> 的某个上游存储库的克隆。我们称这个全新的副本 R(用于存储库)。它有一堆提交,都是从上游克隆的。它没有你自己的提交。
我从 2015 年 3 月 6 日的 repo 获得了 file.txt,我对其进行了更改,但我没有 repo 的副本。
所以,除了这个新克隆的存储库 R 之外,您在任何地方都没有提交。您只是在 R 之外的某个地方保存了一个文件。 (运气好的话,你仍然有这个文件的干净保存版本。)
我需要合并最新的 repo 对 file.txt 所做的更改。
现在您遇到了一个中等规模的问题,因为您不知道您原来的file.txt 来自哪个提交。 Git 存储库存储提交,它们是完整的快照,而不是变更集。自从您从某个提交中复制 R 后,您无法轻松找到他们进行了哪些提交,因为您没有该原始提交的 ID。
(您可以将您保存的file.txt 与他们最新的file.txt 进行比较,这可能是一种方法。)
如何让 git 知道 3/6/15 的 file.txt 实际上是 2/1/17 存储库中的 file.txt 的旧版本并将它们合并?
你没有。日期根本不重要;合并需要每个文件的三个版本:
-
基础版本,您和他们开始使用的版本;
- 您当前的版本(日期无关,只是“您的最新版本”);和
- 他们当前的版本(日期再次无关)。
Git 或任何三向合并系统此时可以做的就是进行两个比较:
-
你改变了什么?也就是我们如何修改基础文件来生成你的文件?
-
他们改变了什么?也就是说,我们如何修改基础文件以拿出他们的文件?
然后系统可以组合这些更改。
但你刚才说你只有一个 file.txt。大概,那是你最新的。您需要两个版本:基本版本和最新版本。
如果您确实拥有这两个版本,则可以回避 Git 所做的大部分工作,而只需使用文件级合并(Git 将其作为一种辅助程序包含在内):
git merge-file --diff3 my-latest-file.txt base-file.txt their-file.txt
(这都可以在任何存储库之外完成)。这可能存在合并冲突——您更改了某些内容的地方,他们更改了某些内容,并且合并算法无法确定要保留两个不同更改中的哪一个。在这种情况下,文件以冲突标记包围的两个更改(以及--diff3 和基本文本)结束,因此当您编辑文件时,您可以找到冲突,并决定如何解决它们。
猜猜#2
也许您确实有两个保存的file.txt 版本:您从它们那里获得的原始基本版本(在您随后删除的克隆中)和您当前的版本。在这种情况下,您也许可以更直接地使用 Git。您需要做的是在您为自己创建的新分支上进行包含您的版本文件的提交。
困难的部分是您需要将这个新分支从原始file.txt 位于该存储库中的位置分离出来。这意味着您必须找到包含原始 file.txt 的提交的 ID。
有一些面向脚本的方法可以找到此类提交(在这里您可以实际上使用 Git 保存的时间戳来加快搜索此类提交的速度)。因为提交存储快照,所以可能有 许多 个提交以这种形式包含此文件,具体取决于它随时间变化的程度。如果您知道要使用哪个 Git 哈希 ID,或者知道可以解析为正确 Git 哈希 ID 的标签名称,那将是最好和最简单的。但如果没有,请参阅Which commit has this blob?
cd R # enter the repository you cloned
git checkout <hash> # get detached HEAD on the correct commit
... check to make sure file.txt is the right one ...
git checkout -b personal-branch
这最后一步创建了一个新分支,以便您可以将file.txt 的您的 版本复制到适当的位置并提交:
cp /path/to/my/version/of/file.txt file.txt
git add file.txt # tell Git to save this one
git commit -m 'update as of 2/6/17' # or use a better commit message
现在您有了自己的分支,拥有自己的提交,所以现在您可以让 Git 将您的工作与他们的工作合并:
git checkout master
... make sure file.txt is theirs ...
git checkout personal-branch
... make sure file.txt is yours ...
git merge master # get every change they made and merge with ours
这可能存在合并冲突(与您使用 git merge-file 看到的相同),您必须像以前一样解决这些冲突。如果是这样,您必须运行 git commit 来保存合并结果。如果没有,git merge 会为您运行 git commit。无论哪种方式,您现在都可以为新提交输入提交消息。
猜猜#3
在这里,我假设您确实运行了git pull。所有git pull 都运行git fetch,然后是git merge。这里的问题是您只能在现有存储库中运行git pull,然后您说您没有。要使用git pull,您必须拥有一个。
如果您有有一个,它在git merge 之前有哪些提交?您可以从这些提交中获得此 file.txt 的哪些版本?也许其中一个 提交具有易于识别的基本版本,这将允许您自己进行三向合并,或者像猜测 #2 那样进行新的提交,并让 Git 进行三-为你合并。