From 344a107b557604d3f958e7bf7ebf0901290c50d5 Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Tue, 18 Feb 2025 16:24:35 +0000 Subject: [PATCH] merge-tree --stdin: flush stdout to avoid deadlock MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit If a process tries to read the output from "git merge-tree --stdin" before it closes merge-tree's stdin then it deadlocks. This happens because merge-tree does not flush its output before trying to read another line of input and means that it is not possible to cherry-pick a sequence of commits using "git merge-tree --stdin". Fix this by calling maybe_flush_or_die() before trying to read the next line of input. Flushing the output after each merge does not seem to affect the performance, any difference is lost in the noise even after increasing the number of runs. $ git rev-list --merges --parents -n100 origin/master | sed 's/^[^ ]* //' >/tmp/merges $ hyperfine -L flush 0,1 --warmup 1 --runs 30 \ 'GIT_FLUSH={flush} ./git merge-tree --stdin Acked-by: Elijah Newren Signed-off-by: Junio C Hamano --- builtin/merge-tree.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index 9a6c8b4e4c..57f4340fab 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -18,6 +18,7 @@ #include "tree.h" #include "config.h" #include "strvec.h" +#include "write-or-die.h" static int line_termination = '\n'; @@ -623,6 +624,7 @@ int cmd_merge_tree(int argc, } else { die(_("malformed input line: '%s'."), buf.buf); } + maybe_flush_or_die(stdout, "stdout"); if (result < 0) die(_("merging cannot continue; got unclean result of %d"), result); -- 2.47.3