简而言之:
一种解决方案是使用嫁接连接历史,然后git filter-branch
根据这些嫁接重写历史,然后可选地进行合并。
请注意,在原始存储库( rebase解决方案)的新开发之上重放您的更改(您的提交)的解决方案是另一个可行的解决方案。
更长的版本:
假设您记得,或者您可以通过检查源代码和/或使用 git 命令找到您下载快照的存储库的修订版,并开始本地开发。让我们将此修订称为 START 或 A。
假设您本地断开连接的历史记录在原始存储库的克隆中。这意味着您的本地断开连接的开发与项目的完整历史记录在同一个存储库中。假设您的本地分支位于分支“master”中(为简单起见,只有一个分支)。
如果您没有使用本地断开连接的工作将项目提取到存储库中,您可以这样做:
$ git remote add origin git://github.com/mojombo/mojombo.github.com.git
$ git fetch origin
历史现在如下所示:
*---*---*---*---*---A---*---*---*---* <--- origin/master(远程跟踪分支)
x---y---*---*---* <--- master(你的本地断开连接历史)
上图中名为 A 的提交是您作为快照下载并开始本地开发的 START 提交。
有两种可能性:您已将“A”的快照作为初始提交“x”提交,或者您所做的第一次提交是本地修改。
在第一种情况下(您提交了原始起始状态,例如“初始提交”或“导入”),您希望连接的历史看起来像这样:
*---*---*---*---*---A---*---*---*---* <--- origin/master(远程跟踪分支)
\
\-y---*---*---* <--- master(你的本地断开连接历史)
即你的第一个原始提交'y'让'A'作为父母。
在第二种情况下(您提交了更改),您希望连接的历史看起来像这样:
*---*---*---*---*---A---*---*---*---* <--- origin/master(远程跟踪分支)
\
\-x---y---*---*---* <--- master(你的本地断开连接历史)
即,您希望首先提交“x”以将“A”作为父级。
在这两种情况下,您都希望找到提交“A”的完整 SHA-1 标识符,以及提交“x”和“y”的完整 SHA-1 标识符。
您可以使用git rev-parse找到提交“A”的 SHA-1(假设您还不知道):
$ git rev-parse A # or A^{commit}
437b1b20df4b356c9342dac8d38849f24ef44f27
(可能需要 '^{commit}' 后缀来确保您找到提交SHA-1,例如,如果您通过其标签知道“A”,例如“v0.99”,这很重要;在您的情况下,它是没有必要,因为有问题的存储库不使用标签)。
您可以使用git rev-list找到提交“x”和“y”的 SHA-1 (假设您的开发是在分支“master”上完成的):
$ git rev-list --topo-order master | tail -2
8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68
e83c5163316f89bfbde7d9ab23ca2e25604af290
(“ | tail -2
”在这里是为了在生成的列表中找到最后两个提交;如果你没有它,你不需要使用它)。
注意: 在上面的所有示例中,完整的 SHA-1 都是示例,不应按原样使用!
让我们将您希望将“A”(或“START”)作为父级的提交命名为 FIRST(根据您的情况,它将是“x”或“y”,如上所述)。现在我们使用移植机制连接历史:
$ echo "<SHA-1 of FIRST> <SHA-1 of START>" > .git/info/grafts
然后你应该检查你现在是否已经正确连接(加入)历史,通过使用图形历史浏览器,如 gitk,或 QGit,或 GitX,你是在 MacOS X 上,甚至是“ git log --graph
”,或“ git show-branch
”,例如:
$ gitk master origin/master # or --all
(此处 gitk 仅作为示例;如果您使用“ git show branch
”,则并不总是可以使用 ' --all
' 选项)。
最后,我们可能希望使这些更改永久化,因此从我们的存储库中获取的任何人也将具有关联的历史记录。我们可以使用git filter-branch来做到这一点:
$ git filter-branch master
您将在“refs/original/master”中拥有原始(断开连接的)历史记录。
现在您可以删除移植文件:
$ rm .git/info/grafts
现在您将能够合并原始存储库的新开发:
$ git merge origin/master
设置每个分支的配置,以便在分支'master'上拉(合并)原始(al)存储库中的更改时只需执行“git pull”就足够了,留给读者练习......: - )
注意: rebase 解决方案将导致以下历史记录(假设我们有第一次提交是简单导入的情况):
*---*---*---*---*---A---*---*---*---* <--- origin/master(远程跟踪分支)
\
\-y'---*'---*'---*' <--- master(你的本地断开连接历史)
(其中y'
意味着提交y
被修改:它应该是相同的变更集,但它与提交不同)。