go-git是一个使用Go语言实现的高度可扩展的Git库(类似libgit2或jgit),可以很方便地将Git集成到Go语言编写的服务中。go-git的目标是与git完全兼容,目前它涵盖了大多数基本的读操作和一些主要的写操作,但缺少诸如合并之类的主要操作,go-git支持的命令详见兼容性文档。
JGit是Java语言实现的Git库。
Dulwich是Python语言实现的Git库。
代码示例
1,使用go-git将本地目录初始化为Git仓库:git init <directory>
$ vim main.go
package main
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/object"
)
// https://github.com/go-git/go-git/blob/master/_examples/sha256/main.go
func main() {
var (
directory string = "repository"
filename string = "example-git-file"
content string = "hello world!"
message string = "example go-git commit"
name string = "leitiannet"
email string = "347341200@qq.com"
)
// 删除仓库
os.RemoveAll(directory)
// 初始化仓库
Info("git init %s", directory)
r, err := git.PlainInit(directory, false)
CheckIfError(err)
// 新建文件
Info("echo -n \"%s\" > %s", content, filename)
err = os.WriteFile(filepath.Join(directory, filename), []byte(content), 0644)
CheckIfError(err)
// 将文件内容从工作目录添加到暂存区
Info("git add %s", filename)
w, err := r.Worktree()
CheckIfError(err)
_, err = w.Add(filename)
CheckIfError(err)
// 提交更新(将暂存区的内容在数据库中创建持久快照)
Info("git commit -m \"%s\"", message)
commit, err := w.Commit(message, &git.CommitOptions{
Author: &object.Signature{
Name: name,
Email: email,
When: time.Now(),
},
})
CheckIfError(err)
// 显示提交信息
Info("git show -s")
obj, err := r.CommitObject(commit)
CheckIfError(err)
fmt.Println(obj)
}
func CheckIfError(err error) {
if err == nil {
return
}
fmt.Printf("\x1b[31;1m%s\x1b[0m\n", fmt.Sprintf("error: %s", err))
os.Exit(1)
}
func Info(format string, args ...interface{}) {
fmt.Printf("\x1b[34;1m%s\x1b[0m\n", fmt.Sprintf(format, args...))
}
$ export GO111MODULE=on
$ export GOPROXY="https://goproxy.cn"
$ go mod init gogit
$ go mod edit -require github.com/go-git/go-git/v5@v5.6.0
$ go mod tidy
$ go run main.go
git init repository
echo -n "hello world!" > example-git-file
git add example-git-file
git commit -m "example go-git commit"
git show -s
commit 93974121806693d28738bdbc6a6025221ba01666
Author: leitiannet <347341200@qq.com>
Date: Mon Jun 03 21:25:54 2024 +0800
example go-git commit
2,使用go-git从其它服务器克隆Git仓库:git clone <repository> <directory>
$ vim main.go
package main
import (
"fmt"
"os"
"github.com/go-git/go-git/v5"
)
// https://github.com/go-git/go-git/blob/master/_examples/clone/main.go
func main() {
var (
url string = "https://github.com/leitiannet/template.git"
directory string = "repository"
)
// 删除仓库
os.RemoveAll(directory)
// 克隆仓库
Info("git clone %s %s", url, directory)
r, err := git.PlainClone(directory, false, &git.CloneOptions{
URL: url,
Progress: os.Stdout,
})
CheckIfError(err)
// 显示提交历史
Info("git log -1")
// 获取HEAD指向的分支
ref, err := r.Head()
CheckIfError(err)
commit, err := r.CommitObject(ref.Hash())
CheckIfError(err)
fmt.Println(commit)
}
func CheckIfError(err error) {
if err == nil {
return
}
fmt.Printf("\x1b[31;1m%s\x1b[0m\n", fmt.Sprintf("error: %s", err))
os.Exit(1)
}
func Info(format string, args ...interface{}) {
fmt.Printf("\x1b[34;1m%s\x1b[0m\n", fmt.Sprintf(format, args...))
}
$ export GO111MODULE=on
$ export GOPROXY="https://goproxy.cn"
$ go mod init gogit
$ go mod edit -require github.com/go-git/go-git/v5@v5.6.0
$ go mod tidy
$ go run main.go
git clone https://github.com/leitiannet/template.git repository
Enumerating objects: 21, done.
Counting objects: 100% (21/21), done.
Compressing objects: 100% (15/15), done.
Total 21 (delta 1), reused 21 (delta 1), pack-reused 0
git log -1
commit 192fceb15074c3ca7a208cbb21a39c3578589960
Author: leitiannet <347341200@qq.com>
Date: Sun May 19 07:54:35 2024 +0800
init Go project template
结构关系
- Repository:仓库,只要拥有一个Repository实例,就可以访问相应仓库信息并对其进行改变
- Worktree:工作树,即工作目录
- storage.Storer:存储系统
- billy.Filesystem:文件系统