Git development
 help / color / mirror / Atom feed
From: Tyler Cipriani <tyler@tylercipriani.com>
To: git@vger.kernel.org
Cc: Srinidhi Kaushik <shrinidhi.kaushik@gmail.com>,
	Stefan Haller <lists@haller-berlin.de>,
	"D . Ben Knoble" <ben.knoble@gmail.com>,
	Phillip Wood <phillip.wood123@gmail.com>,
	Johannes Schindelin <Johannes.Schindelin@gmx.de>,
	Tyler Cipriani <tyler@tylercipriani.com>
Subject: [PATCH v2 0/2] push: fix --force-if-includes consulting wrong ref
Date: Tue,  8 Sep 2026 16:20:54 -0600	[thread overview]
Message-ID: <20260908222056.1150748-1-tyler@tylercipriani.com> (raw)
In-Reply-To: <20260904210122.431757-1-tyler@tylercipriani.com>

Changes since v1:

- Clarify in log message 1/2 that --force-if-includes will reject a
  detached HEAD today (when the same-named local branch lacks the remote
  tip). And note that this change makes it explicit to always reject
  the detached HEAD case.

--force-if-includes has been checking the reflog of the local branch named
after the destination branch regardless of what's being pushed. This can cause
false rejections or unintended data loss.

False rejection has been reported twice that I could find:

- 2023-07-26 - Stefan Haller reported local branch with a different name
               false rejection[0]
- 2025-05-08 - D. Ben Knoble reported detached HEAD false rejection[1]

The same root cause can result in data loss: when a same-name local branch
contains the remote tip but you --force-if-includes push an unrelated branch,
clobbering the remote repo. PoCs are in t/t5533-push-cas.sh -- new test cases
fail against maint, but pass with patches applied.

Existing tests covered refspecs with different names for --force-with-lease,
but missed --force-if-includes. New patches cover:

- allow forced-update using refspec with different-named local branch
- allow same as above, but with HEAD
- reject force-update using refspec with different-named local branch lacking
  branch tip
- reject same as above using HEAD
- reject detached HEAD

Resolved question: the detached HEAD case; HEAD's reflog was considered
and rejected as too broad for purpose in the original review. cf. [2]

[0]: <https://lore.kernel.org/git/f51c73ed-eb03-83ca-fb31-d3e2645c9a63@haller-berlin.de>
[1]: <https://lore.kernel.org/git/CALnO6CCk0SgwObQRnpd5Pt_DvCKF8dBmyVHivU6Nr_O-GusGLA@mail.gmail.com>
[2]: <https://lore.kernel.org/git/CAHLx=O=tVhtiZpaRP9TpfiBfOMS2xPe3c3=mC3VNEdBrLOioFg@mail.gmail.com>

Tyler Cipriani (2):
  push: check pushed ref for --force-if-includes
  push: fix --force-if-includes detached HEAD advice

 Documentation/config/advice.adoc |  4 ++
 advice.c                         |  1 +
 advice.h                         |  1 +
 builtin/push.c                   | 15 +++++++
 builtin/send-pack.c              |  5 +++
 remote.c                         | 27 +++++++++++-
 remote.h                         | 10 +++--
 send-pack.c                      |  1 +
 t/t5533-push-cas.sh              | 70 +++++++++++++++++++++++++++++++-
 transport-helper.c               |  5 +++
 transport.c                      |  8 ++++
 transport.h                      |  1 +
 12 files changed, 143 insertions(+), 5 deletions(-)

Range-diff against v1:
1:  5e866b883e ! 1:  da27c421ed push: check pushed ref for --force-if-includes
    @@ Commit message
         the remote main.
     
         Find local reflog using ref->peer_ref. When using a refspec like
    -    HEAD:refs/heads/main, we resolve HEAD to a branch and use that reflog.
    -    In a detached HEAD state, the reflog cannot tell us if the history
    -    being pushed includes the tip of the remote, so the push is rejected.
    +    HEAD:refs/heads/main, we resolve HEAD. If HEAD is a branch, use that
    +    branch's reflog.
    +
    +    But if HEAD does not resolve to a branch (i.e. a detached HEAD), then we
    +    reject the push. HEAD's reflog is too broad to tell us if the history
    +    being pushed includes the tip of the remote. Rejecting a detached HEAD
    +    already happens today (if the same-named local branch lacks the remote
    +    tip); now the detached HEAD state is explicitly rejected.
     
         Skip deletions:
     
2:  4ae40db7fe = 2:  e07d16d53e push: fix --force-if-includes detached HEAD advice

base-commit: e9019fcafe0040228b8631c30f97ae1adb61bcdc
-- 
2.47.3


  parent reply	other threads:[~2026-09-08 22:21 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04 21:01 [PATCH 0/2] push: fix --force-if-includes consulting wrong ref Tyler Cipriani
2026-09-04 21:01 ` [PATCH 1/2] push: check pushed ref for --force-if-includes Tyler Cipriani
2026-09-05 18:57   ` Ben Knoble
2026-09-04 21:01 ` [PATCH 2/2] push: fix --force-if-includes detached HEAD advice Tyler Cipriani
2026-09-05 18:59 ` [PATCH 0/2] push: fix --force-if-includes consulting wrong ref Ben Knoble
2026-09-06 20:24   ` Tyler Cipriani
2026-09-08 22:20 ` Tyler Cipriani [this message]
2026-09-09 11:59   ` [PATCH v2 " D. Ben Knoble
2026-09-08 22:20 ` [PATCH v2 1/2] push: check pushed ref for --force-if-includes Tyler Cipriani
2026-09-10 18:43   ` Junio C Hamano
2026-09-10 22:08     ` Tyler Cipriani
2026-09-08 22:20 ` [PATCH v2 2/2] push: fix --force-if-includes detached HEAD advice Tyler Cipriani
2026-09-10 23:05 ` [PATCH v3 0/2] push: fix --force-if-includes consulting wrong ref Tyler Cipriani
2026-09-10 23:05   ` [PATCH v3 1/2] push: check pushed ref for --force-if-includes Tyler Cipriani
2026-09-11  6:55     ` Patrick Steinhardt
2026-09-11 22:58       ` Tyler Cipriani
2026-09-11 15:31     ` Junio C Hamano
2026-09-11 23:47       ` Tyler Cipriani
2026-09-10 23:05   ` [PATCH v3 2/2] push: fix --force-if-includes detached HEAD advice Tyler Cipriani
2026-09-11  6:55     ` Patrick Steinhardt
2026-09-11 16:03       ` Junio C Hamano
2026-09-11 15:40     ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260908222056.1150748-1-tyler@tylercipriani.com \
    --to=tyler@tylercipriani.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=ben.knoble@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=lists@haller-berlin.de \
    --cc=phillip.wood123@gmail.com \
    --cc=shrinidhi.kaushik@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox