Git local mirror and repository

邮差的信 提交于 2019-12-06 03:53:10

Assuming you can drop the "mirror" requirement, and have "local (bare) repo $X also copies upstream repo $UX using refs/heads/upstream/$branch to name upstream branches known there as refs/heads/$X", use your second approach, but do this instead:

$ 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

This assumes you won't use branch names like upstream/master for anything yourself. (You could also/instead do something like:

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

but refs/upstream/* references are not copied over by normal git clone, git fetch, etc., so this is more of a pain for "normal" git users.)

Let's make a clone of the --bare repo too to see what happens as we go on. (For reference, on $upstream_host, I have /tmp/t, a regular git repo. On $local_host, the not-quite-mirror machine, I have /tmp/tt/t.git, a --bare repo that does this upstream tracking thing. I am actually using the same host for both but the principle applies...)

$ 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

Now I made a change on $upstream_host in /tmp/t, and commited it. Back on $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)

Thus, changes made upstream will appear in your "sort of a mirror but not exactly" bare git repo as a change to upstream/master rather than master, or more generally, upstream/$branch for any $branch. If you want to merge them you'll have to do that manually. My example below is a bit messy because the change I made on $upstream_host was a history rewrite (hence all the forced update stuff), which winds up getting exposed here via the clones. If you don't want it exposed you'll have to note which updates were history rewrites and (in effect) manually copy them to your own not-quite-mirror, and then on to any clones of that. I'll just go ahead and make a real merge.

So, now we go to the non-bare repo on $local_host, in /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

I've now updated the --bare clone ($local_host, /tmp/tt/t.git) via the non-bare clone to merge the upstream work into my local not-exactly-a-mirror. The HEAD revision is my merge, HEAD^1 is the original (broken) update that used to be origin/upstream/master (before all the "forced update"ing), and HEAD^2 is the corrected update that is now origin/upstream/master (afterward):

$ git rev-parse HEAD^2 origin/upstream/master
5e013711f5d6eb3f643ef562d49a131852aa4aa1
5e013711f5d6eb3f643ef562d49a131852aa4aa1

(The name is just upstream/master in the --bare clone, so the git rev-parse above is from /tmp/xt/t not /tmp/tt/t.git.)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!