在新的Git仓库上重新播放提交的最简单方法

26

我一直在使用git-svn,最近在尝试提交时遇到错误(我认为这是libneon中的一个bug导致的,但这超出了本问题的范围)。解决办法是使用git svn clone重新克隆我的git存储库。然而,在我的旧git存储库的主分支上有更改,我无法使用git svn dcommit提交到svn。我想在用git svn克隆的新存储库上重播这些更改。我认为我可以使用git format-patch导出一个补丁集,然后在新存储库上重播这些更改,但我不完全确定如何操作,我想知道是否有更简单或更优雅的方法来完成这个任务。

2个回答

56

从你的新仓库中,添加一个远程引用到你的旧仓库:

git remote add temp file:///path/to/old/repo/on/your/machine

从旧存储库获取:

git fetch temp

从旧仓库检出您的主分支:

git checkout temp/master -b wip

(wip代表进行中)

将更改的内容重新基于现有仓库中的内容:

git rebase master

将主分支指向您的新HEAD:

git checkout master
git merge wip

删除对旧存储库和使用的wip分支的远程引用:

git branch -d wip
git remote rm temp

你实际上在做什么:

首先,通过添加远程引用并拉取,你正在从以前的仓库中获取提交记录,这些记录你还没有在当前仓库中。Git知道如何做到这一点,因为无论提交记录在哪里或者如何产生,同一个提交记录在任何地方都是相同的。它是几个众所周知的信息块的SHA1哈希,包括目录树、提交者、时间戳等。

因此,当你基于同一个SVN仓库创建了一个新的Git仓库时,所有的提交记录都有相同的SHA1哈希值。因此,你拉取到当前仓库的新提交记录依然指向正确的内容。这非常酷,也很重要。

然后,你切换到temp的主分支的末尾,并告诉它在你当前的主分支上进行变基。变基可能是不必要的,因为SVN的主分支可能没有移动到旧仓库的主分支之外,但最好还是保险起见。

变基通过反向遍历历史记录,找到两个提交之间的共同祖先,然后将其切换到你指定的分支名称(在本例中为master),从你的原始分支中挑选每个缺失的提交记录。完成后,它将当前分支指向应用的最后一个提交。

最后,将主分支与wip合并只是为了快进主分支到末尾。因为这是一条直线,所以这只是一个简单的快进。你也可以轻松地进行变基或重置--hard;任何一种方法都可以将主分支更改为指向正确的位置。合并只是其中最安全的一种,因为如果发生了奇怪的事情,它会让你知道这不是一个简单的快进。


1
工作得非常完美,谢谢。我想更好地了解这里涉及的过程,所以你能高层次地解释一下它是如何工作的吗?特别是,我认为 git rebase master 会将 temp/master 中的更改回放到 master 上,但我不明白它是如何知道要这样做的。此外,在变基后合并 wip 的目的是什么?谢谢! - jbeard4

9
您可以:
  • 将旧的存储库添加为新存储库的远程存储库(git remote
  • 获取旧分支
  • 将您感兴趣的旧分支部分在当前的master上进行变基。
请参见如何挑选一系列提交并合并到另一个分支中
# go to your current but incomplete new master branch
git checkout master

# mark your current master HEAD as branch 'tmp'
git checkout -b tmp

# reset your master to the old one
git branch -f master oldrepo/master

# replay the right commits on top of 'tmp' (which was your master HEAD)
git rebase --onto tmp first_SHA-1_of_old_master_to_replay~1 master

# remove tmp branch, 
# your master HEAD is now on top of tmp, with the right commits replayed
git branch -d tmp

即使SHA1与您的旧master历史记录和第二个git-svn clone的新主人不同,该解决方案仍将起作用。这就是为什么我建议使用rebase --onto:如果由于任何原因,第二个git-svn clone未生成完全相同的SHA1,则两个master的历史记录可能没有共同之处。


我的SHA1校验和并不完全相同,而rebase --onto让我免于无尽的冲突之苦。谢谢! - Daniel Hershcovich
@DanielHershcovich:不用谢,感谢你的编辑(我已经批准了)。 - VonC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接