添加原始哈希以在git rebase上提交(使用新根)

添加原始哈希以在git rebase上提交(使用新根),git,version-control,rebase,git-rebase,git-filter-branch,Git,Version Control,Rebase,Git Rebase,Git Filter Branch,我有一个过去用SVN管理的代码库,但现在用git管理。当代码迁移到git时,历史记录丢失了 我已经设法做到了,现在正试图git重新设置最近提交的内容的基础 我有两个分支,gitcommits,其中包含自迁移到git以来的提交,以及svncommits,其中包含较旧的历史记录。每个分支包含3000多个提交 我发现以下命令在旧历史的基础上构建新的历史(尽管有一些手动合并冲突处理): 有几个提交引用了提交散列,我知道在重新基址完成后,这些散列会发生变化。为了使这些信息不会永远丢失,我想将每个提交的原始

我有一个过去用SVN管理的代码库,但现在用git管理。当代码迁移到git时,历史记录丢失了

我已经设法做到了,现在正试图
git重新设置最近提交的内容的基础

我有两个分支,
gitcommits
,其中包含自迁移到git以来的提交,以及
svncommits
,其中包含较旧的历史记录。每个分支包含3000多个提交

我发现以下命令在旧历史的基础上构建新的历史(尽管有一些手动合并冲突处理):

有几个提交引用了提交散列,我知道在重新基址完成后,这些散列会发生变化。为了使这些信息不会永远丢失,我想将每个提交的原始提交哈希添加到新重定基础的提交消息中

这意味着像这样的原始提交:

commit aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Author: Boaty McBoatface <boaty@example.com>
AuthorDate: Wed Jul 27 00:00:00 1938 +0000
Commit: Boaty McBoatface <boaty@example.com>
CommitDate: Wed Jul 27 00:00:00 1938 +0000

Reticulate splines

The splines had been derezzed, and needed to be reticulated.
commit aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
作者:Boaty McBoatface
作者日期:星期三7月27日00:00:00 1938+0000
提交:Boaty McBoatface
委托日期:星期三7月27日00:00:00 1938+0000
网状样条
样条线已经去毛刺,需要进行网格化处理。
会变成

commit bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
Author: Boaty McBoatface <boaty@example.com>
AuthorDate: Wed Jul 27 00:00:00 1938 +0000
Commit:     Meshy <meshy@example.com>
CommitDate: Wed Nov 16 10:23:31 2016 +0000

Reticulate splines

The splines had been derezzed, and needed to be reticulated.

Original hash: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
提交bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
作者:Boaty McBoatface
作者日期:星期三7月27日00:00:00 1938+0000
提交:Meshy
委托日期:2016年11月16日星期三10:23:31+0000
网状样条
样条线已经去毛刺,需要进行网格化处理。
原始哈希:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

这可能吗?也许使用
git过滤器分支

时,答案可能取决于要重新设置基础的提交数量。
如果要重定基址的分支包含的提交数量相当少,且您可以手动编辑,则以下提示可能会起作用:

一般来说,交互式的基础应该对您有所帮助,我希望您不一定要进行分支过滤

r, reword = use commit, but edit the commit message
使用交互式重基,尝试通过在提交消息中插入原始哈希来重写每个提交

对于更大数量的提交,在3000个左右的情况下,让我们尝试使用筛选器分支:

git filter-branch --msg-filter 'cat && echo "Original hash $GIT_COMMIT"' HEAD~3000..HEAD
它将为您所在分支的过去3000次提交中的每一次提交生成新的提交,其中包含重写的提交消息。新提交消息的格式与此类似(请注意底部的提交哈希):

之后,您可以安全地进行重设基础。应该保留旧的提交哈希


Maciej

首先,请注意:确保您确实想要这样做,因为可以使用
git replace
(下面简要提及)以保留ID的方式将历史记录缝合在一起。当然,它也有自己的缺点;搜索使用过它的人的报告


是的,您可以使用
git filter branch
执行此操作

不过,您可能希望将“在新转换上重新设置新提交的基础”步骤与“…相结合,然后编辑所有新提交以同时包含其旧ID”步骤,因为重新设置基础通过复制提交来工作,而过滤分支通过。。。复制提交::-)

所有执行此类操作的Git命令都必须复制,因为每个提交的哈希ID都是提交内容的函数。如果新提交与原始提交在任何方面都不同,它将获得一个新的、不同的ID

git-rebase
git-filter-branch
之间的区别在于复制了哪些提交以及如何执行复制

如果不使用
--保留合并
,则可通过选择非合并提交列表,将每个此类提交转换为一个变更集(通过减法,或多或少:child减去parent=从父到子的增量),然后将此增量添加到
--到
点或到目前为止添加的提交

使用
--preserve merges
时,rebase仍会选择非合并提交的列表。然后,在有合并提交的地方,rebase重新执行合并(这就是为什么必须重新解决合并冲突)。它必须重新合并,因为新的基可能导致不同的合并,而且合并不能转换为单个变更集(“子-父”提供一个增量,但至少有两个父,因此至少有两个增量,在一般情况下,我们不能同时保留这两个增量)

过滤器分支使用完全不同的方法。无论是否为合并,都会选择要筛选的提交。(实际的选择是通过运行
git rev list
,这是相当于
git log
的“管道”来完成的)这个完整的提交ID列表被放置到一个堆中:一个存储在普通文件中的排序拓扑顺序堆,以便父提交总是在其子提交之前进行处理

然后,对于列表中的每个ID:

  • 将原来的提交一个la
    git checkout
    ,提取到一个没有底层git repo的临时树中

  • 应用树过滤器以修改树。(此修改在保存临时树的临时目录中运行。当许多人尝试访问像
    。/../fixed version
    这样的文件时,这一部分会使他们在执行第一个树筛选时出错。相对路径失败,因为临时树根本不在存储库中。)

  • 重建一组新的Git树和代表新树的blob对象,即新的提交快照

  • 将提交消息筛选器应用于消息

  • 将提交环境筛选器应用于其余的提交元数据(author和committer内容)

  • 使用新消息和新树进行新提交。或者,如果您提供了提交筛选器,则使用它进行提交或不进行提交;此时,还可以使用父过滤器修改新提交的父项

  • 拉斯维加斯
    git filter-branch --msg-filter 'cat && echo "Original hash $GIT_COMMIT"' HEAD~3000..HEAD
    
    commit 08ac9b84d820ec7b70fa53075adc06f0a8185ab4
    Author:
    Date:   Mon Nov 14 13:14:30 2016 +0100
    
     Adds javadoc
    
    Auto inserted text: ....
    Change-Id: ...dbf9497387a3c271ae0349822cb4b8...
    Original hash 9d01f3e5b39b15c9dbe923916b6c25019b5b9796
    
    $ git rev-parse svn-commits
    9999999999999...
    
    $ git rev-list --max-parents=0 git-commits
    11111111111111...
    
    --parent-filter 'if [ $GIT_COMMIT = 11111... ]; then
      echo -p 999999...; else cat; fi'
    
    Original hash: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    
    --msg-filter 'cat; echo; echo "Original hash: $GIT_COMMIT"'
    
    --msg-filter 'cat; echo; echo "new commit $(map $GIT_COMMIT) \
    filtered to reparent original commit $GIT_COMMIT"'