【问题标题】:How do I view a git diff in a text editor?如何在文本编辑器中查看 git diff?
【发布时间】:2019-11-01 17:08:47
【问题描述】:

如何在像 Atom 这样的普通旧文本编辑器中查看 git diff?我不想设置或使用差异工具,我只想在任何基本的文本编辑器中查看差异。

我看到的关于设置差异工具的其他问题的答案,但我只想指定一些随机文本编辑器。


附加问题:

  • 差异工具和任何文本编辑器有什么区别?

【问题讨论】:

  • 您可以使用文本编辑器作为您的 difftool。这意味着 git difftool 将启动您提供的应用程序并将 2 个文件作为参数传递给它。你想用它们做什么取决于你。

标签: git git-diff


【解决方案1】:

如何在像 Atom 这样的普通旧文本编辑器中查看 git diff?我不想设置或使用差异工具,我只想在任何基本的文本编辑器中查看差异。

差异输出只是文本,因此您可以将其重定向到一个文件并打开该文件,或者(取决于编辑器和平台)将输入直接通过管道传输到编辑器。

如果您确实想将编辑器作为差异工具运行,the documentation 将描述如何调用编辑器。您可能需要一个包装脚本在命令行的正确位置使用环境变量调用 atom。

附带问题:差异工具和任何文本编辑器有什么区别?

通用文本编辑器不太可能像专用工具那样显示差异。至少,如果它能够识别格式,它可能会突出显示特定于 diff 的部分。

真正的差异工具通常会让您有机会查看文件的旧版本和新版本,并直观地显示更改所在的位置。它也可能突出显示行内更改(差异本身是基于行的)。


我一般反对文字图片,但既然我们真的在讨论界面......

  1. git diff 的输出在文本编辑器中打开: 这与仅在终端中读取差异几乎没有什么不同,因此我看不到太多好处。它确实突出显示了 index 行,但这只有在我在单个差异中扫描多个大块时才真正有用。

  2. GVim 逃犯插件显示相同的变化: 这是我的编辑器内部使用逃犯插件的视图。您可以看到我从join 行中删除了一个空格的行内突出显示。如果我继续在右窗格中输入,它甚至会实时更新。这也是唯一一个正确语法高亮源代码的地方。

  3. 在与 git difftool 的融合中打开了相同的更改 这是更改如何适应整个 IMO 文件的最友好的视图。

