英文:
How to push specific branch to remote with go-git
问题
什么是使用go-git
将特定的本地分支推送到特定远程仓库的规范方法?
我有一个已经用go-git
检出和打开的本地仓库:
repo, err := git.PlainOpen("my-repo")
该仓库有一个默认的origin
远程仓库。
我正在尝试将该仓库的内容同步到另一个名为mirror
的远程仓库,所以我添加了这个远程仓库:
repo.CreateRemote(&config.RemoteConfig{
Name: "mirror",
URLs: []string{"git@github.com:foo/mirror.git"},
})
首先,我从origin
远程仓库获取仓库内容:
err = remote.Fetch(&git.FetchOptions{
RemoteName: "origin",
Tags: git.AllTags,
})
...然后使用remote.List()
来获取所有感兴趣的分支和标签。
最后一步是将这些分支推送到mirror
远程仓库,并根据映射重写分支名称。例如,将检出的refs/remotes/origin/master
分支作为refs/heads/master
推送到mirror
远程仓库的main
分支。因此,我遍历这些分支,并尝试逐个推送它们:
refSpec := config.RefSpec(fmt.Sprintf(
"+%s:refs/remotes/mirror/%s",
localBranch.Name().String(),
// 映射分支名称,例如 master -> main
mapBranch(remoteBranch.Name().Short()),
))
err = repo.Push(&git.PushOptions{
RemoteName: "mirror",
Force: true,
RefSpecs: []config.RefSpec{refSpec},
Atomic: true,
})
但是这会导致git.NoErrAlreadyUpToDate
错误,并且在mirror
远程仓库上没有任何操作发生。
英文:
What is the canonical way to push specific single local branch to specific remote with go-git
?
I have a local repository checked out and opened with go-git
repo, err := git.PlainOpen("my-repo")
The repo has default origin
remote.
I'm trying to sync contents of this repository to another remote mirror
, so I'm adding the remote
repo.CreateRemote(&config.RemoteConfig{
Name: "mirror",
URLs: []string{"git@github.com:foo/mirror.git"},
})
First I fetch repo contents from origin
err = remote.Fetch(&git.FetchOptions{
RemoteName: "origin",
Tags: git.AllTags,
})
... and do a discovery of all branches and tags of interest with remote.List()
Final step is pushing the branches to mirror
, while rewriting branch names based on a map. E.g. refs/remotes/origin/master
checked out as refs/heads/master
should be pushed to mirror
remote as main
. Therefore I'm iterating over the branches and trying to push them one by one:
refSpec := config.RefSpec(fmt.Sprintf(
"+%s:refs/remotes/mirror/%s",
localBranch.Name().String(),
// map branch names, e.g. master -> main
mapBranch(remoteBranch.Name().Short()),
))
err = repo.Push(&git.PushOptions{
RemoteName: "mirror",
Force: true,
RefSpecs: []config.RefSpec{refSpec},
Atomic: true,
})
But this results in git.NoErrAlreadyUpToDate
and there's nothing happening on the mirror
remote.
答案1
得分: 2
refSpec
在将单个分支推送到远程时,不应该采用+refs/heads/localBranchName:refs/remotes/remoteName/remoteBranchName
的格式,如这里所示:
// RefSpec是从本地分支到远程引用的映射。
...
// 例如:"+refs/heads/*:refs/remotes/origin/*"
//
// https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
type RefSpec string
而应该采用以下格式:
"+refs/heads/localBranchName:refs/heads/remoteBranchName"
请参考示例:
refSpecStr := fmt.Sprintf(
"+%s:refs/heads/%s",
localBranch.Name().String(),
mapBranch(remoteBranch.Name().Short()),
)
refSpec := config.RefSpec(refSpecStr)
log.Infof("Pushing %s", refSpec)
err = repo.Push(&git.PushOptions{
RemoteName: "mirror",
Force: true,
RefSpecs: []config.RefSpec{refSpec},
Atomic: true,
})
英文:
The refSpec
, when pushing single branch to a remote, should NOT be in format +refs/heads/localBranchName:refs/remotes/remoteName/remoteBranchName
as indicate e.g. here:
// RefSpec is a mapping from local branches to remote references.
...
// eg.: "+refs/heads/*:refs/remotes/origin/*"
//
// https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
type RefSpec string
but as
"+refs/heads/localBranchName:refs/heads/remoteBranchName"
instead. See example:
refSpecStr := fmt.Sprintf(
"+%s:refs/heads/%s",
localBranch.Name().String(),
mapBranch(remoteBranch.Name().Short()),
)
refSpec := config.RefSpec(refSpecStr)
log.Infof("Pushing %s", refSpec)
err = repo.Push(&git.PushOptions{
RemoteName: "mirror",
Force: true,
RefSpecs: []config.RefSpec{refSpec},
Atomic: true,
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论