Git Bash 卡在 diff / log 上,自发地一遍又一遍地重复相同的命令

Posted

技术标签:

【中文标题】Git Bash 卡在 diff / log 上,自发地一遍又一遍地重复相同的命令【英文标题】:Git Bash gets stuck on diff / log, spontaneously repeats same command over and over 【发布时间】:2011-11-27 18:42:59 【问题描述】:

我在 Windows 7 / XP 上遇到了一个奇怪的 Git Bash 问题。它曾经工作得很好,但最近我发现在我执行git diffgit log 之后,Git Bash 变得无法使用:在 diff/log 之后,即使我返回命令提示符后,Bash 仍然突然而且显然是自发地重复相同的命令,未经提示,而我正在输入后续命令。

还有其他人遇到过这个问题吗?任何建议都将不胜感激,因为目前这确实限制了 Git Bash 的用处。

【问题讨论】:

您是否使用q 退出寻呼机? 啊,不 - 我使用 Ctrl-C 返回命令提示符。那是错的吗?奇怪的是它以前可以正常工作,但现在不行了。 Ctrl-C 不应退出寻呼机(在 linux 系统上也不会)。当您在 Windows 上按 Ctrl-C 时(我想是 msysgit?),您会以某种方式“从外部”杀死进程(即来自 cmd.exe)。 【参考方案1】:

你必须使用q 来退出 git 的寻呼机。使用 Ctrl-C 只会在 windows 上导致问题。

Ctrl-C 不应退出寻呼机(在 linux 系统上也不会)。当您在 Windows 上按 Ctrl-C 时(我想是 msysgit?),您会以某种方式“从外部”(即来自 cmd.exe)杀死进程。我不知道发生这种情况的确切原因。

正如我过去遇到过类似的问题:尝试以随机顺序反复点击q 和 Ctrl-C,如果幸运的话,您会再次得到工作提示;)[没有更好的解决方案我知道——但它对我有用……]

【讨论】:

谢谢,这完全解决了它!我确实在使用 msysgit。有点尴尬的是我只是按了错误的键......虽然 Ctrl-C 有点 几乎 有效,但它很奇怪和令人困惑。无论如何,再次感谢。 一旦我停止使用 Ctrl+C - 不再出现故障!谢谢 在 Ubuntu 11 上,我通过关闭并重新打开终端解决了这个问题。 对我来说,在 Windows 7 上,“q”停止工作的时间更少,但也会冻结屏幕。我在“q”之后输入的所有内容都保留在标准输入中,直到我按下 CTRL-C,此时我所有沮丧的命令尝试都在 shell 中执行!【参考方案2】:

请注意,使用 Git 2.12(2017 年第一季度,6 年多之后),git 寻呼机会话中的 Ctrl+C 应该表现得更好。

参见Jeff King (peff) 的commit 46df690、commit 246f0ed、commit 2b296c9(2017 年 1 月 7 日)。(由 Junio C Hamano -- gitster -- 合并到 commit 5918bdc,2017 年 1 月 18 日)

execv_dashed_external: 等待孩子信号死亡

键入^Cpager,这通常不会杀死它,杀死Git 并将寻呼机作为某些进程树结构中的附带损害。 此问题已修复。

您可以使用git -p stash list 之类的命令运行任何虚线外部,命令运行完毕,但寻呼机仍在运行。

简短的版本是一切都应该正常停止(Git和寻呼机)

但详细一点:

git 运行pager 时,git 进程必须 闲逛并等待pager 完成,即使它 没有更多数据可以提供给它。 这是因为gitpager 作为子进程生成,因此git 进程是终端上的会话负责人。在它死后,pager 将完成从终端的当前读取(吃掉那个 字符),然后让EIO 尝试再次读取。

注意:EIO(错误 5)代表错误 I/O,并且是(source):

捕捉各种意外硬件错误。它可能来自物理错误,但另外,尝试从标准输入读取的孤立进程(其父进程已死亡)将得到此错误。如果您尝试打开已在使用的 pty 设备,BSD 系统会返回此信息。 尝试从已关闭的流中读取将返回 EIO,磁盘读取或写入超出设备的物理范围。 当进程没有控制 tty 时打开/dev/tty 也会吐回EIO

所以(在pager 中返回^C):

当您点击^C 时,会将SIGINT 发送到gitpager, 这是一个类似的情况。pager 会忽略它,但 git 进程需要等待直到寻呼机完成。我们很久以前在a3da882 (pager: do wait_for_pager on signal death, 2009-01-22) 中解决了这个问题。

但是当你有一个破折号的外部(或一个指向内置的别名,它将为内置的重新执行 git)时,混合中有一个额外的过程。 例如,运行:

$ git -c alias.l=log l

