编辑(下面的原始答案):让我首先将您的图形转换为文本,(我希望)没有拼写错误或其他严重错误。这就是您现在所拥有的,正如git log --graph --oneline 可能会显示的那样(尽管--graph --oneline 可能会选择稍微不同的提交顺序——图形查看器生成的蓝线和绿线可能按提交日期排序,而不考虑拓扑,而不是先按拓扑排序):
* cb420e0 (master, ...) evert "Update README.md"
* 7a16df4 Update README.md
* 7564754 Update README.md
* 214cd47 Update README.md
* d064f7c Merge pull request #6 from ...
|\
* | d936a24 Changing Run instructions
* | 2cbd7c2 Minor edits for Google Drive link
* | 1a3d871 Updated process documentation with google drive link
| * 0594132 (TrustM..., ...) Added some comments to various scripts.
| * 7e060c4 Updated the JSON dialogues and implemented the Trust mechanism
|/
* 4d7f49b Configured script inputs and enabled mouse during pause screen.
* 47d4161 Merge pull request #5 from ...
|\
| * e999b3d (origin/Trying...) Adjusted ray cast length to be more realistic.
| * 953e4c3 Fully functional dialogue system implemented.
* | 1f33079 updated wiki to reflect marking of prototype
| * 09e350b Added in most of the Yarn framework
| * 2dda031 fixed heirarchy of files
| * bf667cc Merge branch 'develop' of ...
| |\
| * | 79e068d Character placement
(我们看不到任何低于这一点的东西,尽管显然必须有更多的提交)。
我猜你想要返回的提交状态是2dda031 fixed heirarchy of files。
现在,最棘手的部分是这个状态“存在于”曾经显然是一个分支,在“Merge pull request #5 from ...”提交下。如果在还原过程中的某个时刻,您要运行 git revert -m <some-number> 47d4161,您将告诉 Git 将 47d4161 与它的第一个父级 1ff3079 或第二个父级 d999b3d 进行比较。这些差异中的第一个显示了自合并基础以来每次提交的效果——无论提交是什么:我们无法从图中的这个片段中看到它;我们需要更多的图表来找到它,因为它在“屏幕”的底部 - 这两个中的一个,另一个差异显示了自合并基础到另一个的每个提交的效果。所以用-m 1 回复基本上会带走以下效果:
* e999b3d (origin/Trying...) Adjusted ray cast length to be more realistic.
* 953e4c3 Fully functional dialogue system implemented.
* 09e350b Added in most of the Yarn framework
* 2dda031 fixed heirarchy of files
* bf667cc Merge branch 'develop' of ...
...
在使用-m 2的同时,基本上去掉了以下效果:
* 1f33079 updated wiki to reflect marking of prototype
...
(在这两种情况下,我们可能看不到更多的提交)。我很清楚你不想这样做,但我不确定。
但是请注意,如果您只是提取提交 2dda031 的内容,您仍然会失去 1f33079 的效果以及它下面的任何其他提交,因为您得到origin/Trying... 之前的几次提交的状态。
提交d064f7c 更简单,因为它只是从合并基础4d7f49b 合并d936a24 和0594132。如果你想撤销提交1a3d871+2cbd7c2+d936a24 的效果,你可以git revert -m 1 d064f7c。如果你想撤销提交的影响0594132+7e060c4,你可以git revert -m 2 d064f7c。但是由于您(大概)想要撤消所有这些的效果,因此单独撤消它们会更简单,完全跳过合并。
由于您可能还想通过214cd47 撤消cb420e0,您只需分别撤消这些操作。
如果您想保留1f33079 和更早提交的效果,请不要恢复它们。如果你想撤销它们的效果,你可以git revert -m 2 47d4161,它会一次性撤销它们。我怀疑你想要那个,但和以前一样,这取决于你。
请注意,任何还原都可以使用-n 运行(在索引和工作树中还原而不提交),但是一旦您开始了一系列-n 操作,您必须继续使用-n 并最终提交, 在您可以在没有 -n 的情况下开始新的还原之前。
根据您想要的结果,也许最简单的方法是首先提取提交47d4161 的内容 — 无需单独提交即可从尽可能远的位置提取树状态-backouts——然后在每个额外的提交上使用git revert -n 来恢复。要提取这些内容,您可以使用git checkout <commit> -- .,但有轻微的风险,即不会删除此后新文件的索引和工作树条目,也可以使用git read-tree --reset -u <commit> 来避免风险(请参阅下面的注释,在原始答案中,也)。我会选择后者,给出:
git read-tree --reset -u 47d4161
git revert -n e999b3d
git revert -n 953e4c3
git revert -n 09e350b
(当然,假设这会为您提供您想要的最终工作树和索引状态)。
(下面一行的原始答案。)
Git 的revert 不会将提交恢复到(这使得命令命名不当:它使用了错误的动词)。它的作用是退出(即“恢复”)一个特定的提交,或者可能是一组提交。1你已经中途了有2dda031..HEAD,因为这个范围语法实际上意味着HEAD ^2dda031,即从HEAD 可到达的所有提交的集合,不包括(减去,使用集合减法)从2dda031 可到达的所有提交的集合。
现在,由于合并,这里存在多个问题。第一个是排除2dda031 及其父级未能排除合并的另一端,因此您将恢复太多提交。第二个问题是,从某种意义上说,合并提交是一种提交,当它的单次提交更改时,“所有更改都由一个分支带来”。2 第三个是为了恢复合并提交,您必须指定要考虑的“边”,但为了恢复非合并,您不得指定任何“边”。
其中一些问题的解决方案是完全避免恢复合并,而其他问题的解决方案是在适用的情况下仅恢复合并。但是还有另一种更简单的方法,具体取决于您的实际目标:如果真的要恢复 to 提交,那么执行此操作的 Git 动词实际上是 git checkout——但有一些陷阱。请参阅this answer 到一个相关的(甚至可能是重复的,取决于您的目标)问题。 git rm -r . 的原因是删除当前索引中不会被 git checkout <hash> -- . 步骤提取的所有文件。
您可以使用一个快捷方式来代替git rm -r . && git checkout <hash> -- . 序列,它也不依赖于当前工作目录:您可以运行git read-tree --reset -u <hash>。这将丢弃索引的当前内容 (--reset) 并用指定提交的内容 (<hash> 参数) 替换它们,然后更新工作树以匹配,删除从索引中删除的所有文件并更新索引中更新的任何文件。
请注意,在所有情况下,最终结果都在索引和工作树中,但尚未提交,因此您必须运行 git commit。
请注意,如果您的目标实际上不是将 还原为 特定提交,而是还原引入的一系列更改,那么使用 git revert -n 的方法是根据需要使用尽可能多的单独的git revert 命令:每个要撤消的更改集一个。其中一些可能是git reverts 的非合并,一些可能是git reverts 的合并。不过,请参阅脚注 2,并记住无论您使用哪种方法,即使您想保留它,您想要保留的更改最终也会成功(更改将消失)。
1因此,其他一些 VCS 中的动词是“backout”。
2这个描述在一个微妙但非常重要的方面是错误的:合并 combines 变化。合并的输入是两组更改:一组从合并基础提交到 --ours 提交,另一组从合并基础提交到 --theirs 提交。这两个变更集可能重叠。如果他们这样做了,并且在任何时候重叠“足够相似”,Git 只需要 一个副本 的更改。如果 Git 获取了某个更改 Δ 的副本,其中 Δ 出现在两个更改集中,并且您还原了 --theirs 更改集,Git 会退出 Δ 即使它在 --ours 更改集中 (如果您退出 --ours delta,同样的推理也适用:Git 不应该,但确实将其从作为 --theirs 引入的版本中删除。)