Commit b9e4814
cmd/init.go
@@ -1,24 +1,279 @@
package cmd
import (
+ "fmt"
+ "os"
+ "os/exec"
+ "time"
+
+ "github.com/go-git/go-billy/v5/osfs"
+ "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/config"
+ "github.com/go-git/go-git/v5/plumbing"
+ "github.com/go-git/go-git/v5/plumbing/object"
"github.com/spf13/cobra"
)
func NewInitCmd() *cobra.Command {
+ var setupWorktree bool
var cmd = &cobra.Command{
- Use: "tissue init",
- Short: "init tissues for the current repo",
- Long: `<long description>`,
- RunE: initRunE,
+ Use: "init",
+ Short: "Initialize tissue issue tracking in the current repo",
+ Long: `Initialize tissue issue tracking by creating an orphan 'issues' branch
+with proper structure and optionally setting up a git worktree for easy access.`,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ return initRunE(cmd, args, setupWorktree)
+ },
}
// flags
- // cmd.Flags()
+ cmd.Flags().BoolVar(&setupWorktree, "setup-worktree", false, "Create a git worktree for the issues branch")
return cmd
}
-func initRunE(cmd *cobra.Command, args []string) error {
+func initRunE(cmd *cobra.Command, args []string, setupWorktree bool) error {
+ // Step 1: Open and validate repository
+ fmt.Println("Initializing tissue issue tracking...")
+
+ repo, err := git.PlainOpen(".")
+ if err != nil {
+ return fmt.Errorf("failed to open repository: %w\nMake sure you're in a git repository", err)
+ }
+
+ // Store current branch to return to later
+ head, err := repo.Head()
+ if err != nil {
+ return fmt.Errorf("failed to get current branch: %w", err)
+ }
+ originalBranch := head.Name()
+
+ // Check if issues branch already exists
+ _, err = repo.Reference(plumbing.ReferenceName("refs/heads/issues"), false)
+ if err == nil {
+ return fmt.Errorf("issues branch already exists. Use 'tissue status' to check current setup")
+ }
+
+ // Step 2: Create orphan branch
+ fmt.Println("Creating orphan 'issues' branch...")
+ orphanRef := plumbing.NewSymbolicReference(
+ plumbing.HEAD,
+ plumbing.ReferenceName("refs/heads/issues"),
+ )
+ err = repo.Storer.SetReference(orphanRef)
+ if err != nil {
+ return fmt.Errorf("failed to create orphan branch: %w", err)
+ }
+
+ // Step 3: Get worktree and initialize files
+ worktree, err := repo.Worktree()
+ if err != nil {
+ return fmt.Errorf("failed to get worktree: %w", err)
+ }
+
+ // Clear the working directory for orphan branch
+ fs := osfs.New(".")
+
+ // Create README.md
+ readmePath := "README.md"
+ readmeContent := `# Issue Tracker
+
+This branch contains all issues for this repository.
+Each issue is a markdown file with YAML frontmatter.
+
+## Structure
+
+Issues are stored as markdown files with the following frontmatter:
+
+` + "```yaml" + `
+---
+id: 001
+title: Issue title
+status: open
+type: bug|feature|task
+created: 2025-09-24
+assignee: username
+---
+` + "```" + `
+
+## Usage
+
+Use the tissue CLI to manage issues:
+- ` + "`tissue new`" + ` - Create a new issue
+- ` + "`tissue list`" + ` - List all issues
+- ` + "`tissue view <id>`" + ` - View an issue
+- ` + "`tissue update <id>`" + ` - Update an issue
+`
+ readmeFile, err := fs.Create(readmePath)
+ if err != nil {
+ return fmt.Errorf("failed to create README.md: %w", err)
+ }
+ _, err = readmeFile.Write([]byte(readmeContent))
+ if err != nil {
+ readmeFile.Close()
+ return fmt.Errorf("failed to write README.md: %w", err)
+ }
+ readmeFile.Close()
+
+ // Create .gitignore
+ gitignorePath := ".gitignore"
+ gitignoreContent := `# Ignore everything except markdown files and directories
+/*
+!*.md
+!*/
+!.gitignore
+`
+ gitignoreFile, err := fs.Create(gitignorePath)
+ if err != nil {
+ return fmt.Errorf("failed to create .gitignore: %w", err)
+ }
+ _, err = gitignoreFile.Write([]byte(gitignoreContent))
+ if err != nil {
+ gitignoreFile.Close()
+ return fmt.Errorf("failed to write .gitignore: %w", err)
+ }
+ gitignoreFile.Close()
+
+ // Stage files
+ fmt.Println("Creating initial structure...")
+ _, err = worktree.Add(readmePath)
+ if err != nil {
+ return fmt.Errorf("failed to stage README.md: %w", err)
+ }
+ _, err = worktree.Add(gitignorePath)
+ if err != nil {
+ return fmt.Errorf("failed to stage .gitignore: %w", err)
+ }
+
+ // Commit
+ commit, err := worktree.Commit("Initialize issues branch for issue tracking", &git.CommitOptions{
+ Author: &object.Signature{
+ Name: "Tissue CLI",
+ Email: "tissue@example.com",
+ When: time.Now(),
+ },
+ })
+ if err != nil {
+ return fmt.Errorf("failed to commit initial structure: %w", err)
+ }
+ fmt.Printf("Created initial commit: %s\n", commit.String()[:7])
+
+ // Step 4: Push to remote if it exists
+ remotes, err := repo.Remotes()
+ if err == nil && len(remotes) > 0 {
+ fmt.Println("Pushing to remote...")
+ err = repo.Push(&git.PushOptions{
+ RemoteName: "origin",
+ RefSpecs: []config.RefSpec{
+ config.RefSpec("refs/heads/issues:refs/heads/issues"),
+ },
+ })
+ if err != nil && err != git.NoErrAlreadyUpToDate {
+ fmt.Printf("Warning: Could not push to remote: %v\n", err)
+ fmt.Println("You can push manually later with: git push -u origin issues")
+ } else if err == nil {
+ fmt.Println("Pushed issues branch to remote")
+ }
+ }
+
+ // Step 5: Return to original branch
+ err = worktree.Checkout(&git.CheckoutOptions{
+ Branch: originalBranch,
+ })
+ if err != nil {
+ return fmt.Errorf("failed to return to original branch: %w", err)
+ }
+ fmt.Printf("Returned to branch: %s\n", originalBranch.Short())
+
+ // Step 6: Setup worktree if requested
+ if setupWorktree {
+ fmt.Println("Setting up git worktree...")
+
+ // TODO: Remove dependency on git CLI when go-git supports worktrees
+ // Track progress: https://github.com/go-git/go-git/pull/396
+ cmd := exec.Command("git", "worktree", "add", "issues", "issues")
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ err := cmd.Run()
+ if err != nil {
+ return fmt.Errorf("failed to create worktree: %w\nYou can manually run: git worktree add issues issues", err)
+ }
+
+ // Add issues/ to .gitignore in main branch
+ gitignoreMainPath := ".gitignore"
+ var gitignoreContent []byte
+
+ // Check if .gitignore exists
+ if file, err := os.Open(gitignoreMainPath); err == nil {
+ defer file.Close()
+ info, _ := file.Stat()
+ gitignoreContent = make([]byte, info.Size())
+ file.Read(gitignoreContent)
+ }
+
+ // Append issues/ if not already present
+ gitignoreStr := string(gitignoreContent)
+ if !contains(gitignoreStr, "issues/") {
+ if len(gitignoreStr) > 0 && gitignoreStr[len(gitignoreStr)-1] != '\n' {
+ gitignoreStr += "\n"
+ }
+ gitignoreStr += "issues/\n"
+
+ err = os.WriteFile(gitignoreMainPath, []byte(gitignoreStr), 0644)
+ if err != nil {
+ return fmt.Errorf("failed to update .gitignore: %w", err)
+ }
+
+ // Stage and commit .gitignore update
+ _, err = worktree.Add(gitignoreMainPath)
+ if err != nil {
+ fmt.Printf("Warning: Could not stage .gitignore: %v\n", err)
+ } else {
+ _, err = worktree.Commit("Add issues worktree to gitignore", &git.CommitOptions{
+ Author: &object.Signature{
+ Name: "Tissue CLI",
+ Email: "tissue@example.com",
+ When: time.Now(),
+ },
+ })
+ if err != nil {
+ fmt.Printf("Warning: Could not commit .gitignore update: %v\n", err)
+ }
+ }
+ }
+
+ fmt.Println("Git worktree created at ./issues")
+ }
+
+ fmt.Println("\n✓ Tissue initialized successfully!")
+ fmt.Println("\nNext steps:")
+ if !setupWorktree {
+ fmt.Println(" - Run 'tissue init --setup-worktree' to create a worktree")
+ fmt.Println(" - Or manually: git worktree add issues issues")
+ }
+ fmt.Println(" - Create your first issue: tissue new")
+ fmt.Println(" - List issues: tissue list")
+ fmt.Println(" - Check status: tissue status")
+
return nil
}
+
+func contains(s, substr string) bool {
+ return len(s) > 0 && len(substr) > 0 &&
+ (s == substr ||
+ len(s) > len(substr) &&
+ (s[:len(substr)] == substr ||
+ s[len(s)-len(substr):] == substr ||
+ len(s) > len(substr)+1 &&
+ containsInMiddle(s, substr)))
+}
+
+func containsInMiddle(s, substr string) bool {
+ for i := 1; i < len(s)-len(substr); i++ {
+ if s[i:i+len(substr)] == substr {
+ return true
+ }
+ }
+ return false
+}
docs/cmd/init.md
@@ -5,7 +5,6 @@ Initialize tissue issue tracking in a git repository.
## Tissue Command
```bash
tissue init
-tissue init --setup-worktree
```
## Manual Workflow (bash + git)
.gitignore
@@ -1,1 +1,2 @@
docs/book
+tissue
go.mod
@@ -3,7 +3,27 @@ module tissue
go 1.24.2
require (
+ dario.cat/mergo v1.0.0 // indirect
+ github.com/Microsoft/go-winio v0.6.2 // indirect
+ github.com/ProtonMail/go-crypto v1.1.6 // indirect
+ github.com/cloudflare/circl v1.6.1 // indirect
+ github.com/cyphar/filepath-securejoin v0.4.1 // indirect
+ github.com/emirpasic/gods v1.18.1 // indirect
+ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
+ github.com/go-git/go-billy/v5 v5.6.2 // indirect
+ github.com/go-git/go-git/v5 v5.16.2 // indirect
+ github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
+ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
+ github.com/kevinburke/ssh_config v1.2.0 // indirect
+ github.com/pjbgf/sha1cd v0.3.2 // indirect
+ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
+ github.com/skeema/knownhosts v1.3.1 // indirect
github.com/spf13/cobra v1.10.1 // indirect
github.com/spf13/pflag v1.0.9 // indirect
+ github.com/xanzy/ssh-agent v0.3.3 // indirect
+ golang.org/x/crypto v0.37.0 // indirect
+ golang.org/x/net v0.39.0 // indirect
+ golang.org/x/sys v0.32.0 // indirect
+ gopkg.in/warnings.v0 v0.1.2 // indirect
)
go.sum
@@ -1,10 +1,76 @@
+dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
+dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
+github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
+github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNxpLfdw=
+github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
+github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
+github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
+github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
+github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
+github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
+github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
+github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
+github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
+github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM=
+github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
+github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
+github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
+github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
+github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
+github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
+github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
+golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
+golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
+golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
README.md
@@ -46,7 +46,8 @@ mdbook serve docs
tissue init
# Clone a repository and set up tissue branch
-tissue clone https://github.com/user/repo.git
+git clone https://github.com/user/repo.git
+cd repo
tissue init --setup-worktree
```