[英]Undo change in git (not rewriting history)
我在脚本中进行了更改并提交了它。 然后我做了一些其他更改,并将它们推送到远程存储库等。
然后我意识到我提到的第一个更改是愚蠢的,并且想要撤消它。我可以“取消应用”提交,而无需手动复制/粘贴差异吗?
举个例子:我有两个文件, 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
我可以撤消该功能删除,并使其显示为“提交4”(而不是删除提交1)
只是评论:
git revert aCommit
确实恢复了所有提交(如“提交的所有文件部分”):
它计算反向补丁,将其应用于HEAD并提交。
所以这里有两个问题(第一个很容易解决):
-no-commit
选项:“ git revert --no-commit aCommit
”:这在将一个以上的提交效果恢复到你的索引中时非常有用。 git-checkout
,特别是git checkout <commit> <filename>
语法(虽然这不是你需要的) Easy Git (Elijah Newren)试图为Git Mailing列表带来更“完整的恢复”; 但没有太大的成功:
人们偶尔会想“恢复变化”。
现在,这可能是:
- 之前32到29次修改之间的变化,
- 它可能是自上次提交以来的所有更改,
- 它可能是自3次提交以来的变化,或者
- 它可能只是一个特定的提交。
- 用户可能希望将此类反转仅限于特定文件 ,
( eg revert
此处记录了 eg revert
,但我不确定它是否是当前分布的一部分,例如)
但这一切归结为最终“恢复变化”。
eg revert --since HEAD~3 # Undo all changes since HEAD~3
eg revert --in HEAD~8 # much like git revert HEAD~8, but nocommit by default
eg revert --since HEAD foo.py # Undo changes to foo.py since last commit
eg revert foo.py # Same as above
eg revert --in trial~7 bar.c baz. # Undo changes made in trial~7 to bar.[ch]
这些“还原数据”真的如此不同,以至于应该需要不同的命令,或者简单的还原命令不应该支持某些操作吗?
当然,大多数用户大多数时间都可能会使用“eg revert FILE1 FILE2...
”表单,但我没有看到支持额外功能的危害。还有......有什么根本可以让核心的git不采用这种行为吗?
以利亚
注意:默认情况下提交对于通用的
revert
命令没有意义,并且“git revert REVISION
”会因指令错误输出(告诉用户添加--in标志)。
假设您已经知道旧的提交X引入了不应该发生的更改。
有点管道是有序的。
您需要的是列出您需要还原的所有特定文件的方法
(如“在保留所有后续更改时取消在提交X中所做的更改” ),
然后,对于他们每个人:
git-merge-file -p a.py X X^
这里的问题是恢复丢失的功能而不删除您可能想要保留的a.py中的所有后续更改。
这种技术有时称为“负合并”。
由于git merge-file <current-file> <base-file> <other-file>
意味着 :
将从<base-file>
到<other-file>
所有更改合并到<current-file>
,您可以通过声明要包含所有更改来恢复已删除的功能。)
注意: ' - -p
'参数允许您首先查看更改,而不对当前文件执行任何操作。 如果您确定,请删除该选项。
注意 : git merge-file
并不那么简单 :你不能像那样引用文件的先前版本。
(你会有一遍又一遍的令人沮丧的消息: error: Could not stat X
)
你必须:
git cat-file blob a.py > tmp/ori # current file before any modification
git cat-file blob HEAD~2:a.py > tmp/X # file with the function deleted
git cat-file blob HEAD~3:a.py > tmp/F # file with the function which was still there
git merge-file a.py tmp/X tmp/F # basically a RCS-style merge
# note the inversed commit order: X as based, then F
# that is why is is a "negative merge"
diff -u a.py tmp/ori # eyeball the merge result
git add a.py
git commit -m "function restored" # and any other changes made from X are preserved!
如果要对先前提交中的大量文件执行此操作...某些脚本按顺序排序;)
要将更改恢复为提交中的仅一个文件,如VonC所指出的,我会checkout
分支(主服务器或主干或其他),然后checkout
我想要还原的文件的版本并将其视为新提交:
$ git checkout trunk
$ git checkout 4f4k2a^ a.py
$ git add a.py
$ git diff #verify I'm only changing what I want; edit as needed
$ git commit -m 'recover function deleted from a.py in 4f4k2a'
可能有一个管道命令可以直接执行此操作,但如果我知道它,我就不会使用它。 并不是我不相信Git,而是我不相信自己 - 如果不查看该提交中的文件中发生的变化,那么我就不相信我知道了。 一旦我看,通过编辑diff
来构建新的提交会更容易。 也许这只是个人的工作方式。
看看这个git revert问题 。 如果不是在包括最近提交的连续序列中,则似乎存在恢复旧提交的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.