我试图通过嫁接历史将2个存储库合并为1。我认为这是获得干净线性历史的最简单方法。
我试过将另一个作为远程数据库添加到初始存储库中来实现:
git init
echo "Hello" > Hello.txt
git add -A
git commit -m "initial commit"
git remote add b c:\pathToB
git replace --graft master b/master
树看起来不错,问题是我没有在当前目录中获取repo B的内容。
我也试过这个(提交哈希是b / master的提示)
git filter-branch -f --parent-filter 'sed "s~^\$~-p b34fc98295273c41aeb203213ad5fe4f95ba205b~"'
当我检查树时,我可以看到每个提交都包含它的更改,但主repo中的第一个提交基本上是删除了repo B带来的所有更改:
原始提交都没有删除文件。
我错过了什么,我使用过滤器分支和移植物错了吗?或者我是否只需要使用cherry-pick或rebase来保留当前目录中的所有更改?
答案 0 :(得分:1)
你需要结合树木。例如,您可以使用git merge
。如果你的Git足够新,你将需要--allow-unrelated-histories
标志。这样的合并将使用空树作为合并基础,因此它认为从merge base到 L 的更改是"在commit L 中添加所有文件"并且从合并库到 R 的更改为"在commit R "中添加所有文件(其中 L 和 R 的定义方式我想为git merge
定义;请参阅,例如this answer)。
提交是快照。 (这部分,我希望,没有争议。)
Git的git replace
个对象实际上是替换。也就是说,每当Git要通过其哈希标识1234567...
(或其他)查找对象时,Git会首先检查:是否在1234567...
中为refs/replace/
列出了替换项?如果有这样的替换,Git会通过将refs/replace/1234567...
解析为不同的哈希ID并读取该对象来读取替换对象。
所以:
git init echo "Hello" > Hello.txt git add -A git commit -m "initial commit"
此序列首先创建一个新的,完全空的存储库(假设还没有Git存储库,以便git init
进行创建)。 echo
命令在工作树中创建一个文件; git add -A
将工作树文件添加到索引(其副作用是将文件的数据作为 blob 对象存储到存储库中,尽管这样做了这里不重要)。最后一步git commit ...
创建一个树对象来保存快照 - 其中包含一个文件Hello.txt
,其中包含您放入其中的内容 - 然后创建一个提交对象,例如1234567...
,将您列为作者和提交者,具有消息" initial commit",使用创建的树来保存快照,并且 - 因为它是第一个commit ever-没有父提交:它是一个新的root提交。
现在我们有:
git remote add b c:\pathToB
这只会为新的远程fetch
添加网址(和b
设置)。
缺少一步:
git fetch b
调用另一个Git(在本地机器上c:\pathToB
是本地的 - 通常我们会在另一台机器上调用Git,通过HTTPS或SSH或其他类似的,但这很好)并且从中下载对象。具体来说,它获得了他们没有提交的任何提交(这是他们的所有提交)以及完成这些提交所需的任何对象(这些提交都是他们的其他对象)并将它们复制到您的存储库中。这些都有一些 not 1234567...
的ID,因为每次提交都有一个保证唯一的哈希ID。
最后:
git replace --graft master b/master
这告诉你的Git设置其中一个替换。特别是,它表示它应该将master
标识的提交(我们上面已经说过1234567...
)复制到就像原始的,除了它有一个父哈希,它是提交b/master
标识的任何东西。让我们说b/master
标识提交fedcba9...
。
让我们说git replace
提交的新提交具有ID 8888888...
。其内容如下:
1234567...
复制或重新创建(这并不重要); 1234567...
复制或重新创建的日期戳(这并不重要); 1234567...
; 1234567...
复制的树(快照)(此部分至关重要);和fedcba9...
的父哈希。您现有的master
仍然标识1234567...
,但现在当您要求Git 显示您1234567...
时,您的Git会看到refs/replace/1234567...
存在并且说'不要使用那个,而是使用8888888...
而不是#34;。因此,您的Git会查找对象8888888...
,并找到您使用1234567...
保存的树,其中只有一个文件。在之前提交 - 替换为1234567...
替换 - 具有不同的文件,因此从那时到现在的更改必须是:删除所有这些文件,并创建Hello.txt
代替。
要使下一个保存的快照以某种方式使用两个树,您需要将master
的树与{{1}的树结合使用}}。这永远不会是b/master
(尽管它是git replace
还是其他/不同的东西取决于你)。