Skip to content

Commit 48badd3

Browse files
authored
Merge pull request #5 from go-git/worktree-docs
tutorials: Add worktree management guide
2 parents eb7cf5f + 4d6d65c commit 48badd3

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ nav:
2121
- Getting Started: tutorials/getting-started.md
2222
- Advanced Usage: tutorials/advanced-usage.md
2323
- Troubleshooting: tutorials/troubleshooting.md
24+
- Worktrees: tutorials/worktrees.md
2425
- Migrating to V6: tutorials/migrating-from-v5-to-v6.md
2526
- Concepts:
2627
- Overview: concepts/overview.md

src/tutorials/worktrees.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
layout: default
3+
title: Working with Linked Worktrees
4+
---
5+
# Working with Linked Worktrees
6+
7+
Git worktrees allow you to check out multiple branches simultaneously, each
8+
in its own working directory. go-git supports creating and opening linked
9+
worktrees through the experimental `x/plumbing/worktree` package.
10+
11+
## Overview
12+
13+
A Git repository has one **main worktree** (created by `git init` or
14+
`git clone`) and zero or more **linked worktrees**. Each linked worktree
15+
has its own checked-out branch and working directory, while sharing the
16+
same object database and refs with the main repository.
17+
18+
Common use cases:
19+
20+
- Running tests on one branch while developing on another
21+
- Comparing behavior across branches side by side
22+
- Building a release while continuing feature work
23+
24+
## Creating a Linked Worktree
25+
26+
To create a linked worktree, you need:
27+
28+
1. A `storage.Storer` that implements `WorktreeStorer` (e.g. `filesystem.Storage`)
29+
2. A `billy.Filesystem` for the new worktree's working directory
30+
3. The commit hash to check out
31+
32+
```go
33+
package main
34+
35+
import (
36+
"fmt"
37+
"os"
38+
"path/filepath"
39+
40+
"github.com/go-git/go-billy/v6/osfs"
41+
"github.com/go-git/go-git/v6"
42+
"github.com/go-git/go-git/v6/plumbing"
43+
"github.com/go-git/go-git/v6/storage/filesystem"
44+
45+
xworktree "github.com/go-git/go-git/v6/x/plumbing/worktree"
46+
)
47+
48+
func main() {
49+
repoPath := "/path/to/repo"
50+
worktreePath := "/path/to/new-worktree"
51+
commitHash := "abc123..."
52+
53+
// Open the repository's .git storage
54+
dotgitFs := osfs.New(filepath.Join(repoPath, ".git"), osfs.WithChrootOS())
55+
store := filesystem.NewStorageWithOptions(dotgitFs, nil, filesystem.Options{})
56+
57+
// Create a worktree manager
58+
wt, err := xworktree.New(store)
59+
if err != nil {
60+
fmt.Fprintf(os.Stderr, "error: %v\n", err)
61+
os.Exit(1)
62+
}
63+
64+
// Create the linked worktree filesystem
65+
worktreeFs := osfs.New(worktreePath)
66+
name := filepath.Base(worktreePath)
67+
68+
// Add the worktree at the given commit
69+
err = wt.Add(worktreeFs, name,
70+
xworktree.WithCommit(plumbing.NewHash(commitHash)))
71+
if err != nil {
72+
fmt.Fprintf(os.Stderr, "error: %v\n", err)
73+
os.Exit(1)
74+
}
75+
76+
fmt.Printf("Worktree %q created at %s\n", name, worktreePath)
77+
}
78+
```
79+
80+
## Opening an Existing Linked Worktree
81+
82+
Once a linked worktree exists on disk, open it like any other repository
83+
using `git.Open` with the shared storage and the worktree filesystem:
84+
85+
```go
86+
r, err := git.Open(store, worktreeFs)
87+
if err != nil {
88+
log.Fatal(err)
89+
}
90+
91+
ref, err := r.Head()
92+
if err != nil {
93+
log.Fatal(err)
94+
}
95+
96+
commit, err := r.CommitObject(ref.Hash())
97+
if err != nil {
98+
log.Fatal(err)
99+
}
100+
101+
fmt.Println(commit)
102+
```
103+
104+
## Worktree Configuration Extension
105+
106+
When `extensions.worktreeConfig` is enabled in the repository config,
107+
each linked worktree can have its own `config.worktree` file at
108+
`.git/worktrees/<name>/config.worktree`. go-git's filesystem storage
109+
reads these files and overlays them on the shared repository config,
110+
matching the behavior of upstream Git.
111+
112+
This is useful for per-worktree settings such as `core.sparseCheckout`
113+
or custom configuration that should differ between worktrees.
114+
115+
Reference: [git-worktree configuration file](https://git-scm.com/docs/git-worktree#_configuration_file)
116+
117+
## Worktree Naming
118+
119+
Worktree names must match the pattern `[a-zA-Z0-9\-]+`. Typically the
120+
name is derived from the base directory name of the worktree path (e.g.
121+
`/tmp/hotfix` produces the name `hotfix`).
122+
123+
## Limitations
124+
125+
- Only `add` is fully supported for creating worktrees. Not all flags
126+
or subcommands from `git worktree` are implemented.
127+
- The worktree package lives in `x/plumbing/worktree`, meaning its API
128+
is **experimental** and may change without notice.
129+
- The storer must implement `WorktreeStorer` — currently only
130+
`storage/filesystem` satisfies this.
131+
- Worktree lock, move, and prune operations are not yet supported.
132+
133+
See the [full example](_examples/worktrees/main.go) in the go-git repository.

0 commit comments

Comments
 (0)