在 Git 裸仓库中执行 "fetch --all" 命令无法将本地分支与远程分支同步。

10

我正在尝试定期同步一个git裸库,我的本地分支使用“--track”选项创建。这是我的配置(不包括不必要的内容):

[core]
        bare = true
[remote "origin"]
        url = git@github.com:Ummon/D-LAN.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
[branch "website"]
        remote = origin
        merge = refs/heads/website

我必须使用“cp”命令来更新本地分支:

 git fetch --all
 cp -r refs/remotes/origin/* refs/heads

有没有更优雅的解决方案?

1个回答

19

不要复制引用文件(非常糟糕!),而是使用 git update-ref

请注意,当推送而不是拉取到裸仓库时,您可以很容易地获得所需的内容。

使用以下命令:

 git clone --mirror . /tmp/bareclone

要创建完全与同步的裸仓库,可以使用以下命令:

现在,要将所有分支与裸克隆镜像同步,请使用以下命令:

 git push /tmp/bareclone --mirror

请注意,这也会删除源代码库中不存在但仍在裸克隆中的任何头。还要注意,您可以使用send-pack而不是push,因为此接口相当低级且实际上由send-pack实现。
希望对你有所帮助。
正如评论者所指出的,我稍微避开了这个主题,即似乎不可能一次性做到相反的事情。然而,您可以通过执行类似以下的略微高级的操作来实现目标:
1. 简单、安全且相当无聊。
git fetch $url -- $(git ls-remote -h $url |
    while read sha ref; do echo "$ref:refs/remotes/fetched/${ref#refs/heads/}"; done)

设置`url=git://your.server/project.git',例如:

我确保引用被创建在相对安全的位置。效果与执行以下命令非常相似:

git remote add fetched $url --fetch

这段内容没有太多实质性的东西,但是它展示了如何使用管道命令来实现它,因此我们现在可以根据我们的需求进行调整:

2. 直接提取到本地分支(头部)

现在,如果你确定自己知道在做什么,则可以使用以下样式将分支本地复制:

git init --bare .
git fetch $url -- $(git ls-remote -h $url |
    while read sha ref; do echo "$ref:$ref"; done)

注意:如果你想要强制更新(例如在没有快进拉取的情况下,由于上游的rebase、reset、filter-branch或修订提交(通常是任何重写历史),请将echo "$ref:$ref"替换为echo "+$ref:$ref");(感谢Dov;

3. 完整操作

这也可以结合起来,这样你就可以有一个远程定义。 我建议这样做,因为这意味着本地分支实际上正在跟踪远程分支,如果你不小心用这些强大的fetch命令覆盖了这些分支上的一些本地提交,你将拥有更好的隔离/恢复选项。

git init --bare .
git remote add fetched $url --fetch
git for-each-ref --format='%(refname:short)' -- 'refs/remotes/fetched/' |
    while read ref; do git branch -t "$(basename "$ref")" "$ref"; done

玩得开心,祝你好运


1
谢谢,我对每个分支都这样做:git update-ref refs/heads/master refs/remotes/origin/master - gburri
非常感谢您!我一直在寻找更新克隆的方法。关于您上面的第二个示例,我有一个评论,我添加了一个+到引用中,以便它读作“do echo“+$ref:$ref””。 - Dov Grobgeld
只是想指出,最后的解决方案应该是 git for-each-ref。 (我试图自己编辑它,但“编辑必须至少为6个字符”,而我只添加了4个:p)。 这对我非常有用。 非常感谢。 - DanielM
@DanielM 谢谢!已修复。 - sehe
1
与其使用basename,我会选择参数扩展并使用git branch -t ${ref#fetched/} $ref,这样您仍然可以在fetch和本地上拥有分支名称foo/bar - Vser
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接