Labels: bug
Priority: should-fix
Source: claude
Summary
git trees init checks whether the bare clone succeeded but not whether any of
the three steps that make the container usable succeeded. A half-configured
container still prints initialized … and exits 0.
Evidence
The clone is handled correctly, with rollback (git-trees:188-191):
if ! git clone --bare "$url" "$dir/trees-bare.git"; then
rm -rf "$dir"
return 1
fi
The next three commands are unchecked (git-trees:195-197):
git -C "$dir" config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
git -C "$dir" fetch origin
git -C "$dir" remote set-head origin --auto >/dev/null 2>&1
With no set -e, execution continues past any failure to _seed_agents and
then to echo "initialized $dir (default branch: $def)".
The fetch refspec step is exactly what makes remote-tracking refs work in a
bare clone (a bare clone does not set it up — the README calls this out). If
fetch fails, the container has no origin/* refs, so the very next thing a
user does breaks: git trees add <branch> cannot resolve origin/<default>,
and _default_branch silently falls back to the literal string main
(git-trees:56), which may not exist.
A plausible trigger: the clone succeeds against a reachable host, then the
network drops, or credentials work for read-only clone but the fetch is
interrupted. The user sees "initialized" and a broken container.
Proposed fix
Chain the post-clone steps and roll back on failure, matching the clone path.
set-head --auto is genuinely optional (it fails harmlessly on a remote with
no HEAD), so leave it unchecked:
if ! git -C "$dir" config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*' \
|| ! git -C "$dir" fetch origin; then
echo "git trees init: clone succeeded but fetch/config failed — removing $dir" >&2
rm -rf "$dir"
return 1
fi
git -C "$dir" remote set-head origin --auto >/dev/null 2>&1
Rollback is preferable to leaving the directory: a novice who retries init
otherwise hits git trees init: $dir already exists (git-trees:185) and has
to know to rm -rf first.
Test plan
Labels: bug
Priority: should-fix
Source: claude
Summary
git trees initchecks whether the bare clone succeeded but not whether any ofthe three steps that make the container usable succeeded. A half-configured
container still prints
initialized …and exits 0.Evidence
The clone is handled correctly, with rollback (
git-trees:188-191):The next three commands are unchecked (
git-trees:195-197):With no
set -e, execution continues past any failure to_seed_agentsandthen to
echo "initialized $dir (default branch: $def)".The fetch refspec step is exactly what makes remote-tracking refs work in a
bare clone (a bare clone does not set it up — the README calls this out). If
fetchfails, the container has noorigin/*refs, so the very next thing auser does breaks:
git trees add <branch>cannot resolveorigin/<default>,and
_default_branchsilently falls back to the literal stringmain(
git-trees:56), which may not exist.A plausible trigger: the clone succeeds against a reachable host, then the
network drops, or credentials work for read-only clone but the fetch is
interrupted. The user sees "initialized" and a broken container.
Proposed fix
Chain the post-clone steps and roll back on failure, matching the clone path.
set-head --autois genuinely optional (it fails harmlessly on a remote withno HEAD), so leave it unchecked:
Rollback is preferable to leaving the directory: a novice who retries
initotherwise hits
git trees init: $dir already exists(git-trees:185) and hasto know to
rm -rffirst.Test plan
file://still initializes and prints the default branch"initialized", directory removed
init, re-running the same command works (no stale dir)file://init (see the CI coverage issue —initiscurrently untested)