如何使用寻呼机进行长 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 diff
或git log
做同样的事情呢?
因为一次只能有一个交互式应用程序。
git diff
和 git log
是非交互的。 git add -p
和寻呼机是互动的。
管道模型的性质意味着一次只能控制一个应用程序,并且需要一个交互式应用程序来控制。要让寻呼机获得对终端的控制(以便它可以显示提示并响应您的输入),git add -p
必须释放控制权。一旦完成,它就无法恢复。
这样看:会有两个命令行提示试图与您交互:一个用于git add -p
,另一个用于寻呼机。他们将如何协调?它必须是这样的:
git add -p
向 stdout
写入一个块,以及一个块结束 (EOH) 标记,而不是通常的文件结束 (EOF) 标记。
git add -p
然后将终端的控制权交给管道另一端的任何应用程序。
寻呼机将接收大块,并通过控制终端显示大块的片段及其命令提示符。
寻呼机的行为与通常一样,但有很大不同。通常它会看到一个 EOF 标记,所以当你说你已经完成(quit
命令)时,它会退出。但是 EOH 制造商告诉寻呼机,“不要退出。当用户完成后,将控制权交还给上游应用程序。不要退出。等待。”
因此,当您使用各种寻呼机命令仔细阅读该块时,您可以使用它的quit
命令告诉它您已像往常一样完成。
但现在寻呼机没有退出,而是以某种方式将终端控制权交还给git add
。
git 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 -p
的split
命令
您是否考虑过使用git add -p
的split
命令来打断大佬?无论如何,我发现更小的帅哥更容易理解!
【讨论】:
您的回答似乎假设需要同时从终端读取两个应用程序。我不认为是这种情况:为什么不能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 \"$@\" #"
按e
在less
中寻呼大块头
按q
暂存显示的内容
按v
编辑显示的内容
按^C
退出并重复交互式菜单
我正在做一个 PR 来解决 git
本身的问题。
【讨论】:
以上是关于如何使用寻呼机进行长 git add --patch hunks?的主要内容,如果未能解决你的问题,请参考以下文章