Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Push discards pre-push hook output, so an interactive hook looks like a hang

オープン
#420 コメント 0 件 リアクション 2 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
76/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
静か
技術スタック
go
領域
cli

調査の方向性

internal/git/gitops.go の defaultOps.Push 付近と internal/git/git.go の runInteractive 付近を読み、既存のインタラクティブな commit パスと比較します。pre-push hook のシナリオを再現して統合テストを実行します。完了の条件は、hook のプロンプト、出力、git の進捗がターミナルに届き、拒否された push は引き続きエラーを返しつつ stderr が重複しないことです。

索引モデルが issue の本文から書いたものです。

説明

bug topic: cli - push

Summary

Every command that pushes (sync, push, submit, link) runs git push with stdout sent to /dev/null and stderr sent to an in-memory buffer that is only surfaced if the push fails. A pre-push hook that prompts for input therefore prints its question into the void while blocking on /dev/tty, and gh stack sync appears to hang forever with no output and no timeout.

The same discarding affects non-interactive hooks: their logging and git's own transfer progress never appear, so a merely slow hook (a test suite, a linter) is indistinguishable from a hang.

Steps to reproduce

  1. In a repo with a stack, add .git/hooks/pre-push:
#!/bin/sh
echo "Run the full test suite? [y/N] "
read ans < /dev/tty
  1. Run gh stack sync.

Expected: the hook's prompt appears and you can answer it.

Actual: output stops after Pushing N branches to origin... and the command waits indefinitely. Typing y + Enter unblocks it, but nothing on screen indicates input is wanted.

Root cause

internal/git/gitops.godefaultOps.Push ends in runSilent, which routes through the package-level client in internal/git/git.go:16:

var client = &cligit.Client{}

The client is zero-valued, so Stdin, Stdout, and Stderr are nil, and Client.Command copies them straight onto the exec.Cmd (cli/cli/v2/git/client.go:95-97). Nil Stdout on an exec.Cmd means /dev/null; Command.Run swaps nil Stderr for a bytes.Buffer (cli/cli/v2/git/command.go:20-23) that is only read back on failure. The hook process still inherits the controlling terminal, so read < /dev/tty blocks on real keystrokes — but the prompt it wrote to stdout/stderr is gone. context.Background() with no timeout means the wait is unbounded.

Verified with a pre-push hook that wrote to stdout, stderr, and a log file: the log confirmed the hook ran, and neither stream reached the terminal.

The codebase already has the right helper for this — runInteractive (internal/git/git.go:60) wires os.Stdin/Stdout/Stderr and is used for git commit. Push never got equivalent treatment.

Suggested fix

Have Push run through runInteractive so hook prompts, hook output, and git's transfer progress reach the terminal as they are produced. Since git and the hook have then already written their own messages to stderr, the returned error should carry only the exit status rather than folding the buffered stderr back in and printing it twice.

I have this working locally with integration tests covering a real pre-push hook (output visible on success; stderr visible and an error returned when the hook rejects the push). Happy to open a PR if that's welcome, or leave it here for a maintainer to pick up.

Related

  • #135 and #293 both ask for --no-verify. This is a separate problem: those are about skipping hooks, this is about hooks that run correctly but invisibly. A --no-verify flag would not fix the invisible-prompt hang for people who need their hooks to run.
主要言語
Go
スター
1.5k
フォーク
73
平均マージ
1日 8時間
マージ済み PR(30日)
7

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

github/gh-stack のほかの issue

github/gh-stack の issue をすべて見る

似ている issue

Go の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。