撤消 git 中的更改(不重写历史记录)
我对脚本进行了更改并提交了它。 然后我做了一些其他更改,并将它们推送到远程存储库等。
然后我意识到我提到的第一个更改是愚蠢的,并且想要撤消它。我可以“取消应用”该提交,而不手动复制/粘贴差异吗?
举个例子:我有两个文件,a.py
和b.py
:
Commit 1:
I delete a function in a.py
Commit 2:
I change a few lines in b.py
Commit 3:
I change the docstring in a.py
我可以撤消该函数删除,并使其显示为“commit 4”(而不是删除提交1)
I made a change in a script and committed it. Then I made a few other changes, and pushed them to a remote repository and such.
Then I realised that first change I mentioned was stupid, and want to undo it.. Can I "unapply" that commit, without manually copy/pasting the diff?
As an example: I have two files, a.py
and b.py
:
Commit 1:
I delete a function in a.py
Commit 2:
I change a few lines in b.py
Commit 3:
I change the docstring in a.py
Can I undo that function deletion, and make it appear as "commit 4" (rather than deleting commit 1)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
是的,您可以使用 git revert 来实现此目的。 有关详细信息,请参阅 git 手册部分。
要点是你可以说:
其中 4f4k2a 是你想要撤消的提交的 id,它会尝试撤消它。
Yes, you can use git revert for this. See the git manual section on this for more information.
The gist is that you can say:
Where 4f4k2a is the id of the commit you'd like to undo, and it will try to undo it.
只是一条评论:
是否恢复所有提交(如“提交的所有文件部分”):
它计算一个反向补丁,将其应用于 HEAD 并提交。
所以这里有两个问题(第一个问题很容易解决):
-no-commit
选项:“git revert --no-commit aCommit
":当连续恢复多个提交对索引的影响时,这非常有用。为此,如果您想提取另一个提交中的特定文件,您应该看到
git-checkout
,特别是git checkout
语法(但这并不完全是您在本例中需要的)Easy Git (Elijah Newren) 试图为 Git 邮件列表; 但没有取得多大成功:
(
例如还原
是记录在这里,但我不确定它是当前发行版的一部分,例如)假设您在 50 个已提交的文件中发现了 20 个文件,您意识到旧的提交 X 引入了不应该发生的更改。
一些管道是有序的。
您需要的是一种列出您需要恢复的所有特定文件的方法
(如“取消提交 X 中所做的更改,同时保留所有后续更改”),
然后,对于它们中的每一个:
这里的问题是恢复丢失的函数,而不删除您可能想要保留的 a.py 中的所有后续更改。
该技术有时被称为“负合并”。
由于
git merge-file; <基本文件> <其他文件>
意思:将从
到
的所有更改合并到中;
,您可以通过说要合并所有更改来恢复已删除的函数。)注意:'
-p
' 参数允许您首先查看更改,而无需对当前文件执行任何操作。 当您确定后,删除该选项。注意:
git merge-file
是没那么简单:您不能像这样引用文件的早期版本。(您会一遍又一遍地收到令人沮丧的消息:
错误:无法统计 X
)您必须:
如果要在先前提交中对大量文件执行此操作...需要编写一些脚本;)
Just a comment:
does revert the all commit (as in "all the files part of the commit" ):
it computes a reverse patch, applies it on HEAD and commit.
So two problems here (the first one is easily solved):
-no-commit
option: "git revert --no-commit aCommit
": this is useful when reverting more than one commits' effect to your index in a row.For that, if you want to extract specific files as they were in another commit, you should see
git-checkout
, specifically thegit checkout <commit> <filename>
syntax (that is not exactly what you need in this case though)Easy Git (Elijah Newren) tried to bring a more "complete revert" to the Git Mailing list; but without much success:
(
eg revert
is documented here, but I am not sure it is part of the current distribution of eg though)Lets say you have, out of 50 committed, 20 files you realize that old commit X introduced changes that should not have taken place.
A little plumbing is in order.
What you need is a way to list all the specific files you need to revert
(as in "to cancel changes made in commit X while keeping all subsequent changes"),
and then, for each of them:
The issue here is to recover the lost function without obliterating all subsequent changes in a.py you might want to keep.
That technique is sometime called "negative merging".
Since
git merge-file <current-file> <base-file> <other-file>
means:incorporates all changes that lead from the
<base-file>
to<other-file>
into<current-file>
, you can restore the deleted function by saying you want to incorporate all changes.)Note: the '
-p
' argument which allows you to review first the changes without doing anything on the current file. When you are sure, remove that option.Note: the
git merge-file
is not that simple: you can not reference previous versions of the file just like that.(you would have over and over the frustrating message:
error: Could not stat X
)You have to:
If this is to be done for a large number of files within a previous commit... some scripting is in order ;)
要将更改仅恢复到提交中的一个文件,如 VonC 指出,我会
签出
分支(主干或主干或其他),然后签出
我想要恢复的文件版本并将其视为新提交:可能有一个管道命令可以直接执行此操作,但如果我知道的话我就不会使用它。 这并不是说我不相信 Git,而是我不相信自己——我不会相信,如果不查看该提交中的文件以及此后的更改内容,我就知道自己知道什么。 一旦我查看,通过编辑
diff
来构建新的提交会更容易。 也许这只是个人的工作方式。To revert the changes to only one file within a commit, as VonC pointed out, I would
checkout
the branch (master or trunk or whatever) and thencheckout
the version of the file I wanted to revert and treat it as a new commit:There's probably a plumbing command that would do this directly, but I wouldn't use it if I knew it. It's not that I don't trust Git, but I don't trust myself -- I wouldn't trust that I knew without looking what was changed in that file in that commit and since then. And once I look, it's easier to just build a new commit by editing the
diff
. Perhaps that's just personal workstyle.看看这个 git revert 问题。
如果不是连续序列(包括最近的提交),则恢复较旧的提交似乎存在问题。
Have a look at this git revert question.
There seems to be a issue reverting older commits if not in a consecutive sequence including the most recent commit.