Skip to content

Commit 0fa0af1

Browse files
authored
Refactor worktree path conversion to ensure relative paths for .git and back-references (#394)
Signed-off-by: Johannes Ott <mail@johannes-ott.net>
1 parent 158c116 commit 0fa0af1

2 files changed

Lines changed: 112 additions & 34 deletions

File tree

Lines changed: 73 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,83 @@
11
#!/bin/bash
22

33
# Fix git worktree paths for devcontainer usage
4-
# This script converts absolute paths in .git to relative paths
5-
6-
if [ -f .git ] && [ ! -d .git ]; then
7-
# This is a worktree, .git is a file
8-
echo "🔧 Detected git worktree, fixing git directory reference..."
9-
10-
# Read the current gitdir
11-
GITDIR=$(cat .git | sed 's/gitdir: //')
12-
13-
# Check if it's an absolute path
14-
if [[ "$GITDIR" == /* ]]; then
15-
echo "📝 Found absolute path, converting to relative..."
16-
17-
# Extract worktree name from gitdir
18-
WORKTREE_NAME=$(basename "$GITDIR")
19-
20-
# Create relative path pointing to .repo
21-
RELATIVE_PATH="../.repo/worktrees/$WORKTREE_NAME"
22-
23-
# Update .git file
24-
echo "gitdir: $RELATIVE_PATH" > .git
25-
26-
echo "✅ Updated .git to use relative path: $RELATIVE_PATH"
4+
# Converts absolute paths to relative paths in both directions:
5+
# 1. Worktree/.git → ../.repo/worktrees/<name>
6+
# 2. .repo/worktrees/<name>/gitdir → ../../../<name>/.git
7+
8+
set -e
9+
10+
if [ ! -f .git ] || [ -d .git ]; then
11+
echo "ℹ️ Regular git repository (not a worktree), nothing to fix."
12+
exit 0
13+
fi
14+
15+
echo "🔧 Detected git worktree, fixing git directory references..."
16+
17+
# ── 1. Read current gitdir ────────────────────────────────────────────────────
18+
19+
GITDIR=$(sed 's/gitdir: //' .git)
20+
WORKTREE_NAME=$(basename "$(pwd)")
21+
22+
echo " Worktree name : $WORKTREE_NAME"
23+
echo " Current gitdir: $GITDIR"
24+
25+
# ── 2. Fix .git file (Worktree → Bare Repo) ──────────────────────────────────
26+
27+
EXPECTED_GITDIR="../.repo/worktrees/$WORKTREE_NAME"
28+
29+
if [ "$GITDIR" != "$EXPECTED_GITDIR" ]; then
30+
echo "📝 Fixing .git (absolute → relative)..."
31+
echo "gitdir: $EXPECTED_GITDIR" > .git
32+
echo "✅ .git updated: $EXPECTED_GITDIR"
33+
else
34+
echo "✅ .git already correct."
35+
fi
36+
37+
# ── 3. Fix gitdir back-reference (Bare Repo → Worktree) ──────────────────────
38+
#
39+
# Relative path is calculated from:
40+
# .repo/worktrees/<name>/gitdir
41+
# to:
42+
# <name>/.git
43+
#
44+
# Both on host and in devcontainer the directory structure is:
45+
# <root>/
46+
# .repo/worktrees/<name>/gitdir (3 levels deep)
47+
# <name>/.git
48+
#
49+
# So the relative path is always: ../../../<name>/.git
50+
51+
BACK_REF_FILE="../.repo/worktrees/$WORKTREE_NAME/gitdir"
52+
EXPECTED_BACK_REF="../../../$WORKTREE_NAME/.git"
53+
54+
if [ ! -f "$BACK_REF_FILE" ]; then
55+
echo "⚠️ Back-reference file not found: $BACK_REF_FILE"
56+
echo " Make sure the .repo mount is available."
57+
else
58+
CURRENT_BACK_REF=$(cat "$BACK_REF_FILE")
59+
echo " Current back-ref: $CURRENT_BACK_REF"
60+
61+
if [ "$CURRENT_BACK_REF" != "$EXPECTED_BACK_REF" ]; then
62+
echo "📝 Fixing back-reference (absolute → relative)..."
63+
echo "$EXPECTED_BACK_REF" > "$BACK_REF_FILE"
64+
echo "✅ Back-reference updated: $BACK_REF_FILE$EXPECTED_BACK_REF"
2765
else
28-
echo "Path is already relative, nothing to fix."
66+
echo "Back-reference already correct."
2967
fi
30-
else
31-
echo "ℹ️ Regular git repository (not a worktree), nothing to fix."
3268
fi
3369

34-
# Verify git is working
70+
# ── 4. Verify ─────────────────────────────────────────────────────────────────
71+
72+
echo ""
73+
echo "🔍 Verifying git..."
74+
3575
if git status > /dev/null 2>&1; then
3676
echo "✅ Git is working correctly!"
77+
git worktree list
3778
else
38-
echo "❌ Warning: Git commands may not work properly. Please check your worktree setup."
39-
fi
79+
echo "❌ Git commands not working. Current state:"
80+
echo " .git contents : $(cat .git)"
81+
echo " back-ref : $(cat "$BACK_REF_FILE" 2>/dev/null || echo 'not readable')"
82+
exit 1
83+
fi

scripts/manage-worktrees.sh

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,47 @@ skipping upstream configuration"
191191

192192
convert_git_to_relative() {
193193
local WORKTREE_PATH=$1
194+
local WORKTREE_NAME
195+
WORKTREE_NAME=$(basename "$WORKTREE_PATH")
194196
local GIT_FILE="$WORKTREE_PATH/.git"
195-
197+
196198
[ ! -f "$GIT_FILE" ] && return 0
197-
198-
info "Converting .git to relative path..."
199-
echo "gitdir: ../.repo/worktrees/$(basename "$WORKTREE_PATH")" > "$GIT_FILE"
200-
success "Converted .git to relative path"
199+
200+
# ── 1. Fix Worktree → Bare Repo (.git file) ──────────────────────────────
201+
local EXPECTED_GITDIR="../.repo/worktrees/$WORKTREE_NAME"
202+
local CURRENT_GITDIR
203+
CURRENT_GITDIR=$(sed 's/gitdir: //' "$GIT_FILE")
204+
205+
if [ "$CURRENT_GITDIR" != "$EXPECTED_GITDIR" ]; then
206+
info "Converting .git to relative path..."
207+
echo "gitdir: $EXPECTED_GITDIR" > "$GIT_FILE"
208+
success "Converted .git → $EXPECTED_GITDIR"
209+
else
210+
info ".git already uses relative path"
211+
fi
212+
213+
# ── 2. Fix Bare Repo → Worktree (gitdir back-reference) ──────────────────
214+
# Relative path from .repo/worktrees/<name>/gitdir to <name>/.git
215+
# Both on host and in devcontainer the structure is flat:
216+
# <root>/.repo/worktrees/<name>/gitdir → ../../../<name>/.git
217+
local BACK_REF_FILE="$REPO_DIR/worktrees/$WORKTREE_NAME/gitdir"
218+
local EXPECTED_BACK_REF="../../../$WORKTREE_NAME/.git"
219+
220+
if [ ! -f "$BACK_REF_FILE" ]; then
221+
warning "Back-reference not found: $BACK_REF_FILE"
222+
return 0
223+
fi
224+
225+
local CURRENT_BACK_REF
226+
CURRENT_BACK_REF=$(cat "$BACK_REF_FILE")
227+
228+
if [ "$CURRENT_BACK_REF" != "$EXPECTED_BACK_REF" ]; then
229+
info "Converting back-reference to relative path..."
230+
echo "$EXPECTED_BACK_REF" > "$BACK_REF_FILE"
231+
success "Converted back-reference → $EXPECTED_BACK_REF"
232+
else
233+
info "Back-reference already uses relative path"
234+
fi
201235
}
202236

203237
sanitize_branch_name() {

0 commit comments

Comments
 (0)