如何使 git-log 向上滚动而不是向下滚动

Posted

技术标签:

【中文标题】如何使 git-log 向上滚动而不是向下滚动【英文标题】:How to make git-log scroll up instead of down 【发布时间】:2016-06-15 01:50:01 【问题描述】:

每当我在终端模拟器中查看git log --all --graph --oneline --decorate 输出时,都会在终端屏幕顶部查看第一个提交。当我使用q 退出git log 输出视图时,其中的几行不再可见,因为屏幕底部附加了一些新行,用于下一个命令。

不过,通常情况下,最上面的那几行是最有趣的,因为它们类似于最近的 git 历史记录,所以我希望它们在我键入下一个 git 命令时仍然可见。

如何使git log 输出从屏幕底部开始出现,即在底部查看第一个提交?您必须向上滚动才能查看较旧的提交。

注意:--reverse 标志不是一个选项有两个原因。

    每次您必须一直滚动到底部才能查看第一个 提交。那不应该是必要的。我想从底部开始。 它不与 --graph 标志结合使用:fatal: cannot combine --reverse with --graph

【问题讨论】:

你试过git log --reverse吗? Can I get git log to print the history in reverse order?的可能重复 @Jubobs 没有重复。 Git log --reverse 将从最后一次提交开始,这不是我想要的。此外,它不能与 --graph 结合使用。将更新问题以将其作为要求包含在内 When I have git log print out as oneline, how do I reverse it?的可能重复 @FarhadFaghihi 不,不,不。阅读问题。 【参考方案1】:

原来的答案,这不起作用,所以转到工作版本的编辑

如果直接从命令行使用,以下sed 解决方案对我有用。它不使用任何临时字符串通过seds y 命令切换\/

$ git --no-pager log --all --graph --decorate --oneline --color=always | tac | sed 'h
s!\( *[0-9a-z]\7\ .*\)\0,1\$!\1!
y/\\\/_¯/\/\\¯_/
x
s!\(.*\)\( *[0-9a-z]\7\ .*\)\0,1\$!\2!
x
G
s/\n//' | less -X +G -r

它假定 SHA 代码长度为 7 个字符,并使用它来“识别”不是\/|_*<space>,我无法将它们放在第一个 s 命令的搜索模式的开头,并在第二个 s 命令中代替第一个 .

我不知道为什么当所有 sed 命令都放在使用 seds -f 选项调用的脚本中时,我无法让它工作。

EDIT(上面的代码其实有问题)

正如@user1902689 所指出的,sed 脚本可以让任何人(包括我自己)眼睛流血,因为它们非常神秘。

