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 diff
或git 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
: 等待孩子信号死亡
键入
^C
到pager
,这通常不会杀死它,杀死Git 并将寻呼机作为某些进程树结构中的附带损害。 此问题已修复。
您可以使用git -p stash list
之类的命令运行任何虚线外部,命令运行完毕,但寻呼机仍在运行。
简短的版本是一切都应该正常停止(Git和寻呼机)
但详细一点:
当
git
运行pager
时,git 进程必须 闲逛并等待pager
完成,即使它 没有更多数据可以提供给它。 这是因为git
将pager
作为子进程生成,因此git
进程是终端上的会话负责人。在它死后,pager
将完成从终端的当前读取(吃掉那个 字符),然后让EIO
尝试再次读取。
注意:EIO
(错误 5)代表错误 I/O,并且是(source):
捕捉各种意外硬件错误。它可能来自物理错误,但另外,尝试从标准输入读取的孤立进程(其父进程已死亡)将得到此错误。如果您尝试打开已在使用的 pty 设备,BSD 系统会返回此信息。 尝试从已关闭的流中读取将返回 EIO,磁盘读取或写入超出设备的物理范围。 当进程没有控制 tty 时打开
/dev/tty
也会吐回EIO
。
所以(在pager
中返回^C
):
当您点击
^C
时,会将SIGINT
发送到git
和pager
, 这是一个类似的情况。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)
如果您点击
^C
,SIGINT
会发送给所有用户。寻呼机忽略它,子 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 忽略新文件和已删除文件?
Github 操作错误;看不到 Master 的 git diff