git:追溯引入几次合并

git:追溯引入几次合并,git,Git,我试图通过将git应用于一个项目来学习git,在这个项目中,我已经跟踪了一段时间的远程代码库。 当我把所有东西都放到git中时,我只是为所有外部版本创建了一个remote分支,并将我的版本放在master上,因此当前我的存储库如下所示: master: A0---A1.0--A1.1--A2.0--A2.1-.... \ remote: B1----------B2-----------.... 我的问题是:如何追溯告诉git发生的合并

我试图通过将git应用于一个项目来学习git,在这个项目中,我已经跟踪了一段时间的远程代码库。 当我把所有东西都放到git中时,我只是为所有外部版本创建了一个
remote
分支,并将我的版本放在
master
上,因此当前我的存储库如下所示:

master: A0---A1.0--A1.1--A2.0--A2.1-....
          \                
remote:    B1----------B2-----------....
我的问题是:如何追溯告诉git发生的合并,使存储库看起来像这样(不应更改代码):

标准git免责声明:上述操作不会影响任何已发布的历史记录:)

编辑:下面是我如何按照Kevin的建议使用移植物完成的:

首先,我手动创建了.git/info/grafts,如下所示(所有条目都是sha1的):

然后,在检查情况是否良好(gitx)之后,我运行了
git过滤器分支
,没有参数

过滤器分支
将使嫁接永久化,并将原始提交的引用存储在
refs/originals/…
中,以允许您通过
git reset--hard refs/originals/refs/heads/master
退出。由于一切看起来都很好,我按如下方式清除了所有剩余物:

rm .git/info/grafts
rm .git/refs/originals

如果已经收集了垃圾,则需要执行git update ref-d refs/originals/refs/heads/master。

听起来像是您想要的。你可以为你想要的新合并创建嫁接(记住要在嫁接中包含原始父级!),当一切看起来都很好时,使用git filter branch(阅读手册!)将其保存在石头中。

你可以通过做一个交互式重基来完全伪造它,指定你想要编辑所有这些提交,并用以下内容对其进行修订:

git rebase -i A0 master
# change the lines for A1.0 and A2.0 to "edit"
# git stops at A1.0
git merge --no-commit --strategy=ours B1     # the SHA1 of B1, of course
git commit --amend
git rebase --continue
# git stops at A2.0
git merge --no-commit --strategy=ours B2
git commit --amend
git rebase --continue

每次停止时,从技术上讲,您是在合并,但是使用
ours
策略,它保留当前提交的所有内容。
--no commit
告诉git在提交之前停止。然后用合并修改当前提交(基本上是指替换),而不是像通常那样将合并作为单独的提交。塔达!A1.0已替换为具有相同树但具有附加父级的新提交
commit--amend
为您提供编辑消息的机会;您可能希望这样做,以便留下一些您所做的记录。

我知道这是一个老问题,但有一种更新的执行方法(从Git 1.6.5开始)

git替换--graft

SHA散列在哪里像一个符咒一样工作——我将在我的问题中添加伪代码以供参考(在注释中有点难)。git过滤器分支之后有一件事情看起来很有趣:
git分支-a
只显示
master
remote
,但gitx显示了一个悬挂的东西,看起来像A1.1中的分支(来自A1.0),A2.0和A2.1(标记为
refs/original/refs/heads/master
)。这是什么?有没有简单的方法删除它?@Janus:这是确保你不会真的搞砸的过滤分支。对于它重写的每个ref
refs/foo/bar
,它都会在
refs/originals/refs/foo/bar
中创建原始文件的副本。如果你意识到自己完全搞砸了,你所要做的就是
git重置--hard refs/originals/refs/heads/master
。如果您确认这一切都有效,那么您可以删除它们。如果只有一个,请使用git update ref-d refs/original/refs/heads/master。对于多个,使用手册页中的一行代码:
git For each ref--format=“%(refname)”refs/original/| xargs-n 1 git update ref-d
。有关更多详细信息,请参阅手册页。如果您尚未进行垃圾收集,还可以使用
rm-rf.git/refs/original
(垃圾收集后,它们将存储为所谓的“打包引用”,您需要使用update ref杀死它们)。谢谢!我一直在思考这些问题,但我没有想到,你可以在重新组合的基础上进行合并。现在我(认为)我已经学会了这一点,我将尝试grafts方法只是为了好玩:)我已经将Kevin的anwer标记为一个解决方案:你的anwer教会了我更多关于git的日常工作,但是关于grafts的信息比周围的交互回退要少:)@Janus:他的答案对我来说实际上是新的-其中一个是我的。很酷的东西。@Janus:至于能在重设基础时进行合并。。。你实际上可以做任何事。交互式重基只是尝试按顺序应用补丁,当你告诉它时停止,当你告诉它时挤压。一旦你让它停止,你可以做各种疯狂的事情来得到你想要的任何承诺。
rm .git/info/grafts
rm .git/refs/originals
git rebase -i A0 master
# change the lines for A1.0 and A2.0 to "edit"
# git stops at A1.0
git merge --no-commit --strategy=ours B1     # the SHA1 of B1, of course
git commit --amend
git rebase --continue
# git stops at A2.0
git merge --no-commit --strategy=ours B2
git commit --amend
git rebase --continue
git replace --graft <commit> <parent1> <parent2>