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

7
每当我在终端模拟器中查看 git log --all --graph --oneline --decorate 的输出时,第一个提交会出现在终端屏幕的顶部。当我用 q 退出 git log 输出视图时,一些行就不再可见了,因为在屏幕底部添加了一些新行以供下一个命令使用。
通常情况下,这些顶部的行是最有趣的,因为它们类似于最近的 git 历史记录,所以当我输入下一个 git 命令时,我希望它们仍然可见。
如何使 git log 输出从屏幕底部开始显示,即首次提交被查看在底部?您需要向上滚动以查看早期提交。
注意:--reverse 标志不是一个选项,原因有两个:
1. 每次都必须向下滚动到底部才能查看前面的提交,这是不必要的。我想从底部开始。 2. 它不能与 --graph 标志结合使用:fatal: cannot combine --reverse with --graph

你试过用 git log --reverse 这个命令了吗? - jub0bs
1
@Jubobs 不要重复。Git log --reverse 会从最后一次提交开始,这不是我想要的。而且,它不能与 --graph 结合使用。将更新问题以包括该要求。 - chtenb
@FarhadFaghihi 不,不,不。请仔细阅读问题。 - chtenb
显示剩余2条评论
4个回答

3
以下sed解决方案对我来说有效,如果直接从命令行中使用。它不使用任何临时字符串来切换\和/,而是依靠sed的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个字符,并使用它来“识别”不是前导序列的\,/,|,_,*和,这些我无法放在第一个s命令的搜索模式开头以及第二个s命令中第一个.的位置。 我不知道为什么当所有sed命令都放在使用sed的-f选项调用的脚本中时,我不能让它工作。正如@user1902689所指出的那样,sed脚本可能使任何人的眼睛流血,包括我自己,因为它们极其晦涩难懂。
在我看来,如果不使用--color=always参数,任务将很容易完成,这种情况下从git log中传出的文本与我们在屏幕上看到的相同;相反,使用--color=always参数会在文本中插入控制序列(例如^[[33m),以控制着色(不同分支使用不同颜色...)。

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

哈希值是该行中不止一个7个字母数字字符的字符串(例如,提交主消息中可能有thiswrd),几乎肯定是第一个,因此可以在其后安全使用贪婪表达式({{link1:sed没有非贪婪表达式}}),但不能在其前使用(在哈希匹配正则表达式之前加上.*会使该正则表达式匹配该行上最后的7个字母数字字符字符串,这可能是anytext,并且哈希值将在.*中丢失)。为了允许以不会吞噬哈希值的方式使用贪婪的.*,我们可以用s命令在换行符\n之间包含哈希值,这些换行符\n不会被.*中的.匹配(因此必须明确输入),从而可以通过在搜索模式中显式使用一些\n来使用后续的s命令限制.*的贪婪性。

我认为以下代码(稍后会解释)并不是最终版本,因为它硬编码了用于获取彩色哈希字符串的颜色转义序列,但只要我尝试过,它就可以工作。

$ 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

每行包含三个部分图形 开始颜色标签 哈希 结束颜色标签 消息,或者只有第一个部分图形sed字符串由9个命令组成,它们以我原来的答案为基础,但是以稍微不同的方式实现(特别是某些命令的顺序被倒转,以节省一个x命令)。
  1. 第一个 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)。
  1. 第二个s命令捕获并替换自身(/\1/),丢弃它之前的所有内容(^.*,即Graph OpeningColorTag),使用\|将备选项分隔在一个捕获组\(...\)中,
    • 换行符包含哈希和其后的所有内容(提交主消息) \n[a-z0-9]\{7\}\n.*,
    • 或行尾$,

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

4. x 命令交换模式空间和保持空间的内容,以便将多行 \nHash\nClosingColorTag Message(或空字符串)保存在保持空间中,并且多行 Graph OpeningColorTag\nHash\nClosingColorTag Message 位于模式空间中,准备重新编辑。
5. 第三个 s 命令从模式空间中删除 \nHash 及其后面的所有内容。
现在,模式空间包含Graph OpeningColorTag
6. y 命令用第一个和第二个非转义 / 之间的每个字符替换第二个和第三个非转义 / 之间的对应字符。在这里,反斜杠和正斜杠都必须用反斜杠进行转义。(这应该是安全的,因为 OpeningColorTag 不应包含任何已翻译的字符。)
现在,模式空间包含 Hparg OpeningColorTag,其中 HpargGraph 的“反转”版本(或仅为 Hparg)。
现在,模式空间包含“Hparg OpeningColorTag\n\nHash\nClosingColorTag Message”(或仅为“Hparg \n”),我们从现在起不再关心保持空间。第四个“s”命令捕获“\n Hash \n”部分,并将其替换为“Hash”。现在,模式空间包含“Hparg OpeningColorTagHashClosingColorTag Message”或“Hparg \n”。最后一个“s”命令删除剩余的换行符“\n”。最终,模式空间包含“Hparg OpeningColorTagHashClosingColorTag Message”或“Hparg”。
步骤8和9不能合并在一起(<例如> <代码>s/\n\n\([a-z0-9]\{7\}\)\n/\1/),因为两个包含哈希的<代码>\n仅在该行包含哈希时存在(如果没有哈希,则第1点的第一个<代码>s无效),而第一个<代码>\n始终存在,因为它随着<代码>G命令一起出现。


实际上,最外层的组\(...\)是不需要的(事实上也没有使用),因此可以将其删除,并且所有对其他捕获组的数字引用都可以减少1,例如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/;但是我会在答案中保留不必要的组,因为它提供了提及捕获组编号并不是如此广泛知晓的机会。


1
有没有可能对每一行进行简短的注释,以帮助那些了解一点 sed 但在查看此内容时眼睛模糊的读者?有点像接受的答案,但对我来说没有正常工作。 - user1902689
1
变成了这样:| | * 2ac7376 将远程跟踪分支'grooverdan\gcc-power-tune'合并到travis¯ppc64le中 - user1902689
1
@user1902689,我想我已经修复了命令(前一个仍然在答案中,以防万一)。我尽量在解释时清晰明了,但是sed脚本无论如何都很难懂。如果您需要其他帮助,请再次评论。 - Enlico
2
哇,我希望能添加几个句子。非常感谢你所做的工作。无法表达我的感激之情。这不仅会帮助我在这里,还可以让我摆脱我的“sed”舒适区。然而,当我复制/粘贴新的内容时,我得到了一个空的“less”显示。删除“less”后出现:sed: -e expression #1, char 64: unterminated 's' command。使用GNU sed 4.5。最终我想将其添加为我的.gitconfiglg的别名,因此在我可以在bash中运行它之后,我将看看是否可以解决sed -f问题或如何重新转义.gitconfig中的所有内容。 - user1902689
1
新版本可以将其导出到文件(删除开头/结尾的单引号)和添加-f参数,这使得将其添加到.gitconfig非常简单。 (我从未尝试过使用 -f 和原始版本。)lgnew =“!f(){ git --no-pager log --all --graph --decorate --oneline --color=always | tac | sed -f /etc/sed/gitGraphFlip.sed; }; f” - user1902689
显示剩余5条评论

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
}

这是一个修改版的脚本,它是该脚本的改进版本。它将下划线替换为上划线,并交换斜杠和反斜杠,以修复在使用tac反转文本后出现的图表问题。
免责声明:
我从未用过这个脚本,因为在处理较大的仓库时速度较慢。它需要加载所有内容,然后应用替换,这需要太多时间。

在OS X上,没有tac命令可用。您可以安装GNU coreutils并使用gtac代替。 - HellaMad
稍微修改了一下答案并加上了免责声明。 - chtenb

1
一个接近预期结果的命令是:
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"

使用在 http://stackoverflow.com/a/35754356/1546844 中提供的 awk 替换脚本,您可以将反斜杠切换应用于图形部分。 - chtenb

1

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


我该如何使git log输出倒序显示?
使用--reverse标志:

--reverse

以相反的顺序输出提交。

git log --reverse

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


我事先不知道我感兴趣的是哪些行,所以我不能使用“-n”。另外,我已经更新了关于需要使用“--graph”参数的OP,这与“--reverse”不相符。 - chtenb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接