将 Git 主分支回滚到主分支历史记录中的特定提交

7
我在git仓库中有以下最近的历史记录:
* 7661a06 (HEAD, origin/devConsolidate, devConsolidate) Fix seg fault; OCBA intermediary compares by value() now also
| * 0bbe038 (origin/master, master) Flawed work no seedShift
|/  
* 62fe9db Turn on OCBA_DEBUG; nan/inf values in OCBA prior to crash
* 71298c8 Turn on OCBA (non-intermediary); seg fault occurs
* 3693904 No OpenMP, no OCBA; no memory leaks on valgrind
* 9d5686c Disable OpenMP threads
* 80bbc3b Debug (-O0) build now throws exception also
* e148013 Post convert simulation4_NEJMdisutilities [] to at()
* 66cfba9 Post convert OCBA [] to at()
* 32db3be Pre convert OCBA [] to at()
* 4a9f25b Prep for debugging
* 907e88b Found error (vector out of bounds); need to fix from here
* ca6c639 Implement elapsed, iteration, and max time in OCBA
* db68c15 Fix SEG FAULT; OCBA now working (with intermediary)
* f1c6f05 GA now uses OCBA; GA/OCBA params from config file; produces SEG FAULT
| * 3b16dcf (origin/genCRNgraph, genCRNgraph) Generate QALYs test and control independent-sampling
|/  
*   001eff2 Merge branch 'OCBAdev'

f1c6f05之后的所有提交(子孙节点)都是为了调试问题而进行的。事后来看,我应该创建一个单独的分支来进行这个调试,但我在master上全做了。现在,在提交7661a06中,我已经修复了这个bug。
我想移动(或回溯)master分支(或指针),使它位于提交f1c6f05处。在这样做之后,我就可以从提交7661a0662fe9db之间的差异中生成补丁,并将其应用到f1c6f05上。因此,我的Git日志的一部分应该如下所示:
* 7661a06 (origin/devConsolidate, devConsolidate) Fix seg fault; OCBA intermediary compares by value() now also
| * 0bbe038 Flawed work no seedShift
|/  
* 62fe9db Turn on OCBA_DEBUG; nan/inf values in OCBA prior to crash
           .
           .        
           .
* db68c15 Fix SEG FAULT; OCBA now working (with intermediary)
| * <HASH> (HEAD, origin/master, master) Fix problem and rewind master
|/
* f1c6f05 GA now uses OCBA; GA/OCBA params from config file; produces SEG FAULT
| * 3b16dcf (origin/genCRNgraph, genCRNgraph) Generate QALYs test and control independent-sampling
|/  
*   001eff2 Merge branch 'OCBAdev'

我需要使用哪些命令来完成所有这些任务?具体来说,我应该如何:(1)移动主分支,(2)生成补丁,以及(3)应用补丁?

2个回答

12

因为你已经将master推送到了origin(origin/master0bbe038处),这将会给那些已经从origin进行了拉取或获取的人造成问题。所以,你可能需要与其他人沟通并协调,让他们根据需要进行调整。

尽管如此,以下是您应该如何操作:

1) 将master回滚至f1c6f05:

git checkout master
git reset --hard f1c6f05
git push -f origin master

如果假设7661a06是你修复代码的唯一关联提交,那么与其生成和应用补丁,你可以简单地执行以下操作:

(2+3)

git checkout -b bug-fix-branch master
git cherry-pick 7661a06

可能会出现一些小冲突,具体取决于所有“debug”提交到底做了什么,以及它们是否接触到了7661a06提交所更改的附近内容,但这些应该很容易解决。完成后,请执行以下操作将此更改合并回主分支:

git checkout master
git merge bug-fix-branch
git branch -d bug-fix-branch    # optional, maybe not desired
git push origin master

此时,其他所有人都需要获取/拉取新的master分支,并重新开始他们正在进行的任何工作。

如果影响到其他人不可接受,您也可以选择执行以下操作:

git checkout master
git revert f1c6f05..62fe9db
git push master

这将在主分支上创建新的提交,撤销所有那些“debug”提交所产生的影响,但实际上不会从历史记录中删除它们。因此,您的工作目录的最终内容应该看起来相同,但历史记录将看起来非常不同。在这种情况下,对其他人没有影响,因此根据您的环境/工作流程,这可能是更好的选择,但它确实为后代记录了错误,并且如果您需要使用git bisect跟踪新错误或其他问题,可能会引起混淆/问题...


哦,我忘了提到这是一个私有仓库。没有其他开发者。 - synaptik
好的,这种情况下,“origin”可以是“备份”存储库或只是另一个系统上的存储库副本(例如台式机与笔记本电脑)?在任何情况下,使用“git reset”和“git push -f”的麻烦应该是非常小的。但是,如果“origin”不是一个裸存储库,您可能会遇到另一个问题 - 在推送之前,您可能需要确保在那里没有检出“master”。 - twalberg
origin 只是我在私有的 GitHub 仓库中存储的一个备份。 - synaptik

1
git checkout master
git reset --hard f1c6f05
git rebase --onto master 62fe9db devConsolidate

如果您对 devConsolidate 的历史记录感到满意:
git checkout master
git merge devConsolidate

这会删除我的任何提交吗?(我不想这样。) - synaptik
1
使用Git删除提交记录真的很困难。所有这些提交记录仍然可以通过它们的哈希值进行访问(除非它们被垃圾回收,这至少需要30天)。重写历史(在这种情况下使用git resetgit rebase)总是创建历史的新版本并将指针(分支)移动到新版本。如果您想要一个对git resetgit rebase之前位置的引用,只需在那里放置一个分支:git branch foo。如果您忘记这样做,可以使用git reflog跟踪分支的历史。 - Peter Lundgren

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