Git Bash застревает в diff/log, спонтанно повторяет одну и ту же команду снова и снова
У меня возникла странная проблема с Git Bash в Windows 7/XP. Он работал нормально, но в последнее время я обнаружил, что после выполнения git diff
или git log
, Git Bash становится непригодным: после diff/log, даже после того, как я вернусь в командную строку, Bash держится внезапно и, по-видимому, спонтанно повторяя ту же команду, неуправляемый, и пока я нахожусь в середине ввода следующей команды.
У кого-нибудь еще была эта проблема? Любые советы будут высоко оценены, потому что это действительно ограничивает полезность Git Bash на данный момент.
Ответы
Ответ 1
Вам нужно использовать q
для выхода из git пейджера. Использование Ctrl-C вызывает проблемы только в Windows.
Ctrl-C не должен выходить из пейджера (и он не работает в Linux-системе). Когда вы Ctrl-C на окнах (msysgit, я полагаю?), Вы как-то убиваете процесс "извне" (т.е. Из cmd.exe). Я не знаю точных причин, почему это происходит.
Как я уже сталкивался с подобными проблемами в прошлом: старайтесь ударить q
и Ctrl-C в случайном порядке, если вам повезет, вы снова получите рабочее приглашение;) [Нет лучшего решения Я знаю... но это сработало для меня...]
Ответ 2
Обратите внимание, что при Git 2.12 (Q1 2017, 6+ лет спустя) a Ctrl + C в сеансе пейджера Git должен вести себя лучше.
См. commit 46df690, зафиксировать 246f0ed, commit 2b296c9 (07 января 2017 г.) Джефф Кинг (peff
).
(слияние Junio C Hamano - gitster
- в commit 5918bdc, 18 января 2017 г.
execv_dashed_external
: подождите, пока ребенок не достигнет смерти
Ввод ^C
в pager
, который обычно не убивает его, убил Git и снял пейджер в качестве побочного урона в определенной структуре дерева процессов. Это было исправлено.
Вы можете запускать любой штрихованный внешний с помощью команд типа git -p stash list
, где команда завершается, но пейджер все еще идет.
Короткий вариант состоит в том, что все должно нормально останавливаться (Git и пейджер)
Но подробно:
Когда git
запускает a pager
, важно для процесса Gitповесьте и дождитесь окончания pager
, хотя это больше нет данных для его подачи.
Это связано с тем, что git
порождает pager
в качестве дочернего элемента, и, таким образом, процесс git
является лидером сеанса на терминале. После того, как он умрет, pager
завершит свое текущее чтение с терминала (есть один символ), а затем получите EIO
попытку прочитать снова.
Примечание: EIO
(ошибка 5) tands для ввода/вывода ошибок и (источник):
для всех неожиданных аппаратных ошибок. Это может быть связано с физическими ошибками, но, кроме того, получит сиротный процесс (процесс, родитель которого умер), который пытается читать со стандартного ввода. BSD-системы возвращают это, если вы пытаетесь открыть устройство pty, которое уже используется.
Попытка чтения из закрытого потока вернет EIO, а также прочитает или напишет диск, который находится за пределами физических границ устройства.
Открытие /dev/tty
, когда процесс не имеет управляющего tty, также вернет обратно EIO
.
Итак (вернемся к ^C
в pager
):
Когда вы нажмете ^C
, который отправит SIGINT
в git
и в pager
, и это аналогичная ситуация.
pager
игнорирует его, но процесс git
должен стоять, пока пейджер не будет выполнен. Мы обратились к этому давно в a3da882 (пейджер: do wait_for_pager о сигнале смерти, 2009-01-22).
Но когда у вас есть пунктирный внешний (или псевдоним, указывающий на встроенный, который будет выполнять повторный exec Git для встроенного), в миксе есть дополнительный процесс.
Например, запуск:
$ git -c alias.l=log l
закончится с деревом процессов, например:
git (parent)
\
git-log (child)
\
less (pager)
Если вы нажмете ^C
, SIGINT
перейдет ко всем из них. Пейджер игнорирует его, а дочерний процесс Git завершится в wait_for_pager().
Но родительский процесс Git умрет, и обычно возникают проблемы с EIO.