如何连接两个 git 历史记录?

发布于 2024-09-09 10:13:17 字数 129 浏览 6 评论 0原文

我有两个相关的 git 存储库。也就是说,一个内容是另一个内容的前身。我想以某种方式将存储库 A 的完整历史记录添加到存储库 B 中,以便 A 的提示将成为存储库 B 的第一个变更集的父级?两者的历史都是相当线性的。

这可能吗?

I have two git repositories that are tangentially related. Namely, content of one was a predecessor of the other. I would like to somehow prepend the full history of depository A to the depository B, so that tip of A would be a parent of the very first changeset of repository B? Histories in both are pretty linear.

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

乞讨 2024-09-16 10:13:17

您可以尝试使用嫁接文件(.git/info/grafts),您可以在其中覆盖提交的父级(例如 projectB 的第一个父级为最新的projectA

另请参阅“什么是 .git/info/grafts for?" 和 "如何在前面添加过去到 git 存储库?”了解有关此操作的更多信息。


skalee 关于文章“Git 的评论 :嫁接存储库”(来自SO用户Ben Straub)具体的例子。

现在我们要做的是更改“nuevo”存储库中的第一个提交(“New commit #1”),以便其父级是最后一个提交在“旧”存储库(“旧#3”)中。是时候学点巫毒了:

git fetch ../old master:ancient_history

Git 允许您从任何其他 git 存储库获取数据,无论此存储库是否与之相关!杰出的!这给我们留下了这个:

在此处输入图像描述

请注意我们如何将旧的 master 分支重命名为cient_history。如果我们不这样做,git 就会尝试将两者合并,并且可能会厌恶地放弃。

现在我们还有一个问题。
这两棵树没有连接,事实上 git pull 根本无法获取cient_history 分支。我们需要一种方法来在两者之间建立联系。

Git 有一个称为移植的工具,它基本上伪造了两个提交之间的父链接。
要制作一个,只需按以下格式在 .git/info/grafts 文件中插入一行:

[ref] [parent]

这两者都需要是相关提交的完整哈希值。那么让我们找到它们:

$ git rev-list master | tail -n 1
d7737bffdad86dc05bbade271a9c16f8f912d3c6

$ git rev-parse ancient_history
463d0401a3f34bd381c456c6166e514564289ab2

$ echo d7737bffdad86dc05bbade271a9c16f8f912d3c6 \
       463d0401a3f34bd381c456c6166e514564289ab2 \
       > .git/info/grafts

在一行中,如 建议 作者:ssokolow

echo $(git rev-list master | tail -n 1) $(git rev-parse ancient_history) > .git/info/grafts 

那里。现在我们的历史记录如下所示:

在此处输入图像描述

克隆此存储库会产生以下结果:

在此处输入图像描述

糟糕。事实证明,移植只对本地存储库生效。我们可以通过明智地应用git fast-import


$ git fast-export --all > ../export

$ mkdir ../nuevo-complete

$ cd ../nuevo-complete

$ git init

$ git fast-import < ../export
git-fast-import statistics: [...]

在一行中,如 ssokolow建议)

git filter-branch $(git rev-parse ancient_history)..HEAD 

这有效地将我们的“假”历史链接转换为真实的历史链接。
所有工程师都必须从这个新存储库重新克隆,因为哈希值都会不同,但对于无停机和完整的历史记录来说,这是一个很小的代价。

在此处输入图像描述

作为 Qix 评论下面

fast-import 似乎只是导入 git 信息,但没有检查任何内容。
git init 最初将您置于 master 状态,因此您需要 git reset --hard HEAD快速导入<之后实际检查文件/代码>


You could try using the graft file (.git/info/grafts) where you could overwrite the parenthood of a commit (like the first of projectB having for parent the latest of projectA)

See also "What are .git/info/grafts for?" and "How to prepend the past to a git repository?" for more on this manipulation.


skalee comments about the article "Git: Grafting repositories" (from SO user Ben Straub) for a concrete example.

Now what we want to do is change the first commit in the “nuevo” repo (“New commit #1”) so that its parent is the last commit in the “old” repo (“Old #3”). Time for some voodoo:

git fetch ../old master:ancient_history

Git lets you fetch from any other git repository, whether this repo is related to it or not! Brilliant! This leaves us with this:

enter image description here

Note how we renamed the old master branch to ancient_history. If we hadn’t, git would have tried to merge the two, and probably given up in disgust.

Now we still have a problem.
The two trees aren’t connected, and in fact a git pull won’t even get the ancient_history branch at all. We need a way to make a connection between the two.

Git has a facility called a graft, which basically fakes up a parent link between two commits.
To make one, just insert a line into the .git/info/grafts file in this format:

[ref] [parent]

Both of these need to be the full hash of the commits in question. So let’s find them:

$ git rev-list master | tail -n 1
d7737bffdad86dc05bbade271a9c16f8f912d3c6

$ git rev-parse ancient_history
463d0401a3f34bd381c456c6166e514564289ab2

$ echo d7737bffdad86dc05bbade271a9c16f8f912d3c6 \
       463d0401a3f34bd381c456c6166e514564289ab2 \
       > .git/info/grafts

(in one line, as suggested by ssokolow)

echo $(git rev-list master | tail -n 1) $(git rev-parse ancient_history) > .git/info/grafts 

There. Now our history looks like this:

enter image description here

Cloning this repo results in this:

enter image description here

Woops. It turns out that grafts only take effect for the local repository. We can fix this with judicious application of git fast-import:

$ git fast-export --all > ../export

$ mkdir ../nuevo-complete

$ cd ../nuevo-complete

$ git init

$ git fast-import < ../export
git-fast-import statistics: [...]

(in one line, as suggested by ssokolow)

git filter-branch $(git rev-parse ancient_history)..HEAD 

This effectively converts our “fake” history link into a real one.
All the engineers will have to re-clone from this new repository, since the hashes will all be different, but that’s a small price to pay for no downtime and a complete history.

enter image description here

As Qix comments below:

fast-import appears to just import the git information, but doesn't check anything out.
git init originally puts you on master, so you need a git reset --hard HEAD to actually check the files out after you fast-import.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文