在新的 git 存储库上重放提交的最简单方法
我一直在使用 git-svn,最近,我在尝试提交时遇到错误(我认为这是由于 libneon 中的错误,但这超出了这个问题的范围)。解决方案是使用 git svn clone 重新克隆我的 git 存储库。但是,我对旧 git 存储库中的 master 分支进行了更改,无法使用 git svn dcommit 提交到 svn。我想在使用 git svn 克隆的新存储库上重播这些更改。我想我可能可以使用 git format-patch 导出补丁集,然后在新存储库上重播这些更改,但我不完全确定如何执行此操作,我想知道是否有甚至更简单或更优雅的方式来实现这一点。
I've been using git-svn, and recently, I've been getting errors when trying to commit (I think this is due to a bug in libneon, but this is beyond the scope of this question). The solution has been to re-clone my git repository using git svn clone
. However, I have changes on the master branch in my old git repository that I was not able to commit to svn using git svn dcommit
. I'd like to replay these changes on the new repository cloned with git svn. I think I could probably export a patch-set using git format-patch
, and then replay these changes on the new repository but I'm not entirely sure how to do this, and I wonder if there's an even easier or more elegant way to accomplish this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从您的新存储库中,添加对旧存储库的远程引用:
从旧存储库中获取:从
旧存储库中检查您的主分支:
(wip 代表正在进行的工作)
将更改重新设置为您的内容之上的更改当前存储库:
更新 master 以指向您的新 HEAD:
删除对旧存储库的远程引用和您使用的 wip 分支:
您实际在做什么:
首先,通过添加远程引用并获取,您将从中提取提交当前存储库中还没有您以前的存储库。 Git 知道如何做到这一点,因为无论在何处或如何进行,相同的提交在任何地方看起来都是相同的。它是一些众所周知的信息的 SHA1 哈希值,包括目录树、提交者、时间戳……
因此,当您基于同一个 SVN 存储库创建新的 Git 存储库时,所有提交都具有相同的 SHA1总和。因此,您提取到当前存储库中的新提交继续指向正确的内容。这非常酷,并且记住这一点很重要。
然后,您切换到 temp 的 master 分支的尖端,并告诉它重新建立到当前的 master 分支。变基可能是不必要的,因为 SVN 的 master 可能没有从旧仓库中的 master 移开,但最好是安全的。
变基通过回溯历史记录来找到两个提交之间最近的共同点,直到它们都指向同一个父提交。然后,它切换到您给它的分支名称(在本例中为
master
),并挑选原始分支历史记录中缺少的每个提交。完成后,它会指向您在应用的最后一次提交时开始时所在的分支。最后master与wip的合并只是为了将master快进到最后。因为是一条直线,所以实际上只是快进。您可以轻松地进行变基或重置 --hard;其中任何一个都会改变主分支以指向正确的位置。合并只是其中最安全的,因为如果发生了奇怪的事情,它会让你知道这不是简单的快进。
From your new repository, add a remote reference to your old repository:
Fetch from the old repo:
Check out your master branch from the old repo:
(wip stands for work-in-progress)
Rebase the changes on top of the stuff in your present repository:
Update master to point at your new HEAD:
Delete the remote reference to your old repo and the wip branch that you used:
What you are actually doing:
Firstly, by adding the remote reference and fetching, you are pulling the commits from your previous repository which you do not yet have in your current repository. Git knows how to do this because, no matter where or how it was made, the same commit looks the same everywhere. It is the SHA1 hash of a few well-known pieces of information, including the directory tree, the committer, timestamp, ...
So when you created a new Git repository based on the same SVN repository, all the commits had the same SHA1 sums. As a result, the new commits that you fetched into your current repository continued to point at the right stuff. This is very cool, and important to remember.
You then switched to the tip of temp's master branch and told it to rebase onto your current master. The rebase may have been unnecessary, as master from SVN may not have moved away from the master in your old repo, but it was best to be safe.
A rebase finds the nearest point of commonality between two commits by working backwards through their histories until they both point at the same parent commit. It then switches to the branch name you gave it (in this case
master
) and cherry-picks each of the commits that were missing from its history from your original branch. Once complete, it points the branch you were on when you started at the last commit it applied.Finally, the merge of master with wip was just to fast-forward master to the end. As it was a straight line, it really was just a fast-forward. You could have just as easily done a rebase or a reset --hard; any of these would have altered the master branch to point at the correct location. Merge was just the safest of these, because if something weird had happened, it would have let you know that it was not a simple fast-forward.
您可以:
git remote
)master< 之上重新调整您感兴趣的旧分支部分/代码>。
请参阅如何挑选提交范围并合并到另一个分支:
即使 SHA1 与您的旧
master
历史记录以及来自第二个git-svn 克隆的新 master 不同,该解决方案也将起作用。代码>.
这就是为什么我建议使用
rebase --onto
:如果出于任何原因,第二个git-svn 发生变化,两个
不会生成完全相同相同的SHA1。master
的历史可能没有任何共同点克隆You could:
git remote
)master
.See How to cherry pick a range of commits and merge into another branch:
That solution will work even if the SHA1 differs from your old
master
history and your new master from your secondgit-svn clone
.That is why I recommend a
rebase --onto
: the history of bothmaster
s might have nothing in common if, for any reason, the secondgit-svn clone
don't generate exactly the same SHA1.