在我看来,如果不使用--color=always,则任务将很容易完成,在这种情况下,文本从git log 输出 会和我们在屏幕上看到的一样;使用--color=always,相反,插入像^[[33m这样的控制序列穿插在文本中来控制着色(不同的分支颜色不同,...)。

但是有一个彩色输出很好,所以我将git log --color=always ... 的输出定向到文件,并查看它,发现哈希总是出现在^[[33m^[[m 之间,其中^[ 是按 Ctrl+V,然后按 Esc 可获得单个字符。这些本质上是 bash 解释为将颜色分别设置为黄色和变回白色的转义序列 (link)。

哈希值,它不是该行中唯一的 7 个字母数字字符串(eg thiswrd 可以在提交主消息中),几乎可以肯定是 first 一个,所以贪心表达式 (sed has no non-greedy expressions) 可以安全地在 之后 使用,而 不能在之前.* 在哈希匹配正则表达式之前该正则表达式匹配该行的最后一个 7 字母数字字符串,例如,它可能是 anytext,而哈希值会在 .* 的某处丢失)。为了允许以不吞噬散列的方式使用贪婪的.*,我们可以将散列括在换行符\n 匹配. 中的 .* (因此,它们必须显式键入) 使用 s 命令,以便我们可以在连续的 s 中“限制”.* 的贪婪通过在搜索模式中显式使用一些\n 命令。

认为以下代码(稍后解释)不是确定的,因为它对用于获取彩色哈希字符串的着色转义序列进行硬编码,但只要我尝试过,它就可以工作。

$ git --no-pager log --all --graph --decorate --oneline --color=always | tac | sed '
s/\(\(^[\[33m\)\([0-9a-z]\7\\)\(^[\[m\)\(.*\)\)/\2\n\3\n\4\5/
h
s/^.*\(\n[a-z0-9]\7\\n.*\|$\)/\1/
x
s/\n[a-z0-9]\7\\n.*$//
y/\\\/_¯/\/\\¯_/
G
s/\n\([a-z0-9]\7\\)\n/\1/
s/\n//' | less -X +G -r

每一行包含三个部分Graph OpeningColorTagHashClosingColorTag Message,或者只包含第一部分Graphsed 字符串由 9 个命令组成,这些命令执行我打算对原始答案执行的操作,但方式略有不同(尤其是某些命令的顺序颠倒了,以保存 x 命令)。

    第一个s 命令在Hash 字符串[0-9a-z]\7\ 的每一侧放置一个换行符\n(如果此行中没有散列,则不执行任何操作;请注意合并之前/之后的行/分歧没有散列或消息跟随它们)。这样做的目的是“隔离”Hash。请注意,捕获组\(...\) 是根据打开标记\( 的出现顺序编号的,因此在替换字符串\2\n\3\n\4\5 中: \2 指的是^[\[33m,即OpeningColorTag(注意:^[ 是通过按Ctrl+V,然后按 获得的单个字符Esc,而“真”[ 必须使用反斜杠 \); \3指的是Hash[0-9a-z]\7\ \4 指的是ClosingColorTag^[\[m(这里所说的\2 也成立); \5 是后面的任何内容,.*(隐含到行尾)。

现在,模式空间(当前行,正如我们目前所编辑的那样)包含原始行,在散列 (Graph OpeningColorTag\nHash\nClosingColorTag Message) 的每一侧都有两个嵌入的换行符,或者如果它不包含散列,则为未修改的原始行(Graph)。

    h 命令将模式空间“保存”到保持空间(将其视为抽屉)。

现在模式和保持空间具有相同的内容(Graph OpeningColorTag\nHash\nClosingColorTag MessageGraph)。

    第二个 s 命令捕获并替换,仅使用它自己 (/\1/) 并丢弃它之前的所有内容 (^.*, ie Graph OpeningColorTag),或者 (\| 分隔捕获组中的替代品\(...\)) 换行符封闭的散列及其后面的所有内容(提交主消息)\n[a-z0-9]\7\\n.*, 或行尾$

现在模式空间包含\nHash\nClosingColorTag Message,如果没有散列,则为空字符串。

    x命令交换pattern和hold space的内容,使得多行\nHash\nClosingColorTag Message(或空字符串)保存在hold space,多行Graph OpeningColorTag\nHash\nClosingColorTag Message在pattern space,准备就绪重新编辑。 第三个s 命令从模式空间中去除\nHash 及其后面的所有内容。

现在模式空间包含Graph OpeningColorTag

    y 将前两个非转义 / 之间的每个字符替换为第二个和第三个非转义 / 之间的对应字符。这里反斜杠和正斜杠都必须用反斜杠转义。 (这应该是安全的,因为OpeningColorTag 不应包含任何已翻译的字符。)

现在模式空间包含Hparg OpeningColorTag,其中HpargGraph 的“反转”版本(或仅Hparg)。

    G 命令获取保留空间的内容并将其附加到(因此大写的G;小写的g复制到 而不是附加到)模式空间,中间有一个换行符\n

现在模式空间包含Hparg OpeningColorTag\n\nHash\nClosingColorTag Message(或仅Hparg\n),从现在开始我们不再关心保持空间。

    第四个s 命令捕获\nHash\n 部分并将其替换为Hash

现在模式空间包含Hparg OpeningColorTag\nHashClosingColorTag MessageHparg\n

    最后一个s 命令删除剩余的换行符\n

最后,模式空间包含Hparg OpeningColorTagHashClosingColorTag MessageHparg

步骤 8. 和 9. 不能融合在一起(eg s/\n\n\([a-z0-9]\7\\)\n/\1/),因为只有当行包含哈希时,包含哈希的两个 \n 才存在(第一个 @987654436第 1 点的@。如果没有哈希,则不执行任何操作),而第一个 \n 始终存在,因为它带有 G 命令。


实际上最外部的组\(...\) 是不需要的(确实没有使用),因此可以将其删除,并且所有对其他捕获的数字引用组可以减1,eg s/\(\(^[\[33m\)\([0-9a-z]\7\\)\(^[\[m\)\(.*\)\)/\2\n\3\n\4\5/ 可以改为s/\(^[\[33m\)\([0-9a-z]\7\\)\(^[\[m\)\(.*\)/\1\n\2\n\3\4/;但我会在答案中保留不必要的组,因为它有机会提及不那么广为人知的捕获组编号。

【讨论】:

有没有机会对每一行进行快速评论,以帮助对sed有所了解但看到此内容时眼睛模糊的读者?有点像接受的答案,这对我来说不能正常工作。 变成这样:| | * 2ac7376 将远程跟踪分支“grooverdan\gcc-power-tune”合并到 travis¯ppc64le @user1902689,我想我已经修复了命令(前者仍在答案中,以防万一)。我试图解释清楚,但sed 脚本无论如何都非常神秘。如果您还有其他需要,请再次评论。 哇,我希望能添加几句话。我真的很感激你在那里所做的工作。不能感谢你。它不仅在这里帮助我,而且最终让我走出我的sed 舒适区。但是,我确实在复制/粘贴新的 less 时显示为空。删除less 给出:sed: -e expression #1, char 64: unterminated 's' command。使用 GNU sed 4.5。我最终想在我的.gitconfig 中将其作为lg 的别名添加,所以在我可以在bash 中运行它之后,我会看看我是否可以找出sed -f 问题,或者如何重新逃避.gitconfig中的一切。 新版本可以将其导出到文件(删除开始/结束单引号)和-f,这使得将其添加到.gitconfig 变得微不足道。 (我从未尝试过-f 和原始版本。)lgnew = "!f() git --no-pager log --all --graph --decorate --oneline --color=always | tac | sed -f /etc/sed/gitGraphFlip.sed; ; f"【参考方案2】:

这是一个似乎可以捕捉到大多数边缘情况的答案。未经彻底测试。

[alias]
    rlog = !"git --no-pager log --all --graph --decorate --oneline --color=always | tac | awk -f ~/switchslashes.awk | less -X +G -r"

文件~/switchslashes.awk包含的位置


    match($0,/([[:space:][:cntrl:]|*\/\\]+)(.*)/,a) # find the segment of the graph
    tgt = substr($0,RSTART,RLENGTH)     # save that segment in a variable tgt
    gsub(/\//,RS,tgt)                   # change all /s to newlines in tgt
    gsub(/\\/,"/",tgt)                  # change all \s to /s in tgt
    gsub(RS,"\\",tgt)                   # change all newlines to \s in tgt
    gsub(/_/,"¯",tgt)                   # change all _ to ¯ in tgt
    print tgt substr($0,RSTART+RLENGTH) # print tgt plus rest of the line

这是this script 的修改版本。它将下划线替换为上划线,将斜杠替换为反斜杠,反之亦然。这会在文本被 tac 反转后修复图形。

免责声明

我从来没有开始使用它,因为它在较大的存储库中速度很慢。它需要加载所有内容,然后应用替换,这对我来说太耗时了。

【讨论】:

在 OS X 上,tac 不可用。您可以安装 GNU coreutils 并改用 gtac。 用免责声明修改了答案。【参考方案3】:

首先,您始终可以将-n 传递到日志以打印出您感兴趣的任意数量的提交。


如何使 git log 输出显示为反向

使用--reverse 标志:

--reverse

以相反的顺序输出提交。

git log --reverse

您可以在此处阅读有关 git log 的更多提示和标志:http://www.alexkras.com/19-git-tips-for-everyday-use/

【讨论】:

我不知道我对哪些行感兴趣,所以我不能-n。另外,我已经更新了关于需要使用 --graph 参数的 OP,该参数不与 --reverse 一起使用。【参考方案4】:

一个接近预期结果的命令是

git --no-pager log --all --graph --decorate --oneline --color=always | tac | less -r +G -X

但是,这仍然会使图表有些混乱,因为斜线没有正确反转。

更新

此命令还负责将斜杠与反斜杠交换,反之亦然。

git --no-pager log --all --graph --decorate --oneline --color=always | tac | sed -e 's/[\]/aaaaaaaaaa/g' -e 's/[/]/\\/g' -e 's/aaaaaaaaaa/\//g' | less -r +G -X

对应的git别名是

[alias]
    rlog = !"git --no-pager log --all --graph --decorate --oneline --color=always | tac | sed -e 's/[\\]/aaaaaaaaaa/g' -e 's/[/]/\\\\\\\\/g' -e 's/aaaaaaaaaa/\\\\//g' | less -r +G -X"

【讨论】:

使用***.com/a/35754356/1546844中的awk替换脚本,可以改进斜线切换,使其仅适用于图形部分

以上是关于如何使 git-log 向上滚动而不是向下滚动的主要内容,如果未能解决你的问题,请参考以下文章

单击按钮时如何使HTML页面一直向上滚动? [复制]

单击按钮时如何使HTML页面一直向上滚动? [复制]

在向上和向下滚动时,使.removeClass()和.addClass()平滑过渡

为啥我的导航栏在向下滚动时不隐藏而在向上滚动时出现?

如何在快速向上或向下滚动时退出键盘? [关闭]

React - 向下滚动时向上滑动固定导航栏,向上滚动时向下滑动