Git 的正确使用姿势与最佳实践 | 豆包MarsCode AI刷题

97 阅读2分钟

1. go-git 介绍

一个用 Go 语言编写的 git 实现库:它的官方仓库地址:go-git

为什么我们需要它? 举个例子:

如果我们需要获取 git log 的信息,需要通过 Go 调用 cmd 命令来获取:获取 git 的 last commit hash 的话需要耗费的时间大概在 50ms 左右(不同运行环境可能不一样)

它的慢原因是什么呢 ? Go 调用 cmd 命令本身存在着性能原因 其次,如果想要获取其它仓库的 git log 信息,还存在着跨文件调用的消耗

所以这里 go-git 的作用就体现出来了!由于它是 go 编写的 git 实现库,所以对 cmd 命令调用的消耗就可以避免了。测试之后,使用时间在 500μs 左右,巨大的提升!

2. go-git 使用

1)go-git 的安装:

go get -u github.com/go-git/go-git/v5

2.2)拉取仓库:

通过 github 地址

r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
URL: "仓库地址",
})

通过本地仓库

	r, err := git.PlainOpen("本地仓库路径")

3)获取 last commit hash:

rHead, _ := r.Head()
 // 将获得的 
 rHeadStr := rHead.String()
 rHeadIdx := strings.Index(rHeadStr, " ")
 lastCommitHash = rHeadStr[:rHeadIdx]

所以可以使用 String() 将获得的信息转为字符串,结尾有空格需要去掉。

4)对 commit 历史信息进行遍历

cIter, _ := r.Log(&git.LogOptions{From: ref.Hash()})
err = cIter.ForEach(func(c *object.Commit) error {
return nil
})

可以通过:Order 指定遍历的方式,Since 和 Until 指定遍历时间范围。

cIter 是一个 object.Commiter 结构体,拥有以下方法,可以根据需要进行使用。

// CommitIter is a generic closable interface for iterating over commits.
type CommitIter interface {
 Next() (*Commit, error)
 ForEach(func(*Commit) error) error
 Close()
}


怎么根据只有一个 Hash 值获取 commit 呢 ?

thisHash := plumbing.NewHash(string("Hash 值"))
thisCommit, _ := object.GetCommit(r.Storer, thisHash)

	

根据 commit 结构体又可以获得别的信息:

type Commit struct {
// Hash of the commit object.
Hash plumbing.Hash
// Author is the original author of the commit.
Author Signature
// Committer is the one performing the commit, might be different from
// Author.
Committer Signature
// PGPSignature is the PGP signature of the commit.
PGPSignature string
// Message is the commit message, contains arbitrary text.
Message string
// TreeHash is the hash of the root tree of the commit.
TreeHash plumbing.Hash
// ParentHashes are the hashes of the parent commits of the commit.
ParentHashes []plumbing.Hash
s storer.EncodedObjectStorer
}
type Signature struct {
  // Name represents a person name. It is an arbitrary string.
  Name string
  // Email is an email, but it cannot be assumed to be well-formed.
    Email string
  // When is the timestamp of the signature.
  When time.Time
}

例如:获取 commit 的时间

thisCommit.Committer.When.String()

在Go项目中,使用Git可以更好地管理项目的依赖关系。当使用Go模块(go mod)时,Git仓库可以作为依赖的源。例如,很多开源的Go库都托管在GitHub(基于Git的代码托管平台)上。开发人员可以通过在go. mod和go. sum文件中指定依赖的Git仓库地址和版本标签,精确地控制项目所依赖的外部代码。这有助于确保项目在不同环境下构建的一致性,避免因为依赖版本的混乱而导致的编译失败或运行时错误。