据我所知,当你想在Git中撤消一些东西时,你必须明确地找到命令来撤消你已经完成的任何事情并发出它。例如,许多撤消提交并重做它的方法之一是遵循here中的示例,
$ git commit ...
$ git reset --soft HEAD^
$ edit
$ git add ....
$ git commit -c ORIG_HEAD
要撤消提款,您可以按照here,
中的说明操作$ git reset --hard
但这些命令不一定互换。有没有理由为什么Git不允许简单的撤销和重做命令?它与背后的哲学有什么关系?另外,我对其他版本控制系统没有太多经验,但是它们中的任何一个都提供了简单的撤销和重做命令吗?
答案 0 :(得分:7)
这种观念有几个问题:
并非所有操作都是可逆的。有时候这是因为Git没有记录足够的信息来推断先前的状态 - 一般来说这是非常昂贵的。有时像git reset --hard
或git clean
这样的东西会破坏未经修改的变化。为了撤消它们,它必须不断自动备份。有时这是因为撤消的概念含糊不清 - 正如您自己指出的那样,撤消提交的方法有很多种。
如果一个操作是可逆的,并且它涉及某种历史,那么撤消/重做是否也应该在历史中,或者它们是否应该消失?是否应通过重置或恢复(创建另一个提交以取消提交)撤消提交?
如果不记录你做的每一件事,你怎么知道最近的操作是什么?假设您向索引添加了一个文件,并创建了一个分支。没有记录是第一次。
即使一切都已明确定义,实施这些工作也是荒谬的。您如何确定单一行动的构成?单个Git命令可能会做很多事情。它应该撤消一步,整个事情?如果您运行了大量命令,每个步骤都执行一小步并且您想要将其全部撤消,该怎么办?并且它必须是完美,完全完美,因为它是那些不知道如何从任何错误中恢复过来的缺乏经验的用户所使用的功能。
所以,就像Git为你提供了做事的工具一样,它为你提供了工具来查看你做过的事情,并在需要的时候自行撤消。
此外,对于“重做”,正如您在问题中定义的那样,它正在重复命令,而不是再次执行原始操作。重做提交时,它是一个不同的提交。重新运行上一个命令是命令行shell 设计要执行的操作。 Git不需要重新发明它。
答案 1 :(得分:4)
实际上你的第一个例子可以用:
执行$ git commit ...
$ edit
$ git add ...
$ git commit --amend
您的第二个示例应该更像git reset --hard <hash>
你的问题的答案是它有可能,但是更多的是驱动git的哲学意味着它还没有完成。从理论上讲,没有办法通过创建它或删除另一个来判断你是否需要提交,但是使用reflog它可能是可能的......之前没有真正考虑过它。
我认为'撤消'和'重做'在源代码管理中并不常见,但如果我错了,请纠正我。
编辑:您可以使用可以执行使用reflog之后的脚本 - 不确定是否有足够的信息,但是值得一试。
答案 2 :(得分:1)
git
实际上是多个小工具,它们作用于存储库,索引和工作目录,因此它没有任何“撤销”的“核心”部分。
那说它确实有各种日志,例如reflog
,让你回顾一下所做的事情。
最后,根据惯例,许多git动作通常被认为是“只有一种方式”,也就是说,你不希望任何人公开看到它,所以git试图让你绕过这个块'在公共场合。如果您仍在本地仓库中,则可以使用各种命令进行备份,但全局撤消不是适当的命令。
答案 3 :(得分:0)
除了其他评论,我还会查看git stash
。我多次隐藏一些工作,修复其他东西,然后解除搁置并继续。或者对于一个webapp,存储我已完成和未提交的工作,刷新浏览器,解除打开,打开一个新选项卡,然后来回比较这两个,以确保与UI相关的错误修复不会破坏其他任何内容。
答案 4 :(得分:0)
有时我会将整个活动源代码树快照到一个压缩文件(在 Mac 上单击一下),然后再做一些让我害怕的事情,比如一个大的变基。
因为我将使用的 git 命令只是在目录树上本地执行,这使得很容易放弃操作并恢复到我之前的情况(包括未签入或修改的文件),如果出现问题搞砸了。
我不需要经常这样做,但是这个手动“撤消”已经不止一次救了我的屁股。