Skip to content

Commit 317178d

Browse files
committed
feat: allow auto checkout worktree creation if branch is on remote
1 parent de93d42 commit 317178d

3 files changed

Lines changed: 43 additions & 2 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ erl_crash.dump
99
*.beam
1010
/config/*.secret.exs
1111
.elixir_ls/
12+
dist/

lib/git_work/commands/checkout.ex

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ defmodule GitWork.Commands.Checkout do
1414
Switch to a branch by navigating to its worktree directory.
1515
1616
Without -b, matches an existing worktree (exact or fuzzy) and prints its
17-
path. Returns an error if no matching worktree is found.
17+
path. If no worktree matches but a remote branch with that exact name
18+
exists, a new worktree is automatically created tracking the remote branch.
19+
Returns an error only if neither a worktree nor a remote branch is found.
1820
1921
With -b, creates a new worktree for the given branch (tracking the remote
2022
branch if one exists, or creating a new local branch otherwise). Returns
@@ -30,6 +32,7 @@ defmodule GitWork.Commands.Checkout do
3032
Examples:
3133
git-work checkout feature-login # switch to existing worktree
3234
git-work checkout login # fuzzy match existing worktree
35+
git-work checkout feature/remote # auto-create from remote branch
3336
git-work checkout -b feature/new # create new worktree
3437
"""
3538
end
@@ -68,7 +71,20 @@ defmodule GitWork.Commands.Checkout do
6871
{:error, "ambiguous match for '#{input}':\n#{formatted}"}
6972

7073
:no_match ->
71-
{:error, "no worktree found for '#{input}' (use -b to create one)"}
74+
# No existing worktree — check if a remote branch matches
75+
bare_dir = Project.bare_path(root)
76+
77+
case Git.cmd(["branch", "-r", "--list", "origin/#{input}"], cd: bare_dir) do
78+
{:ok, ""} ->
79+
{:error, "no worktree found for '#{input}' (use -b to create one)"}
80+
81+
{:ok, _} ->
82+
IO.write(:stderr, "creating worktree from remote branch: '#{input}'\n")
83+
create_worktree(root, input, sanitized)
84+
85+
{:error, _} ->
86+
{:error, "no worktree found for '#{input}' (use -b to create one)"}
87+
end
7288
end
7389
end
7490

test/git_work/commands/checkout_test.exs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,28 @@ defmodule GitWork.Commands.CheckoutTest do
108108
assert File.dir?(path)
109109
assert File.regular?(Path.join(path, "feature-remote.txt"))
110110
end
111+
112+
test "checkout without -b auto-creates worktree from remote branch", %{tmp: tmp} do
113+
origin = GitWork.TestHelper.create_origin_repo(tmp)
114+
project = Path.join(tmp, "project")
115+
{:ok, _} = GitWork.Commands.Clone.run([origin, project])
116+
117+
# Create a branch on the remote
118+
GitWork.TestHelper.create_remote_branch(origin, "feature-remote")
119+
120+
# Fetch so the project knows about it
121+
System.cmd("git", ["fetch", "--all"], cd: Path.join(project, ".bare"))
122+
123+
File.cd!(Path.join(project, "main"))
124+
125+
# Checkout without -b should auto-create from remote
126+
assert {:ok, path} = Checkout.run(["feature-remote"])
127+
assert File.dir?(path)
128+
assert path == Path.join(project, "feature-remote")
129+
assert File.regular?(Path.join(path, "feature-remote.txt"))
130+
131+
# Verify git knows about the worktree
132+
{output, 0} = System.cmd("git", ["worktree", "list"], cd: Path.join(project, ".bare"))
133+
assert output =~ "feature-remote"
134+
end
111135
end

0 commit comments

Comments
 (0)