撤消改变(不重写历史)
我做了一个脚本的改变,并承诺。 然后,我做了一些其他的更改,并将它们推送到远程存储库等。
然后我意识到,我提到的第一个变化是愚蠢的,想要撤消它..我可以“不应用”提交,而不需要手动复制/粘贴差异?
举个例子:我有两个文件, 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
我可以撤销该function删除,并使其显示为“提交4”(而不是删除提交1)
是的,你可以使用git恢复这个。 有关更多信息,请参阅git手册部分 。
要点是你可以说:
git revert 4f4k2a
其中4f4k2a是您要撤消的提交的ID,它将尝试撤消它。
只是一个评论:
git revert aCommit
会恢复所有的提交(如在“提交的所有文件的一部分”):
它计算反向修补程序,将其应用于HEAD并提交。
所以这里有两个问题(第一个很容易解决):
- 它总是提交,所以你可能想要添加
-no-commit
选项:“git revert --no-commit aCommit
”:当在一行中多次提交'提交'效果到你的索引时,这是很有用的。 - 它不适用于特定的文件(如果您的a.py是其他1000个您可能不想恢复的更改提交的一部分)?
为此,如果你想提取特定的文件,就像在另一个提交中那样,你应该看到git-checkout
,特别是git checkout <commit> <filename>
语法(这不是你在这种情况下所需要的)
Easy Git (Elijah Newren)试图给Git邮件列表带来更多的“完全还原” 但没有太大的成功:
人们偶尔想要“恢复变化”。
现在,这可能是:
- 在32到29之间的修改之前,
- 它可能是自上次提交以来的所有更改,
- 它可能是自3提交以来的变化,或者
- 它可能只是一个具体的提交。
- 用户可能希望将这样的反转子集合到特定的文件中 ,
( eg revert
logging在这里 ,但我不确定它是目前分配的一部分,例如虽然)
但最终归结为“恢复变化”。
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...
”的forms,但我没有看到支持额外function的危害。另外…有没有什么基本的东西可以使核心git不采取这种行为?
以利亚
注意:默认提交对于广义
revert
命令是没有意义的,“git revert REVISION
”将会出错(告诉用户添加–in标志)。
假设你有50个承诺的20个文件,你意识到旧的提交X引入了不应该发生的变化。
有一点pipe道是为了。
你需要的是一个列出你需要恢复的所有特定文件的方法
(如在“保留所有后续更改时取消提交X中所做的更改” ),
然后,他们每个人:
git-merge-file -p a.py XX^
这里的问题是恢复丢失的function,而不会消除您可能想保留的所有后续更改。
这种技术有时被称为“负合并”。
因为git merge-file <current-file> <base-file> <other-file>
表示 :
将从<base-file>
到<other-file>
所有更改合并到<current-file>
,可以通过声明要合并所有更改来恢复已删除的函数。
- 来自:X(function已被删除)
- 到:X ^(在X之前的那个函数仍然存在的地方)
注意: '- -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
分支(master或trunk或其他),然后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'
可能有一个pipe道命令会直接做到这一点,但如果我知道的话,我不会使用它。 这并不是我不信任Git,但我不相信自己 – 我不相信我没有看到那个提交文件中的变化,从那以后。 一旦我看,通过编辑diff
来build立一个新的提交就更容易了。 也许这只是个人的工作方式。
看看这个git恢复问题 。 如果不是包括最近的提交在内的连续序列中,似乎还有一个问题还原旧的提交。