[PATCH] push: fix --force-if-includes when remote-tracking ref has no reflog
From: Aleksei Sviridkin <hidden>
Date: 2026-09-03 01:05:51
Subsystem:
the rest · Maintainer:
Linus Torvalds
Since 99a1f9ae10 (push: add reflog check for "--force-if-includes", 2020-10-03), is_reachable_in_reflog() stops walking the reflog of the local branch at entries older than the newest reflog entry of the remote-tracking ref. That timestamp is read by a callback of refs_for_each_reflog_ent_reverse() into a variable that is never initialized, so when the remote-tracking ref has no reflog the walk is cut off at whatever happens to be on the stack. With the files backend a remote-tracking ref created by "git clone" has no reflog and does not get one until it moves. On my machine the leftover value exceeds any real timestamp: the walk stops at the very first entry, never reaches the "Created from" entry that "checkout --track" wrote, and the push is rejected with "remote ref updated since checkout" although nothing on the remote has changed. Initialize the timestamp to zero, so that a remote-tracking ref without reflog makes the walk cover the whole reflog of the local branch, as documented. Signed-off-by: Aleksei Sviridkin <redacted> Assisted-by: LLM --- The new test fails without the fix on my machine (macOS, arm64). As the value read is uninitialized, other platforms may pass it by luck. remote.c | 2 +- t/t5533-push-cas.sh | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/remote.c b/remote.c
index 00723b3..6d30169 100644
--- a/remote.c
+++ b/remote.c@@ -2751,7 +2751,7 @@ static int check_and_collect_until(const char *refname UNUSED, */ static int is_reachable_in_reflog(const char *local, const struct ref *remote) { - timestamp_t date; + timestamp_t date = 0; struct commit *commit; struct commit **chunk; struct check_and_collect_until_cb_data cb;
diff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh
index cba26a8..77f46f3 100755
--- a/t/t5533-push-cas.sh
+++ b/t/t5533-push-cas.sh@@ -396,4 +396,22 @@ test_expect_success '"--force-if-includes" should allow deletes' ' ) ' +test_expect_success '"--force-if-includes" should allow forced update when remote-tracking ref has no reflog' ' + rm -fr dst src && + git init --bare dst && + git push dst main main:branch && + git clone --no-local dst src && + test_when_finished "rm -fr dst src" && + ( + cd src && + # a clone leaves the remote-tracking refs without reflog + # entries with the files backend, but not with reftable + git reflog expire --all --expire=all && + git switch -c branch --track origin/branch && + git reset --hard HEAD^ && + test_commit D && + git push --force-if-includes --force-with-lease="branch" + ) +' + test_done
base-commit: e9019fcafe0040228b8631c30f97ae1adb61bcdc -- 2.55.0