【讨论】:

    【解决方案2】:

    TL;DR:Git 本身对其他命令一无所知,因此您必须提供一组辅助指令 to Git 告诉它:使用程序 X 作为 difftool ,做_____。最好的办法是找到其他人已经构建的指令,如 the comment EncryptedWatermelon added to his own answer,但如果做不到,那么,请参见下文。

    请参阅Useless's answer 了解一些实用技巧。

    请注意,就 Git 本身而言,尽可能简单地说,diff 表示比较两个修订版。例如,这两个修订可以是两个提交,或者一个提交和您的工作树内容。 Git 有一些额外的特殊情况,因此您也可以将它用作标准 Unix/Linux diff 命令的更高级版本,但大多数情况下,它是两个修订版,每个修订版都是一整套文件:

    • 如果左侧修订版有一个名为 F 的文件,而右侧修订版有一个名为 F 的文件,Git 将比较F 的两个版本。

    • 如果左侧有一个文件 D,而右侧修订版中不存在,则文件 D删除 em>.

    • 如果左侧没有文件A,但右侧修订中有文件A,则文件A em> 已添加

    • 如果您启用重命名检测(这是 Git 2.9 以来的默认设置),Git 将在添加和删除文件的情况下尝试查看新添加的文件是否实际上与旧但已删除的文件,如果是,则将其报告为 重命名 文件,旧名称 D(已删除)和新名称 A (添加)。然后 Git 继续比较左侧 D 和右侧 A 的内容。

    • 在比较文件的内容时,如果一切都相同,Git 通常只对文件什么都不说。否则,你可以让 Git 给你一组“删除这一行”和/或“添加另一行”形式的指令。按照说明将文件的旧版本转换为文件的新版本。这些说明不一定是任何人实际所做的!他们只会获得相同的结果。 (通常只有一种明显的方法可以实现结果,所以结果证明是某人所做的。)

    考虑到这一点,git difftool 的作用如下:

    • 首先,它让 Git 比较两个修订版以生成有更改的文件列表,同时抑制这些文件的实际比较。

      李>
    • 然后,使用已更改文件的列表(两个修订版中的但在两个修订版中不匹配的名称集 F),它会复制左侧修订版本的该文件,以及右侧修订版本的副本。在大多数情况下,它必须制作这些副本,因为存储在 Git 中的文件以冻结和压缩的形式保存,只有 Git 可以实际读取。 Git 必须解压缩/解冻它们,“重新水化”文件的内部冻干形式,以便其他程序可以读取它。

      在少数情况下,例如在将特定提交与工作树进行比较时,它可能只在适当的时候使用工作树副本。它仍然可以制作自己的副本。你在这里没有得到任何实际的承诺。

    • 现在该文件有两个副本,Git 使用一个帮助程序来启动您选择的差异工具。这个帮助程序被赋予了几条信息,例如:

      • 每个临时副本的名称
      • 文件的原始名称(临时副本通常有一些难看的临时名称,例如.tmp-123456


      帮助程序的工作是运行 diff 工具,以便它以对用户友好的方式显示这些文件。然后它必须等待工具指示用户已完成查看文件,并确定用户是否表示希望取消查看文件或继续下一个文件对。

    This is the helper program. 这是一个相对简单的 shell 脚本,只有 100 多行。但它使用了更多的 shell 脚本:特别是,它使用了 this larger mergetool helper library,它有超过 450 行的 shell 脚本。

    要提供您自己的工具,您必须——为了获得最佳使用——编写第二个(合并助手)库使用的 shell 脚本,并结合第一个脚本提供有关如何运行您选择的工具的知识。这种互动的关键要素是:

    • 打开这两个文件
    • 显示比.tmpwhatever 更有用的名称
    • 检测用户何时以及是否想要继续下一个差异或退出。

    现有的两个 shell 脚本助手代码库有一些回退,因此如果您的程序使用起来相对简单,现有的助手可以自己运行它。他们只需要知道可执行文件在哪里以及要传递哪些参数以及是否信任其退出代码。您可以通过设置difftool.<em>name</em>.cmdmergetool.<em>name</em>.trustExitCode 来使用git config 进行设置。例如:

    git config --global difftool.foo.cmd '<path> "$LOCAL" "$REMOTE"'
    git config --global mergetool.foo.trustExitCode true
    

    如果 path 处的命令对于“继续下一个差异”退出为零,对于“退出”退出非零,则可以(但不是那么好:文件名会很奇怪且无用)现在”。

    【讨论】:

      【解决方案3】:

      git diff 如果输出很短,将显示在您的控制台中,否则将转到您的寻呼机。即lessmore

      git difftool 将显示在 tkdiff、xxdiff、meld、比较 gvimdiff、... 或您设置的任何内容中

      Difftools 通常让您在分页器处于只读状态时编辑文件

      【讨论】:

      • "whatever you set" 似乎并不正确,因为如果我只设置atom,它就不起作用。我收到错误消息:Unknown merge tool atom.
      【解决方案4】:

      差异工具(例如:http://meldmerge.org/)将在 2、3 甚至 4 个面板(您的版本、远程版本、合并版本、祖先版本)中向您显示差异。

      在文本编辑器上打开 diff(这是我的偏好)将显示 diff 特殊字符,表示内容的添加、删除和修改。以及一些上下文边界信息。

      【讨论】:

      • 感谢您的区别,但您跳过了我的主要问题:那么如何设置 git 以使用 Atom(或任何文本编辑器)来显示差异?
      【解决方案5】:

      你也有,since Git v1.7.8 (Oct. 2011) git jump

      git jump 是一个脚本,可帮助您在编辑器中跳转到项目的“有趣”部分。

      它通过以“quickfix”格式输出一组有趣的点来工作,像 vim 这样的编辑器可以将其用作访问地点的队列(此功能通常用于跳转到编译器产生的错误)。

      例如,给定这样的差异:

      ------------------------------------
      diff --git a/foo.c b/foo.c
      index a655540..5a59044 100644
      --- a/foo.c
      +++ b/foo.c
      @@ -1,3 +1,3 @@
      int main(void) {
      -  printf("hello word!\n");
      +  printf("hello world!\n");
      }
      -----------------------------------
      

      git jump 会将其提供给编辑器:

      -----------------------------------
      foo.c:2: printf("hello word!\n");
      -----------------------------------
      

      请确保使用 Git 2.35(2022 年第一季度):git jump(在 contrib/ 中)的“merge”子命令会默默忽略路径规范和其他参数。

      参见Jeff King (peff)commit 67ba13e(2021 年 11 月 9 日)。
      (由 Junio C Hamano -- gitster -- 合并于 commit a0f3df5,2021 年 12 月 10 日)

      git-jump:将“merge”参数传递给ls-files

      签字人:杰夫·金

      我们目前丢弃了任何给 git jump merge" 的参数。
      我们应该将它们传递给 ls 文件,因为它们很可能是路径规范。
      这符合git jump diff等的行为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-03-30
        • 2019-09-18
        • 1970-01-01
        • 1970-01-01
        • 2017-07-10
        • 2020-11-02
        • 1970-01-01
        相关资源
        最近更新 更多