这是我想做的:
我设置了 cron 作业来从上游获取所有更改并修剪已删除的任何分支,如下所示:
*/5 * * * * cd /home/git/myrepo.git && git fetch origin && git remote prune origin > /dev/null
Run Code Online (Sandbox Code Playgroud)
到目前为止我已经尝试过(以及为什么失败):
1-将 git 存储库设置为镜像(如此处所述)
git clone --bare --mirror URL
Run Code Online (Sandbox Code Playgroud)
问题是,当它执行 时git remote prune,它还会删除对已推送到那里(而不是上游服务器)的“本地”更改的引用。
我还尝试让这个本地存储库成为两个独立存储库的镜像(具有相同的主存储库,但有一些不同的分支),并且在执行时遇到类似的问题git remote prune,它将删除来自其他存储库的分支。
2-仅将 git 设置为裸存储库:
git clone --bare URL
Run Code Online (Sandbox Code Playgroud)
但然后git fetch origin没有正确更新,它似乎正在下载对象,但不创建引用,然后只打印
* branch HEAD -> FETCH_HEAD
Run Code Online (Sandbox Code Playgroud)
并且当前分支的“位置”不会随上游服务器中的内容进行更新。
我也git remote update按照这里的描述进行了尝试,得到了相同的结果。
我可以使用以下命令将该存储库转换为镜像:
git config remote.origin.fetch 'refs/heads/*:refs/heads/*'
Run Code Online (Sandbox Code Playgroud)
但这只会让我回到(1)中的问题
假设您可以放弃“镜像”要求,并让“本地(裸)存储库 $X 也使用 refs/heads/upstream/$branch 复制上游存储库 $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
Run Code Online (Sandbox Code Playgroud)
这假设您不会像upstream/master自己那样使用分支名称。(你也可以/代替做类似的事情:
git config remote.origin.fetch '+refs/*:refs/upstream/*'
Run Code Online (Sandbox Code Playgroud)
但refs/upstream/*引用不会被普通的 、 等复制git clone,git fetch所以这对于“普通”git 用户来说更加痛苦。)
让我们也克隆一下该--bare存储库,看看接下来会发生什么。(作为参考,在 上$upstream_host,我有/tmp/t一个常规 git 存储库。在$local_host不完全镜像的机器上,我有/tmp/tt/t.git一个--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
Run Code Online (Sandbox Code Playgroud)
$upstream_host现在我对进行了更改/tmp/t,并提交了它。回到$local_host:
$ 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)
Run Code Online (Sandbox Code Playgroud)
因此,上游所做的更改将出现在您的“有点像镜子,但不完全是”裸 git 存储库中,作为对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
Run Code Online (Sandbox Code Playgroud)
我现在已经通过非裸克隆更新了--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
Run Code Online (Sandbox Code Playgroud)
(名字只是upstream/master在--bare克隆中,所以git rev-parse上面的内容来自/tmp/xt/tnot /tmp/tt/t.git。)