From: Kristoffer Haugsbakk Date: Tue, 13 Jan 2026 20:26:45 GMT Subject: [BUG] push: pre-push hook that waits for stdin is slow Message-ID: <249f08d1-4457-4a41-8dbe-9725c0c392de@app.fastmail.com> Thank you for filling out a Git bug report! Please answer the following questions to help us understand your issue. What did you do before the bug happened? (Steps to reproduce your issue) Used `git push` with a pre-push hook which included a loop over standard input (stdin): ``` #!/usr/bin/env bash while read -r -a array do # what the loop body does is not important : done ``` At first I tested with a loop body. But I got the same behavior with `:`. It’s just the usual: check if what we are about to push is to some blessed branch. If it is it says that the push failed and tells the user to use `--no-verify` if they are sure. What did you expect to happen? (Expected behavior) For the hook to finish quickly and the push to finish within a few seconds at most. What happened instead? (Actual behavior) The push to the remote (Bitbucket cloud) takes over a minute. But not with `git push --no-verify`. Then it takes a few seconds. What's different between what you expected and what actually happened? Time. Anything else you want to add: I bisected using `timeout 3 git push ...` with a local remote to 857f047e (hook: allow overriding the ungroup option, 2025-12-26). I used a script on my own $dayjob repository. But I also tested the following script on commit f0f19d01 (fails) and the commit right before it (does not fail). It uses a pre-push hook which is just `cat`. Apparently it has to do with how stdin is handled. An empty script does not have this problem. And neither does a script that just uses `echo` (example). ``` #!/bin/sh uuid=d0befd7e-efe4-11f0-b6e1-8b95c76aee96 repo="$HOME"/"$uuid" # Destroy test stuff cleanup () { rm -rf "$repo" } setup () { # I seem to need a realistic/meaty repo git clone . "$repo" && ( cd "$repo" && git tag test-tag && remote=b896ac6c-efe7-11f0-bebc-3bf1b96c1ded git clone . "$remote" && git remote add local "$remote" && # hook setup mkdir hooks && cat <<-\EOF >hooks/pre-push && #!/bin/sh cat EOF chmod +x hooks/pre-push ) } if test "$1" = cleanup then cleanup echo >&2 "bisect: cleaned up test data" exit 128 fi && if ! test -e "$repo" then setup fi && make || exit 125 timeout 3 \ ./bin-wrappers/git -C "$repo" -c core.hookspath=hooks \ push local test-tag # exit code 124: timeout(1) timed out if test "$?" = 124 then exit 1 else exit 0 fi ``` I tested and reproduced the issue on `master`, `next`, and `seen`: • master: on 8745eae5 (The 17th batch, 2026-01-11) • next: 054afa95 (Sync with 'master', 2026-01-12) • seen: b351b516 (Merge branch 'bc/sha1-256-interop-02' into seen, 2026-01-12) Please review the rest of the bug report below. You can delete any lines you don't wish to share. [System Info] git version: git version 2.52.0.421.gc32ead4fc78 cpu: x86_64 built from commit: c32ead4fc78dfd0327f6b2599e4fdca8166afa18 sizeof-long: 8 sizeof-size_t: 8 shell-path: /bin/sh rust: disabled libcurl: 7.81.0 OpenSSL: OpenSSL 3.0.2 15 Mar 2022 zlib: 1.2.11 SHA-1: SHA1_DC SHA-256: SHA256_BLK default-ref-format: files default-hash: sha1 uname: Linux 6.8.0-90-generic #91~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov 20 15:20:45 UTC 2 x86_64 compiler info: gnuc: 11.4 libc info: glibc: 2.35 $SHELL (typically, interactive shell): /bin/bash [Enabled Hooks] commit-msg post-applypatch post-checkout post-commit post-merge post-rewrite pre-auto-gc pre-push reference-transaction -- Kristoffer