【问题标题】:How do I mimic `git --work-tree ...` with `go-git` in go?如何在 go 中用 go-git 模仿 git --work-tree ...
【发布时间】:2021-12-25 15:11:17
【问题描述】:

我有一个裸存储库,我需要在其中添加和提交一组文件。据我了解,将文件添加到索引需要 worktree。在命令行上使用git,我会将git-dir 选项设置为指向裸目录,同时将work-tree 选项设置为指向要添加到索引的文件所在的工作树。像这样:

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

值得一提的是,“.git”目录不是,也不能简单地命名为“.git”。它实际上是一个“自定义”“.git”目录。喜欢git --git-dir /path/to/.notgit ...

我尝试设置 core.worktree 配置选项。但是,将core.bare 设置为true 会导致致命错误。都来自命令行:

$ 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

并使用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)

我的一个想法是依靠git.PlainOpenWithOptions 函数,希望我能够提供一个工作树作为选项。但是,看看 git.PlainOpenOptions 结构类型,这很快就崩溃了。

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
}

如何模仿git --work-tree ...go-git


编辑1:解释“.git”不完全命名为“.git”。

【问题讨论】:

  • 您可以使用带有参数的PlainOpenWithOptions构造函数,正如您在我的回答here中看到的那样

标签: git go go-git


【解决方案1】:

当您使用git.Open() 时,它基本上将存储库结构中的worktree 字段设置为nil,因为它在内部使用PlainOpenWithOptions,默认值为DetectDotGit 作为false。如果你使用下面的构造函数,你会看到,未跟踪的文件将被成功添加。

    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)

执行代码之前

go代码执行后

【讨论】:

  • 我完全忘记添加到问题中的问题是我的裸存储库不是,也不能简单地命名为“.git”。喜欢git --git-dir /path/to/.notgit ...。据我所见(查看git.PlainOpenWithOptions 的源代码)这不起作用,因为DetectDotGit 只查找确切名称为“.git”的父兄弟姐妹(文件或目录)。对不起,我会更新这个问题。 “.git”存储在一个名为GitDirName 的常量中,该常量已导出,但我看不到更改它的方法?
猜你喜欢
  • 1970-01-01
  • 2015-06-26
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 2012-04-02
  • 2013-02-11
  • 1970-01-01
  • 2023-02-09
相关资源
最近更新 更多