如何使用寻呼机进行长 git add --patch hunks?

Posted

技术标签:

【中文标题】如何使用寻呼机进行长 git add --patch hunks?【英文标题】:How do I use a pager for long git add --patch hunks? 【发布时间】:2017-02-06 04:43:27 【问题描述】:

当我以交互方式添加diff 帅哥和git add --patch 时,有时我会得到比屏幕长的帅哥,但无法使用less 来翻阅帅哥。

这对我来说很奇怪,因为我已经设置了:

[core]
      pager = less -FRX --tabs=4

[pager]

  diff = diff-highlight | less -FRX --tabs=4

interactive.diffFilter= 通过管道传送到less 也无助于分页。

我需要怎样做才能让git add--patch 使用less 以便我可以使用键盘来导航超过一个屏幕的任何输出?

【问题讨论】:

git 版本 2.10.0.GIT git 版本 2.28.0 -- 问题仍然存在。 @VonC 有什么想法吗? 【参考方案1】:

你不能。这是the Unix pipeline model 的本质。

使用分页器的 Git 命令可以与 any 通用 stdin 分页器一起工作的原因是因为这个模型。此类 git 命令将其输出写入stdout。寻呼机从stdin 读取其输入。前者的stdout 通过管道传送到后者的stdin正是这种管道模型的简单性使寻呼机具有通用性,并且允许 git 允许您选择您自己的寻呼机,只要它使用此模型。

那么为什么git add -p(或git add -i)不能与git diffgit log做同样的事情呢?

因为一次只能有一个交互式应用程序。

git diffgit log交互的。 git add -p 和寻呼机互动的。

管道模型的性质意味着一次只能控制一个应用程序,并且需要一个交互式应用程序来控制。要让寻呼机获得对终端的控制(以便它可以显示提示并响应您的输入),git add -p 必须释放控制权。一旦完成,它就无法恢复。

这样看:会有两个命令行提示试图与您交互:一个用于git add -p,另一个用于寻呼机。他们将如何协调?它必须是这样的:

    git add -pstdout 写入一个块,以及一个块结束 (EOH) 标记,而不是通常的文件结束 (EOF) 标记。 git add -p 然后将终端的控制权交给管道另一端的任何应用程序。 寻呼机将接收大块,并通过控制终端显示大块的片段及其命令提示符。 寻呼机的行为与通常一样,但有很大不同。通常它会看到一个 EOF 标记,所以当你说你已经完成(quit 命令)时,它会退出。但是 EOH 制造商告诉寻呼机,“不要退出。当用户完成后,将控制权交还给上游应用程序。不要退出。等待。” 因此,当您使用各种寻呼机命令仔细阅读该块时,您可以使用它的quit 命令告诉它您已像往常一样完成。 但现在寻呼机没有退出,而是以某种方式将终端控制权交还给git addgit add 的终端提示将替换寻呼机的... ...现在我们回到第 1 步。继续重复直到 EOF。

如您所见,这不仅是糟糕的用户体验(使用寻呼机的quit 命令返回每个大块上的git add),它会完全破坏破坏 Unix 管道模型的力量和美感

同样的原因git add -p cannot use diff-so-fancy

git -p 具有类似寻呼机的行为的唯一方法是内置一个,或者定义一个“Git Pager API”,然后我们等待人们编写使用此 API 的寻呼机。这是插件模型,与管道模型有很大不同。这也意味着紧密集成:git add -p 命令和寻呼机命令必须组合起来,并在每个命令提示符下都可用。

使用终端应用程序的分页

我发现在终端窗口中向上滚动很容易。我的键盘命令允许我逐行或逐页移动。

使用git add -psplit命令

您是否考虑过使用git add -psplit 命令来打断大佬?无论如何,我发现更小的帅哥更容易理解!

【讨论】:

您的回答似乎假设需要同时从终端读取两个应用程序。我不认为是这种情况:为什么不能git 运行<generate-diff> | less --quit-if-one-screen 来显示差异,等待less 退出,然后打印补丁菜单? 你说得对。它可能。 git add -p 可以调用寻呼机作为单个大块的子进程,而不仅仅是将其所有输出通过管道传递给它。所以这几乎肯定需要更改 git 的add-patch.c。我没有时间去看。同时,尝试less 自己调用子流程的能力,看看这样的用户体验是否可以接受。 例如,less 很长,然后在 less 中使用 m 标记文件中的某个点,然后使用 | 然后你的标记字母,然后使用 less -FN 在 less 中调用 less .看看在外部少进程中标记的短位和长位是如何工作的。收到您的回复后,我会尽快更新我的答案。 我没有按照你的意图在less 内调用less...less 甚至没有被git 调用一次。 正如我在回答中提到的那样,您必须承认的两个答案是黑客行为并导致用户体验不佳。【参考方案2】:

作为一种解决方法,您可以设置EDITOR=less 并使用e (edit) 在大块头上运行less。但按原样,这种解决方法有一些缺点。这些可以通过以下方式避免:

EDITOR="EDITOR='$EDITOR' bash -c 'set -m; less -K \"\$1\"' --" git add -p

在调用less 之前重置EDITOR 允许使用less 中的标准v 键来调用编辑器。

less-K 选项允许使用 Control-C 退出 less,告诉 Git 不要暂存大块。使用q 退出less 将导致大块被上演。

set -m 创建一个单独的进程组,阻止 Control-C 冒泡并终止 Git 进程。

还有提供a better interface for interactive staging的工具如Magit

【讨论】:

这对我不起作用,因为$VISUAL 优先于$EDITOR 使用。 使用$LESS=F,如果大块小于一屏,less 将退出0,自动暂存它:(【参考方案3】:

基于AtnNn's answer,我想出了以下别名:

ap = !"VISUAL=\"VISUAL='$VISUAL' bash -c 'set -m; less -K -+F \\\"\\$1\\\"' --\" git add -p \"$@\" #"
eless 中寻呼大块头 按q 暂存显示的内容 按v 编辑显示的内容 按^C 退出并重复交互式菜单

我正在做一个 PR 来解决 git 本身的问题。

【讨论】:

以上是关于如何使用寻呼机进行长 git add --patch hunks?的主要内容,如果未能解决你的问题,请参考以下文章

QT使用websocket进行长连接

如何在 MVC 3 中正确进行长轮询

如何在 git 命令后在寻呼机中显示输出?

使用 Xampp 进行长轮询

使用 Httpclient 进行长轮询

将`git difftool`管道传输到寻呼机时如何保留颜色