gpt4 book ai didi

svn - 如何将历史记录添加到Git存储库?

转载 作者:行者123 更新时间:2023-12-02 09:29:18 25 4
gpt4 key购买 nike

我有一个存在于两个SVN存储库中的项目。第二个SVN储存库是通过从旧SVN储存库的检出中添加储存库而创建的,而没有剥离SCM信息。文件的内容字节相同,但是没有关联的SCM元数据。

我已经使用了新的SVN存储库,并通过git-svn将其移植到Git存储库中。现在,我想导入旧的存储库,并以某种方式将其链接到新的存储库,这样我就可以看到两者的历史记录。是否有一种简单的方法,而无需手工将两个存储库缝合在一起?

最佳答案

另请参见:如何在我在github.com上创建的项目之上重播对本地Git存储库的提交?问题(和我的回答),尽管情况略有不同,但我认为。



您至少有三种可能性:


使用grafts合并两个历史记录,但不要重写历史记录。这意味着您(以及拥有相同移植的任何人)将具有完整的历史记录,而其他用户则具有较小的存储库。如果有人已经开始使用较短的历史记录在转换后的存储库上进行操作,这还可以避免历史记录重写的问题。
使用嫁接连接两个历史记录,并使用“ git log”或“ gitk”(或其他Git历史记录浏览器/查看器)检查其是否正确,然后使用git filter-branch重写历史记录;那么您可以删除嫁接文件。这意味着从重写的存储库中克隆(获取)的每个人都将获得完整的联合历史记录。但是,如果有人已经基于转换后的短期存储库进行了工作,那么重写历史记录就大不了(但是这种情况可能不适用于您)。
使用git replace合并两个历史记录。这将使人们可以选择获取refs/replace/(然后获得完整的历史记录)或不获取(然后获得简短的历史记录),从而选择是要完整的历史记录,还是仅需要当前的历史记录。不幸的是,这要求当前使用尚未发布的Git版本,开发版本(“主版本”)或1.6.5的候选版本之一。 refs/replace/层次结构计划用于即将发布的Git版本1.6.5。




下面是所有这些方法的分步说明:嫁接(本地),使用嫁接的重写历史记录以及refs / replace /。

在所有情况下,我都假设您在一个存储库中同时拥有当前和历史存储库历史记录(可以使用git remote add从另一个存储库中添加历史记录)。我还假定短历史存储库中的分支(之一)被称为“ master”,而您想要附加当前历史记录的历史存储库中的分支(“提交”)被称为“ history”。您将不得不替换自己的分支名称(或提交ID)。

查找要附加的提交(简短历史记录的根)

首先,您必须在要附加到完整历史记录的短历史记录中找到(的SHA-1标识符)提交。这将是短期历史中的第一个提交,即根提交(没有任何父母的提交)。

有两种找到它的方法。如果确定没有其他根提交,则可以使用以下拓扑以拓扑顺序找到最后一个(最底)提交:

$ git rev-list --topo-order master | tail -n 1


(其中 tail -n 1用于获取输出的最后一行;如果没有它,则不需要使用它。)

如果有可能进行多个root提交,则可以使用以下一种代码查找所有无父母的提交:

$ git rev-list --parents master | grep -v ' '


(其中 grep -v ' ',即单引号之间的空格,用于过滤所有具有任何父项的提交)。然后,您必须检查(例如使用“ git show <commit>”)那些提交(如果有多个),并选择要附加到较早历史记录的提交。

我们称这个提交为尾。您可以使用(假设更简单的方法对您有用)将其保存在shell变量中:

$ TAIL=$(git rev-list --topo-order master | tail -n 1)


在下面的描述中,我将使用 $TAIL来表示您必须替换当前(简短)历史记录中最底层提交的SHA-1 ...或允许shell替您替换。

查找要附加的提交(历史存储库的顶部)

这部分很简单。我们必须将提交的符号名称转换为SHA-1标识符。我们可以使用“ git rev-parse”来做到这一点:

$ git rev-parse --verify history^0


