<feed xmlns='http://www.w3.org/2005/Atom'>
<title>npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/src/bin, branch v2.2.3</title>
<subtitle>Personal mirror of DanConwayDev/ngit-cli on git.upleb.uk
</subtitle>
<id>https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/atom?h=v2.2.3</id>
<link rel='self' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/atom?h=v2.2.3'/>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/'/>
<updated>2026-02-27T17:19:20+00:00</updated>
<entry>
<title>fix: skip ^{} peeled-tag refs in sync to prevent invalid refspec crash</title>
<updated>2026-02-27T17:19:20+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-27T17:17:12+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=e7d7f933cd7eac19434f09096a311adeb5e60747'/>
<id>urn:sha1:e7d7f933cd7eac19434f09096a311adeb5e60747</id>
<content type='text'>
Regression introduced in 28ad5440: ngit sync crashed with
'invalid refspec refs/remotes/origin/v1.4.4^{}:refs/tags/v1.4.4^{}'
on repos with annotated tags. Fixed by guarding all three iteration
sites in sync.rs and identify_remote_sync_issues in list.rs; also
corrected the always-false logic bug in invalid_nostr_state_ref.
</content>
</entry>
<entry>
<title>feat: ngit sync --force republishes state event even with no ref changes</title>
<updated>2026-02-27T15:53:11+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-27T15:51:01+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=71cd982e5ca3e6f60fdf33fd41d0db3eabdbf39f'/>
<id>urn:sha1:71cd982e5ca3e6f60fdf33fd41d0db3eabdbf39f</id>
<content type='text'>
allows users to repair repos whose state event is missing ^{} peeled refs
for annotated tags (or any other corruption) without needing to push a new
ref. the new event is signed with a fresh timestamp and broadcast to all
repo relays and the user's write relays.
</content>
</entry>
<entry>
<title>fix: annotated tags missing from list due to dropped peeled refs</title>
<updated>2026-02-27T15:46:37+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-27T15:40:24+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=28ad5440c7184de9833f8448bc90153ee4499c83'/>
<id>urn:sha1:28ad5440c7184de9833f8448bc90153ee4499c83</id>
<content type='text'>
RepoState::try_from was explicitly discarding all refs/tags/*^{} entries
("peeled" refs) when parsing the nostr state event. This meant the list
command only advertised the tag object OID, but git requires two lines for
annotated tags:

  &lt;tag-object-oid&gt; refs/tags/v1.0.0
  &lt;commit-oid&gt;     refs/tags/v1.0.0^{}

Without the ^{} peeled line git cannot resolve the tag to a commit, so
git fetch --prune treats it as unresolvable and deletes it.

The nostr state event already stores both entries correctly (written by
generate_updated_state in push.rs). The fix simply stops try_from from
discarding the ^{} entries on read, so they flow through to the list
output unchanged.
</content>
</entry>
<entry>
<title>feat: add --bunker-url to account login for non-interactive use</title>
<updated>2026-02-27T14:24:57+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-27T10:07:30+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=2c48e37f8341e0d207dd3260c439a0729464b03d'/>
<id>urn:sha1:2c48e37f8341e0d207dd3260c439a0729464b03d</id>
<content type='text'>
allows non-interactive bunker:// URL login without requiring --nsec,
by connecting to the remote signer and saving credentials to git config
</content>
</entry>
<entry>
<title>fix: correct merge-base in PR events from git push of pr/ branch</title>
<updated>2026-02-26T16:35:59+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T16:35:59+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=01aeb2a3265bcafa162987c85dd281981770bba7'/>
<id>urn:sha1:01aeb2a3265bcafa162987c85dd281981770bba7</id>
<content type='text'>
When pushing a pr/ branch, the ahead slice is reversed by callers before
being passed to generate_patches_or_pr_event_or_pr_updates, making it
oldest-first. The tip/first_commit assignments were backwards (using
first()/last() as if the slice were youngest-first), so the merge-base
was computed as the parent of the PR tip rather than the parent of the
oldest commit. Multi-commit PRs therefore showed only 1 commit when
applied via ngit apply.

Adds an integration test that pushes a two-commit large-file PR branch
and asserts the merge-base tag equals the main branch tip.
</content>
</entry>
<entry>
<title>fix: store tag object OID in tracking ref for annotated tags after push</title>
<updated>2026-02-26T15:26:22+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T15:23:04+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=54f0542a27e4ccab459d87283e4668d865ddd2bb'/>
<id>urn:sha1:54f0542a27e4ccab459d87283e4668d865ddd2bb</id>
<content type='text'>
update_remote_refs_pushed was calling peel_to_commit() for all refs,
discarding the tag object OID for annotated tags. This caused a mismatch
with generate_updated_state, which correctly stores the tag object OID in
the nostr state event. ngit sync would then push the commit OID to grasp
servers that expected the tag object OID, causing rejections.
</content>
</entry>
<entry>
<title>fix: advertise only state events with resolvable git objects</title>
<updated>2026-02-26T15:26:20+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T14:00:12+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=d8b85cbce5cba9bfb8b15a8bd5c1b7200ff3e488'/>
<id>urn:sha1:d8b85cbce5cba9bfb8b15a8bd5c1b7200ff3e488</id>
<content type='text'>
git-remote-nostr now walks the per-relay state events captured in
FetchReport::state_per_relay (newest first) and advertises the first
one whose every OID is either present on at least one git server
(confirmed via list_refs) or already available locally.  If no such
state event exists it falls back to the raw git server state.

Previously the latest nostr state event was always used regardless of
whether its OIDs had been pushed to any server, causing catastrophic
missing-object errors during clone or fetch when a state event was
published ahead of the corresponding git push.
</content>
</entry>
<entry>
<title>fix: strip refs/tags/ prefix when computing remote tracking ref name</title>
<updated>2026-02-26T15:26:19+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T13:41:01+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=b85683201250e97a30bfe7a5dbba5508f8e86f65'/>
<id>urn:sha1:b85683201250e97a30bfe7a5dbba5508f8e86f65</id>
<content type='text'>
refspec_remote_ref_name() only stripped refs/heads/, so tag refspecs
produced refs/remotes/origin/refs/tags/v1.0.0 instead of
refs/remotes/origin/v1.0.0. ngit sync reads the latter form, so the
tracking ref was never found and sync failed with 'src refspec does not
match any existing object'.
</content>
</entry>
<entry>
<title>feat: publish state event to stale grasp relays before sync push</title>
<updated>2026-02-26T15:26:18+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T13:31:44+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=0d6ed93e4d143bb066205543af13f0ec6ddbdd58'/>
<id>urn:sha1:0d6ed93e4d143bb066205543af13f0ec6ddbdd58</id>
<content type='text'>
FetchReport now captures the full state event seen on each relay during
the nostr fetch (state_per_relay: HashMap&lt;RelayUrl, Option&lt;Event&gt;&gt;).
ngit sync uses this to identify grasp server relays with a missing or
outdated state event and publishes the current state event to them
before attempting git pushes, preventing rejections. An existing login
is loaded silently (no prompt, no profile fetch) to provide a signer
for NIP-42 auth if requested.
</content>
</entry>
<entry>
<title>fix: rollback local state event cache on total push failure</title>
<updated>2026-02-26T15:26:18+00:00</updated>
<author>
<name>DanConwayDev</name>
<email>DanConwayDev@protonmail.com</email>
</author>
<published>2026-02-26T12:47:12+00:00</published>
<link rel='alternate' type='text/html' href='https://upleb.uk/npub1sh4dwqc9ypguemh6m8tmxxl8xuzfsz0j8av8vq7t3xd3mldsg9ls4ew80h/ngit-cli-mirror/commit/?id=ee68ccadce6a6c90747cbdaae557babb4683413e'/>
<id>urn:sha1:ee68ccadce6a6c90747cbdaae557babb4683413e</id>
<content type='text'>
When all git servers reject or skip a push, delete the newly-published
state event from the local nostr cache and restore the previous state
event (if any), so that a subsequent retry starts from a clean baseline
rather than a state that no server ever accepted.
</content>
</entry>
</feed>
