Git - 如何在不快速转发和合并为当前的情况下恢复以前的提交

Posted

技术标签:

【中文标题】Git - 如何在不快速转发和合并为当前的情况下恢复以前的提交【英文标题】:Git - How to restore a previous commit without fast forwarding and merge as current 【发布时间】:2021-09-05 15:47:02 【问题描述】:

我是 Web 应用程序的唯一开发人员。每天我都会使用定时任务添加新的提交并推送到主分支(即 git add . & git commit -m "scheduled commit" & git push)

我主要用它来保存每天的备份/版本历史记录,以防我需要恢复。

我的代码库有一个重大问题,我找不到错误,因此想从远程 master 分支恢复 20 个提交,但保留提交的历史记录,以便我可以慢慢添加回确保错误不返回的代码。

我已经完成了 git reset --hard hash ,它已将标头放回 20 次提交。 我现在如何将其合并为一个新的提交?

Git pull/push 将快进这额外的 20 次提交。我不想这样做。我希望代码与 20 次提交前的代码完全相同,作为新提交和最新提交。

git checkout 不起作用,因为它说我落后于 20 次提交。

git checkout hash 让我进入无头模式 - 我不太清楚这意味着什么。

【问题讨论】:

您可以从 20 次提交前创建一个分支,然后通过该分支找出错误所在。 git branch branchname <sha1-of-commit> 不是“headless”模式,而是“detached HEAD”模式。这只是意味着您正在查看历史中的一个特定提交,而不是在某个分支上。 (提交可以在许多分支上,或者根本没有分支,所以这没有什么特别之处。只是如果你在这种模式下进行 new 提交,它根本不会在任何分支上,所以以后很难或不可能找到,及时删除。) 【参考方案1】:

我的代码库有一个重大问题,我找不到错误,因此想从远程 master 分支恢复 20 个提交,但保留提交的历史记录,以便我可以慢慢添加回确保错误不返回的代码。

使用git bisect 可以更快地完成此操作。编写一个演示问题的测试程序,并且在问题出现时以非零值退出;当问题存在时,让程序退出零。那么:

查看分支提示并运行 git bisect start,然后运行 ​​git bisect bad 将提交标记为错误。 选择一些已知良好的提交标记为良好,例如返回 20 个提交。 (如果您不确定那个是否好,请检查它并运行您的测试。)假设您非常确定大约 20 次提交之前的提交是好的,请运行 git bisect good HEAD~20。 现在,使用您的测试程序来诊断提交的好坏,运行git bisect run <em>test_program arguments-if-any...</em>。 Git 将在第一次错误提交时自动归零。

更多详情,请参阅the git bisect documentation。如果很难自动化测试,您仍然可以使用git bisect 并手动测试每个提交。不过,最坏的情况下不必测试大约 20 个修订版,您只需测试大约 log220 或大约 5 个修订版。

(等分完成后,您将在错误提交时处于 detached-HEAD 模式。使用git show 查看提交本身。使用git bisect reset 回到分支提示,脱离分离- HEAD 模式。)

【讨论】:

【参考方案2】:

我最终发现了我的问题。这实际上不是代码库的问题。 我的 Web 应用程序是一个 Laravel 8 项目。

问题出在模块/供应商包之一。

不知何故,干预图像包已损坏(可能是额外的选项卡或空白),导致使用该方法的图像显示为空白。

恢复较旧的提交不会解决此问题,因为供应商文件夹不包含在 github 上(Git 忽略)。

幸运的是,我启用了 Windows 以前的版本,因此我可以重命名当前项目文件夹,恢复几周前的备份,然后对最新提交执行 git pull。由于供应商文件夹不受影响,因此已拉下最新代码,问题不再出现。

我仍然想知道如何将以前的提交恢复为最新的提交,以防我将来需要。

【讨论】:

请参阅How do I revert a Git repository to a previous commit? 了解您的辅助问题的答案。

以上是关于Git - 如何在不快速转发和合并为当前的情况下恢复以前的提交的主要内容,如果未能解决你的问题,请参考以下文章

在 Git 中,如何在不挑选新分支的情况下对历史中具有多个合并提交的分支进行 rebase + squash

Git:如何在不丢失当前分支的情况下克隆项目?

如何在不实际合并的情况下测试合并

如何在不进行任何更改的情况下恢复推送的合并?

Git如何在不提交当前分支的情况下切换到其它分支进行操作——git stash

如何在不使用 git 的情况下查看 git 对象和索引