Git本地镜像和存储库

时间:2013-07-31 20:54:43

标签: git mirror

以下是我想做的事情:

  • 拥有一个镜像上游的本地git存储库
  • 能够推动"本地"分支/更改到该存储库并保留本地
  • 保持此存储库与上游存储库同步,包括:
    • 获取任何新分支
    • 删除上游删除的分支的任何引用

我设置我的cron作业以从上游获取所有更改并修剪任何已删除的分支,如下所示:

*/5 * * * * cd /home/git/myrepo.git && git fetch origin && git remote prune origin > /dev/null

到目前为止我所尝试的(以及它失败的原因):

1-将git存储库设置为镜像(如here所述)

git clone --bare --mirror URL

问题在于git remote prune执行时,它还删除对" local"的引用。已推送的更改(而不是上游服务器)。

我还尝试让这个本地存储库成为两个独立存储库的镜像(具有相同的主服务器,但有一些不同的分支),并且在执行git remote prune时遇到了类似的问题,它将删除来自其他存储库。

2-仅将git设置为裸存储库:

git clone --bare URL

但是git fetch origin没有正确更新,它似乎是在下载对象,但是没有创建引用然后只打印

 * branch            HEAD       -> FETCH_HEAD

和"位置"目前的分支机构没有使用上游服务器中的内容进行更新。

我也按here所述尝试git remote update,结果相同。

我可以convert that repository as a mirror使用:

git config remote.origin.fetch 'refs/heads/*:refs/heads/*'

但这只会让我回到(1)

中的问题

1 个答案:

答案 0 :(得分:3)

假设您可以删除“镜像”要求,并且“本地(裸)repo $ X也使用refs / heads / upstream / $ branch复制上游repo $ UX,将上游分支命名为refs / heads / $ X“,使用你的第二种方法,但改为:

$ cd /tmp; mkdir tt; cd tt; git clone --bare ssh://$upstream_host/tmp/t
$ cd t.git
$ git config remote.origin.fetch '+refs/heads/*:refs/heads/upstream/*'
$ git fetch -p # accidentally omitted this step from cut/paste earlier

这假设您不会自己使用upstream/master这样的分支名称。 (你也可以这样做:

git config remote.origin.fetch '+refs/*:refs/upstream/*'

refs/upstream/*引用不会被普通git clonegit fetch等复制,所以这对“普通”git用户来说更加痛苦。)

让我们复制--bare repo,看看我们继续发生了什么。 (作为参考,在$upstream_host上,我有/tmp/t,一个常规的git repo。在$local_host上,这个不太镜像的机器,我有/tmp/tt/t.git,一个{{ 1}} repo执行此上游跟踪的事情。我实际上使用相同的主机,但原则适用...)

--bare

现在我对$ cd /tmp; mkdir xt; cd xt; git clone ssh://$local_host/tmp/tt/t.git Cloning into 't'... remote: Counting objects: 96, done. remote: Compressing objects: 100% (54/54), done. remote: Total 96 (delta 33), reused 96 (delta 33) Receiving objects: 100% (96/96), 17.11 KiB | 0 bytes/s, done. Resolving deltas: 100% (33/33), done. Checking connectivity... done 中的$upstream_host进行了更改,并提交了它。返回/tmp/t

$local_host

因此,上游所做的更改将显示在您的“镜像但不完全”的git仓库中,作为对$ cd /tmp/tt/t.git; git fetch -p origin # -p will prune deleted upstream/foo's remote: Counting objects: 5, done. remote: Compressing objects: 100% (4/4), done. remote: Total 4 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (4/4), done. From ssh://$host/tmp/t + c10e54c...5e01371 master -> upstream/master (forced update) 的更改,而不是upstream/master,或更一般地,master对于任何upstream/$branch。如果你想合并它们,你必须手动完成。我在下面的例子有点乱,因为我在$branch上所做的更改是历史重写(因此所有$upstream_host内容),它最终通过克隆暴露在这里。如果您不希望它暴露,您将必须注意哪些更新是历史记录重写,并且(实际上)手动将它们复制到您自己的非镜像,然后再到它的任何克隆。我会继续进行真正的合并。

所以,现在我们转到forced update $local_host上的非裸仓库:

/tmp/xt/t

我现在已经通过非裸克隆更新了$ cd /tmp/xt/t $ git fetch remote: Counting objects: 5, done. remote: Compressing objects: 100% (4/4), done. remote: Total 4 (delta 1), reused 1 (delta 0) Unpacking objects: 100% (4/4), done. From ssh://$local_host/tmp/tt/t + c10e54c...5e01371 upstream/master -> origin/upstream/master (forced update) $ git status # On branch master nothing to commit, working directory clean $ git log --oneline --decorate --graph * 5e01371 (origin/upstream/master) add ast example | * c10e54c (HEAD, origin/master, origin/HEAD, master) add ast example |/ * 309b36c add like_min.py ... [snipped] $ git merge origin/upstream/master Merge remote-tracking branch 'origin/upstream/master' # Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit. ... $ git push warning: push.default is unset; its implicit value is changing in Git 2.0 from 'matching' to 'simple'. To squelch this message ... Counting objects: 1, done. Writing objects: 100% (1/1), 244 bytes | 0 bytes/s, done. Total 1 (delta 0), reused 0 (delta 0) To ssh://$local_host/tmp/tt/t.git c10e54c..e571182 master -> master 克隆(--bare$local_host),将上游工作合并到我的本地非精确镜像中。 /tmp/tt/t.git修订是我的合并,HEAD是原始(已损坏)更新,曾经是HEAD^1(在所有“强制更新”之前),origin/upstream/master是现在为HEAD^2(之后)的更正后的更新:

origin/upstream/master

$ git rev-parse HEAD^2 origin/upstream/master 5e013711f5d6eb3f643ef562d49a131852aa4aa1 5e013711f5d6eb3f643ef562d49a131852aa4aa1 克隆中的名称只是upstream/master,因此上面的--bare来自git rev-parse而不是/tmp/xt/t。)