Подтвердить что ты не робот

Git Bash застревает в diff/log, спонтанно повторяет одну и ту же команду снова и снова

У меня возникла странная проблема с Git Bash в Windows 7/XP. Он работал нормально, но в последнее время я обнаружил, что после выполнения git diff или git log, Git Bash становится непригодным: после diff/log, даже после того, как я вернусь в командную строку, Bash держится внезапно и, по-видимому, спонтанно повторяя ту же команду, неуправляемый, и пока я нахожусь в середине ввода следующей команды.

У кого-нибудь еще была эта проблема? Любые советы будут высоко оценены, потому что это действительно ограничивает полезность Git Bash на данный момент.

4b9b3361

Ответ 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.