简体   繁体   English

Git恢复为先前的提交,但将新提交保留为未暂存

[英]Git revert back to previous commit but keep newer commits as unstaged

I have a Git repository whose commit history is the following: A -> B -> C ( C being the latest commit) and this entire history is pushed to a public remote repository. 我有一个Git存储库,其提交历史如下: A -> B -> CC是最新的提交),整个历史都被推送到公共远程存储库中。 Can I do the following ? 我可以做以下事情吗?

Go back to B state and have C as un-staged changes ? 返回到B状态, C为未分段的更改?

As A -> B -> C is pushed to remote repo, I cannot expect a git reset B . 由于A -> B -> C被推送到远程仓库,我不能期望git reset B But what I can expect is A -> B -> C -> B' where, B' is the same state as B but with C as un-staged changes. 但是我可以期待的是A -> B -> C -> B' ,其中, B'B处于相同状态,但C为无阶段变化。

As Ovsyanka answered , git reset does do what you're asking for in terms of work tree (and, for that matter, the index / staging area too: you control whether the index resets to the target commit B , or not, using --mixed vs --soft ). 正如Ovsyanka回答的那样git reset确实按照工作树的要求进行了工作 (就此而言,它也是索引/临时区域:您可以使用--mixed控制索引是否重置为目标提交B ,或者--mixed vs --soft )。 However, if you do a regular git revert C , then do the usual edit-add-commit sequence, you will get: 但是,如果执行常规的git revert C ,然后执行通常的edit-add-commit序列,则会得到:

A--B--C--unC--D

ie, a total of 5 commits. 即,总共5次提交。 Should you not want that, you can use: 如果你希望这样,您可以使用:

git revert -n C

which reverts C in your work tree (and index) without actually committing. 无需实际提交即可还原工作树(和索引)中的C You can then make further changes and commit again, giving: 然后,您可以进行进一步的更改并再次提交,从而得到:

A--B--C--D

where D undoes C and makes further changes. D撤消C 进行进一步更改。

There is a good reason to stick with a simple revert, though. 不过,有充分的理由坚持简单的还原。 Suppose someone—perhaps even you yourself—comes back to this project in the future, say, a year from now. 假设某个人(也许甚至是您自己)将来会回到这个项目,例如从现在开始一年。 This person is wondering what happened in the past, and is looking through the commits. 这个人想知道过去发生了什么,并正在查看提交。 They come upon commit D , which when inspected, clearly undoes some of commit C and also does some other stuff, and they wonder: "Hey, who threw out all that good work in C ? Wait, it was the same guy who wrote C . What the ...?" 他们遇到了提交D ,然后对其进行检查,该提交显然被撤消了提交C某些操作,并且还做了其他一些工作,他们想知道:“嘿,谁把C所有出色工作都扔了?等一下,是 C那个人什么...?”

If they come across, instead, the C--unC--D sequence, with commit unC being "revert ", they—which might, again, be you yourself—will immediately know: "Aha, the person who reverted C is saying C was wrong , and then the person who added D is making a different change... oh, huh, that person is me . Oh yeah, I remember now!" 如果他们C--unC--DC--unC--D序列,而提交unC是“ revert”,那么他们(可能又是你自己)将立即知道:“啊哈,恢复C的人在说C错的 ,然后加D的人正在做出不同的更改……哦,那个人是 。哦,是的,我现在记得!”

Even if you haven't pushed / published commit C , it's still a pretty good idea to revert it like this. 即使您尚未推送/发布提交C ,将其恢复为这样仍然是一个不错的主意。 Then, before you actually git push your sequence of commits, you can run git rebase -i and delete both C and its reversion, to make it look like you never made that mistake. 然后,在实际使用git push提交顺序之前,可以运行git rebase -i并删除C及其版本,以使其看起来从未犯过该错误。 (Or, equivalently, squash a bunch of commits together so that you have one "really good" change, or a small set of "really sensible" changes, rather than a meandering collection of "try this, try that too, oh wait the first one was wrong, ah we need this auxiliary fix as well, oh and before we did any of these changes, it would have been nice if we'd fixed this main problem in the tests! then we'd have seen just what was wrong, and it would be obvious what we were fixing and why!") (或者,等效地,将一堆提交压缩在一起,以便您进行一次“非常好”的更改,或者进行一小组“非常明智的”更改,而不是曲折地收集“尝试一下,也尝试一下,哦,等一下第一个是错误的,嗯,我们也需要此辅助修复程序,哦,在进行任何更改之前,如果我们在测试中解决了这个主要问题,那就太好了!错误,很明显,我们正在修复什么以及为什么!”)

git reset --mixed B do what you wants: git reset --mixed B做你想要的:

Resets the index but not the working tree (ie, the changed files are preserved but not marked for commit) and reports what has not been updated. 重置索引,但不重置工作树(即,已更改的文件将保留,但未标记为提交),并报告尚未更新的内容。 This is the default action. 这是默认操作。

But if you want to actually remove C changes, not just fix it there will be better to make revert C commit and then do another commits. 但是,如果您要删除的是C更改,而不仅仅是对其进行修复,则最好还原C提交然后再执行其他提交。 It will be clear to other peoples, that you completle discarded C commit changes. 对其他人来说,您将完成已丢弃的C提交更改。

You can use git revert C - then you will have clezn working directory and history 'A - B - C - C(rev)' and state of files will be wxactly like in B. 您可以使用git revert C然后将拥有clezn工作目录和历史记录“ A-B-C-C(rev)”,并且文件的状态将与B中的一样。

You can use below commands to meet your requirement: 您可以使用以下命令来满足您的要求:

git revert <commit id for B>
git checkout <commit id for C> -- *.* & git reset HEAD *.*

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM