Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I mimic `git --work-tree ...` with `go-git` in go?

Tags:

git

go

go-git

I have a bare repository in which I need to add and commit a set of files. As far as I understand it, adding files to the index requires a worktree. Using git on the command line, I would set the git-dir option to point to the bare directory along with setting the work-tree option to point to a worktree in which the files to be added to the index live. Like so:

$ git --git-dir /path/to/.git --work-tree /path/to/worktree add ...

It's worth mentioning that the ".git" directory is not, and can not, be named simply ".git". It is in fact a "custom" ".git" dir. Like git --git-dir /path/to/.notgit ....

I tried setting the core.worktree config option. However, with core.bare set to true this results in a fatal error. Both from the command line:

$ git --git-dir /path/to/.notgit config core.worktree /path/to/worktree
$ git --git-dir /path/to/.notgit add ...
warning: core.bare and core.worktree do not make sense
fatal: unable to set up work tree using invalid config

and using go-git:

r, err := git.PlainOpen("/path/to/.notgit")
panicOnError(err)

c, err := r.Config()
panicOnError(err)

fmt.Println(c.Core.IsBare) // true

c.Core.Worktree = "/path/to/worktree"

err = r.SetConfig(c)
panicOnError(err)

_, err = r.Worktree() // panic: worktree not available in a bare repository
panicOnError(err)

One thought I had was to lean on the git.PlainOpenWithOptions function to hopefully allow me to provide a worktree as an option. However, looking at the git.PlainOpenOptions struct type, this fell apart quickly.

type PlainOpenOptions struct {
    // DetectDotGit defines whether parent directories should be
    // walked until a .git directory or file is found.
    DetectDotGit bool
    // Enable .git/commondir support (see https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt).
    // NOTE: This option will only work with the filesystem storage.
    EnableDotGitCommonDir bool
}

How do I mimic git --work-tree ... with go-git?


Edit 1: Explained that ".git" is not exactly named ".git".

like image 573
Emil Walser Avatar asked Nov 13 '21 18:11

Emil Walser


People also ask

Is git written in Go?

Go-git is an open-source implementation of Git written in pure Go. It is currently used for backing projects as a SQL interface for Git code repositories and providing encryption for Git.

What is the worktree in git?

A Git worktree is a linked copy of your Git repository, allowing you to have multiple branches checked out at a time. A worktree has a separate path from your main working copy, but it can be in a different state and on a different branch.

How to update a git worktree?

You can now always view the code in your repository at the main branch. To update the worktree, run the git pull command. This will get all the latest commits to the branch and update your worktree.

What is the git go?

Git-go is a variation of the word get-go, which means at the start or beginning. It is usually found in the phrase from the get-go.


1 Answers

When you use git.Open(), it basically sets worktree field in repository struct as nil, since it uses PlainOpenWithOptions internally with the default value of DetectDotGit as false. If you use the following constructor, you will see, the untracked files will be added successfully.

    r, err := git.PlainOpenWithOptions("/path/to/.git",&git.PlainOpenOptions{DetectDotGit: true})
    panicOnError(err)
    
    c, err := r.Config()
    panicOnError(err)
    
    fmt.Println(c.Core.IsBare) // true
    
    c.Core.Worktree = "/path/to/worktree"
    
    err = r.SetConfig(c)
    panicOnError(err)
    
    _, err = r.Worktree() // panic: worktree not available in a bare repository
    panicOnError(err)

// added this part for test
    workTree, werr := r.Worktree()
    panicOnError(werr)

    hash, hashErr := workTree.Add("a.txt")
    if hashErr != nil {
        log.Fatal(hashErr)
    }
fmt.Println(hash)

Before go code execution enter image description here

After go code execution enter image description here

like image 77
Hüseyin BABAL Avatar answered Oct 23 '22 20:10

Hüseyin BABAL