2011-12-01 64 views
7

据我知道,当你想撤销在Git的东西,你必须明确地找到命令撤消不管它是你做,并出具了。例如,在许多单向撤消承诺和重做它是遵循从here的例子,为什么Git中没有撤消/重做?

$ git commit ... 
$ git reset --soft HEAD^ 
$ edit 
$ git add .... 
$ git commit -c ORIG_HEAD 

或者撤销一拉,就可以按照从here指示,

$ git reset --hard 

但是这些命令不一定可以互换。 Git不允许简单的撤消和重做命令吗?与它背后的哲学有什么关系?另外,我没有太多其他版本控制系统的经验,但是他们中的任何一个都提供了简单的撤消和重做命令?

+0

我不确定,但我认为你可以使用'git rebase'来做到这一点。检查这个http://gitready.com/intermediate/2009/01/31/intro-to-rebase.html – gustavotkg

+2

这个想法是,你通常不想做的事情,让你失去的历史的一部分。撤消提交会将其从历史记录中删除,因此通常不会执行此操作。 – poke

+0

@poke嗯,例如,Adobe Photoshop,保留了大量的历史记录,并且仍然允许您撤销/重做。为什么Git不会这样做? – john

回答

6

有几个问题,这样的观念:

  • 并非所有操作都是可逆的。有时候,这是因为Git没有记录足够的信息来推断先前的状态 - 总体而言,这样做的代价非常昂贵。有时这之类的东西git reset --hardgit clean,毁坏未被跟踪的变化。为了撤消它们,它必须不断自动备份。有时候这是因为撤销的概念是不明确的 - 就像你自己指出的那样,撤销提交有很多方法。

  • 如果操作是可逆的,它涉及到某种历史的,应撤销/重做也成为历史,还是应该让它消失?如果一个提交通过重置回,或通过恢复(创建另一个承诺取消)被撤销?

  • 没有记录你所做的每件最后的事情,你怎么知道最近的操作是什么?假设你向索引添加了一个文件,并创建了一个分支。没有第一个记录。

即使所有东西都有明确的定义,实施这些工作也是荒谬的。你如何确定什么是单一行为?一个Git命令可能会做很多事情。它应该撤消一步,整个事情?如果你已经运行了一个zillion命令,每个步骤都很小,并且你想要全部撤消这些命令呢?它必须是完美的,完全完美,因为这种功能将被没有经验的用户使用,他们不知道如何从任何错误中恢复过来。因此,正如Git为您提供工具来完成工作一样,它会为您提供工具来查看您已完成的工作,并根据需要自行解决问题。

此外,就“重做”而言,正如您在问题中所定义的那样,它会重复一个命令,而不是再次执行原始操作。当你重新提交一个提交时,它是一个不同的提交。重新运行一个以前的命令是命令行的外壳是设计的要做的事情。 Git不需要重新创建它。

4

其实你的第一个例子可以执行:

$ git commit ... 
$ edit 
$ git add ... 
$ git commit --amend 

你的第二个例子应该更像git reset --hard <hash>

的回答你的问题是,它的潜在可能,但肯定它更哲学的驾驶这意味着它没有完成。从理论上讲,无法通过创建或删除另一个来确定是否需要进行提交,但使用reflog可能可能......以前没有真正考虑过这个问题。

我不认为“撤销”和“重做”在源代码控制很平常的事,虽然,但纠正我,如果我错了。

编辑:你可能装备了一个脚本,可以做什么你使用引用日志之后 - 如果不知道有足够的信息存在,但它可能是值得一试。

1

git实际上是对信息库,索引和工作目录充当多个小工具,因此它不具有任何“撤销”一个“核心”的一部分。

这就是说它确实有各种日志,如reflog你回头看看是什么事。

最后,按照惯例,很多git动作通常被认为是“单向的”,也就是说,你不想让任何人公开看到它,所以git试图“让你绕着阻止'在公共场合。如果你仍然在本地回购,你可以使用各种命令备份,但全局撤销并不是一个合适的命令。

+0

“单向”是一种很好的思考方式,因为一旦某种东西在野外复原和重做变得危险 – MattJenko

0

除了其他意见,我会检查出git stash。很多时候,我藏了一些工作,修理了其他东西,然后晾干并继续。或者对于一个web应用程序,隐藏我的完成和未提交的工作,刷新浏览器,清除,打开一个新选项卡,然后将这两个来回比较以确保与UI相关的错误修复不会破坏其他任何内容。