(其中,如果“ history”是标签,则使用“ history ^ 0”代替“ history”;我们需要提交的SHA-1,而不是标签对象的SHA-1)。同样,就像查找要附加的提交一样,让我们​​将此提交ID命名为TOP。您可以使用以下命令将其保存在shell变量中:

$ TOP=$(git rev-parse --verify history^0)


使用嫁接文件加入历史记录

位于 .git/info/grafts中的嫁接文件(如果不存在,则需要创建此文件,如果要使用此机制,则需要创建该文件)用于替换提交的父信息。它是基于行的格式,其中每行包含我们要修改的提交的SHA-1,后跟零个或多个以空格分隔的提交列表,这些列表是我们希望给定提交作为父级提交的;与“ git rev-list --parents <revision>”输出的格式相同。

我们希望没有父项的$ TAIL提交将$ TOP作为其单亲项。因此,在 info/grafts文件中,应该在$ TAIL提交的SHA-1行中用$ TOP提交的SHA-1隔开空格。您可以为此使用以下单行代码(另请参见 git filter-branch文档中的示例):

$ echo "$TAIL $TOP" >> .git/info/grafts


现在,您应该使用“ git log”,“ git log --graph”,“ gitk”或其他历史浏览器检查您是否正确加入了历史。

根据嫁接文件重写历史记录

请注意,这将更改历史记录!

要使嫁接文件中记录的历史记录永久存在,只需使用“ git filter-branch”来重写所需的分支即可。如果只有一个分支需要重写(“ master”),则可以很简单:

$ git filter-branch $TOP..master


(这将仅处理最少的提交集)。如果有更多分支受加入历史记录的影响,则可以简单地使用

$ git filter-branch --all


现在,您可以删除嫁接文件。检查一切是否都如您所愿,并删除 refs/original/中的备份(有关详细信息,请参见“ git filter-branch”的文档)。

使用引用/替换/机制

这是嫁接文件的替代方法。它具有可移植的优点,因此,如果您发布了简短的历史记录并且无法重写它(因为其他人基于他们的简短历史记录而工作),那么使用refs / replace /可能是一个很好的解决方案……至少当Git 1.6.5版本发布时。

refs / replace /机制的运行方式不同于嫁接文件:您可以替换对象而不是修改父级的信息。因此,首先您必须创建一个提交对象,该对象具有与$ TAIL相同的属性,但具有$ TOP作为父对象。

我们可以用

$ git cat-file commit $TAIL > TAIL_COMMIT


(临时文件的名称仅是示例)。

现在,您需要编辑“ TAIL_COMMIT”文件(看起来像这样):

tree 2b5bfdf7798569e0b59b16eb9602d5fa572d6038author Joe R Hacker  1112911993 -0700committer Joe R Hacker  1112911993 -0700Initial revision of "project", after moving to new repository

Now you need to add $TOP as parent, by putting a line with "parent $TOP" (where $TOP has to be expanded to SHA-1 id!) between 'tree' header and 'author' header. After editing 'TAIL_COMMIT' it should look like this:

tree 2b5bfdf7798569e0b59b16eb9602d5fa572d6038parent 0f6592e3c2f2fe01f7b717618e570ad8dff0bbb1author Joe R Hacker  1112911993 -0700committer Joe R Hacker  1112911993 -0700Initial revision of "project", after moving to new repository

If you want, you can edit the commit message.

Now you need to use git hash-object to create a new commit in the repository. You need to save the result of this command, which is the SHA-1 of a new commit object, for example like this:

$ NEW_TAIL=$(git hash-object -t commit -w TAIL_COMMIT)


(此处使用' -w'选项将对象实际写入存储库)。

最后使用 git replace将$ TAIL替换为$ NEW_TAIL:

$ git replace $TAIL $NEW_TAIL


现在,剩下的要检查的内容(使用“ git log”或其他历史记录查看器)是否正确。

现在,任何想要拥有完整历史记录的人都需要添加' +refs/replace/*:refs/replace/*'作为pull refspecs之一。

最后说明:我尚未检查此解决方案,因此您的里程可能会有所不同。

关于svn - 如何将历史记录添加到Git存储库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1220557/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com