最终会得到如下进程树:

  git (parent)
    \
     git-log (child)
      \
       less (pager)

如果您点击^CSIGINT 会发送给所有用户。寻呼机忽略它,子 git 进程将在 wait_for_pager() 中结束。 但是父 git 进程会死掉,通常的 EIO 麻烦就会发生。


在 Git 2.28(2020 年第三季度)中,当一个别名命令(其输出通过 git 管道传输到寻呼机)被信号杀死时,寻呼机进入一个有趣的状态,该状态已被(再次)纠正。

参见Trygve Aaberge (trygveaa) 的commit c0d73a5、commit e662df7(2020 年 7 月 7 日)。(由 Junio C Hamano -- gitster -- 合并于 commit 05920f0,2020 年 7 月 15 日)

Ctrl+C:等待孩子信号死亡,以获得内置函数的别名

签字人:Trygve Aaberge

当您点击 ^C 时,树中的所有进程都会收到它。 当git 命令使用寻呼机时,git 会忽略这一点并等待寻呼机退出。

但是,当使用别名时,树中有一个不会忽略信号的附加进程。这导致它退出,进而导致寻呼机退出。这修复了内置函数的别名。

这最初在46df6906(execv_dashed_external:等待子信号死亡,2017-01-06)中修复,但被ee4512ed(“trace2:创建新的组合跟踪设施”, 2019-02-22,Git v2.22.0-rc0 -- merge 列在 batch #2) 然后 b9140840 ("git: 避免通过虚线形式调用别名内置函数",2019-07-29, Git v2.23.0-rc1 -- merge)。

还有:

当我们运行外​​部命令的别名时,我们希望等待该进程退出,即使在收到通常会杀死 git 进程的 ^C 之后也是如此。当进程忽略 SIGINT(例如,寻呼机经常这样做)时,这很有用,然后我们不希望它被杀死。

拥有调用寻呼机的别名可能并不常见,但它可能很有用,例如如果您有一个 git 命令的别名,该命令使用子 shell 作为参数之一(在这种情况下,您必须使用外部命令,而不是内置命令的别名)。

此补丁与之前的提交类似,但之前的提交仅针对内置命令的别名修复了此问题,而此提交对外部命令的别名进行了相同的修复。除了像之前的提交一样在 clean 之后等待之外,这还可以清理子节点(在之前的提交之前已经为内置函数的别名启用),因为 wait_after_clean 依赖于它。最后,虽然之前的提交修复了回归问题,但我认为这一直无法正常工作。


请注意,如果您使用 trace2 来调试情况,则寻呼机现在已正确跟踪。

当用户生成的寻呼机退出时,跟踪日志没有正确记录其退出状态,这已在 Git 2.31(2021 年第一季度)中得到纠正。

参见Ævar Arnfjörð Bjarmason (avar)commit be8fc53、commit 85db79a、commit c24b7f6、commit 61ff12f(2021 年 2 月 2 日)。(由 Junio C Hamano -- gitster -- 合并到 commit dcb11fc,2021 年 2 月 22 日)

pager:发出信号时正确记录寻呼机退出代码

签字人:Ævar Arnfjörð Bjarmason

当 git 调用一个以非零值退出的寻呼机时,常见的情况是它本身已经返回了正确的 SIGPIPE 失败,但是在 trace2 中记录的退出代码总是被错误地报告1支持>. 修复该问题并在日志中记录正确的退出代码。

由于这为我们提供了在我们最近添加的需要 !MINGW 先决条件的测试之外进行测试的东西,让我们重构测试以在 MINGW 上运行并实际检查 SIGPIPE 之外的 MINGW

wait_or_whine() 仅使用来自 finish_command_in_signal() 的真正 "in_signal" 调用,而 finish_command_in_signal() 又仅在 pager.c 中使用。

in_signal && !WIFEXITED(status)”的情况不在测试范围内。 在这种情况下,让我们记录默认值 -1 以作为衡量标准。

    退出代码的错误记录似乎被复制/粘贴到ee4512e中的finish_command_in_signal()(“trace2:创建新的组合跟踪设施”,2019-02-22,Git v2.22.0-rc0 - - merge 在batch #2 中列出)

【讨论】:

以上是关于Git Bash 卡在 diff / log 上,自发地一遍又一遍地重复相同的命令的主要内容,如果未能解决你的问题,请参考以下文章

如何使 git-diff 和 git log 忽略新文件和已删除文件?

gitlog和diff区别

git 查看对比的方法log diff

Github 操作错误;看不到 Master 的 git diff

sh grep for git log中的一个字符串,使用awk从结果中打印哈希,使用hash来git显示diff

sh grep for git log中的一个字符串,使用awk从结果中打印哈希,使用hash来git显示diff