仅仅是一个注释:
git revert aCommit
revert命令会撤销整个提交(比如“提交的所有文件”):
它会计算一个反向补丁,将其应用于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
在此处记录,但我不确定它是否是当前发行版的eg的一部分)
但最终归结为“还原更改”。
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标志)。
假设你有50个提交,其中有20个文件,你意识到旧的提交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>
中,因此您可以通过说您想要合并所有更改来恢复已删除的函数。)
- 从:X(函数已被删除的位置)
- 到: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!
如果需要对先前提交的大量文件执行此操作...则需要编写一些脚本;)