在Magit 2.1.0中逆转大块


24

我刚刚升级到magit 2.1.0。(以及emacs 25.0.50和git 2.3.1。)

以前,在*magit*缓冲区中,我可以:

  1. 在“未登台”区域中选择一个大块。
  2. 输入v并回答“是”以将其撤消。

这很方便。

但是现在在magit 2.1.0中它给出了一个错误:"Cannot reverse unstaged changes"

为什么?


从错误消息中得到一个提示,我发现我仍然可以执行此操作,尽管可以通过更多步骤来实现“后退”:

  1. s大块头。(向后感觉;将其移至已提交状态。)
  2. 向下导航并在“暂存”区域中将其选中。
  3. v,回答是。
  4. 但是,大块仍处于u暂存状态,因此最后我必须对大块进行暂存。

这是一个错误,还是故意的和/或我很专心?如果是后者,您能帮助我理解吗?


更新:彻底RTFinfo-ing后,我看到有两个命令:

  • v magit-reverse 反向更改工作树中的点。
  • k magit-discard 从工作树中删除当前点的更改。

似乎k magit-discard确实做了我以前v做过的事。它确实适用于未分级的块。

因此,实际上我只需要重新训练我的肌肉记忆就可以使用k。我可以将其发布为自我解答。但是我想我仍然对基本原理感到好奇,因为我想理解它会帮助我从总​​体上更好地了解magit。


很高兴您正在阅读详细信息:)我很困惑您“反转”大块头的意思。我以前从未听过这个词。
PythonNut

k还会丢弃早期版本的magit中未提交的更改,并且似乎是您正在执行的操作的适当命令。v是用于git revert的:创建一个新的提交,该提交与先前的提交相反。我猜想还原未实际提交的更改与放弃它是相同的,但是“还原”作为git命令具有特定的含义。
glucas 2015年

好的,看起来像是v绑定到了magit-revert-item(“反向”术语来自那里,@ PythonNut),对于未暂存的项目,它过去常常做一个magit-discard-item(也绑定到k)-参见此处的 4872行。显然v,我本来应该学会使用的,但它偶然地了解了它的特殊含义k
格雷格·亨德肖特

尽管我通常不喜欢自我答案,但在这种情况下,我认为这是得出结论的最仁慈的方式。:)在下面张贴一个。
格雷格·亨德肖特

Answers:


20

Magit实现了手册中描述的五个“应用变体” :阶段,非阶段,“常规应用”,丢弃和反向。对于大多数Git用户来说,前三个应该很明显。后两者在Git 瓷器中不存在(在Magit中,它们是使用Git 管道命令和Emacs Lisp实现的)。

这两个变体的描述如下:

  • 丢弃。在分阶段的更改中,将其从工作树和索引中删除。在未分段的更改上,仅将其从工作树中删除。
  • 相反。撤消工作树中的更改。已提交和已分阶段的更改都可以撤消。未分段的更改不能撤消。而是丢弃它们。

这两个变体做的事情非常不同,因此在无法使用自身的情况下,这两个变体都不应该退回到另一个变体。在短期内,保留旧的行为(在某些情况下从反向变回丢弃)可能会更方便,但从长远来看,它会阻止用户真正尝试理解这两种变体的用途。

抛弃倒退更为危险。前者“丢弃未提交的更改”(这些更改已丢失,不再存在),而后者实际上是“创建更改”,方法是进行旧的更改并在工作树中进行相反的操作(旧的更改不会丢失,它仍然在提交或索引中)。

从“创建”退回到“删除”非常危险,因此Magit不再这样做。


另请注意,通过使用新的擦拭模式,您可以保护自己免于因意外丢弃而丢失更改。


3
非常感谢您抽出宝贵时间回答和解释其基本原理。
格雷格·亨德肖特

10

似乎我意外地了解到,在这种特殊情况下,确实v绑定了magit-revert-item,曾经做过magit-discard-item无节制的大块头。请参阅<=== HERE ===我在下面发表的评论:

(defun magit-revert-item ()
  "Revert the item at point.
The change introduced by the item is reversed in the current
working tree."
  (interactive)
  (magit-section-action revert (info)
    ([* unstaged] (magit-discard-item))  ;; <=== HERE ===
    (commit (when (or (not magit-revert-item-confirm)
                      (yes-or-no-p "Revert this commit? "))
              (magit-revert-commit info)))
    (diff   (when (or (not magit-revert-item-confirm)
                      (yes-or-no-p "Revert this diff? "))
              (magit-apply-diff-item it "--reverse")))
    (hunk   (when (or (not magit-revert-item-confirm)
                      (yes-or-no-p "Revert this hunk? "))
              (magit-apply-hunk-item it "--reverse")))))

来源:1.4.2代码

但是现在这不会发生:

(defun magit-reverse (&rest args)
  "Reverse the change at point in the working tree."
  (interactive (and current-prefix-arg (list "--3way")))
  (--when-let (magit-current-section)
    (pcase (list (magit-diff-type) (magit-diff-scope))
      (`(untracked ,_) (user-error "Cannot reverse untracked changes"))
      (`(unstaged  ,_) (user-error "Cannot reverse unstaged changes"))
      (`(,_      list) (magit-reverse-files (magit-section-children it) args))
      (`(,_     files) (magit-reverse-files (magit-region-sections) args))
      (`(,_      file) (magit-reverse-files (list it) args))
      (_               (magit-reverse-apply it args)))))

资料来源:大师


但是k直接绑定magit-discard-item。我本来应该学会使用它。在2.1.0之前可以使用,现在仍然可以使用。

总而言之,已对magit 2.1.0进行了重新设计。不可避免的是,有些怪异的极端案例可能无法幸免。而且,我同意,不需要生存。我将重新学习密钥。


1
不错的详细自我解答-也可以接受!
glucas 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.