关于git(二)-详解不使用fork迁移备份git仓库

背景

经常用git都知道,别人有个仓库如在github,轻点fork一下,则这个仓库的所有分支/tags都跑到自己名下的仓库了。但是在更多时候,是没有这个fork按键的,这时需要我们使用命令将仓库的origin备份到myorigin.(假定源仓库为origin,新仓库为myorigin)

一个误区

先来纠正一个误区,那就是很多人使用git push myorigin --all(假设已经git remote add myorigin myorigin_url了),这个命令只能把本地已经存在的分支推到myorigin,而不能把origin所有的分支推到myorigin.

接下来我们用glide这个仓库来作测试,将glide的git仓库https://github.com/bumptech/glide.git转移到我新建的测试仓库https://github.com/yanzi1225627/glide_test.git.

方法一

执行git clone --bare https://github.com/bumptech/glide.git,然后cd glide.git,git branch -a查看:

  2.0
  3.0
  4.0a
  gh-pages
* master
  palette

一共有6个分支,git tag查看下tag的信息:

v2.0-alpha
v2.0.0
v2.0.1
v2.0.2
v2.0.3
v2.0.4
v2.0.5
v3.0.0a
v3.1.0a
v3.2.0a
v3.3.0
v3.3.1
v3.4.0
v3.5.0
v3.5.1
v3.5.2
v3.6.0
v3.6.1
v3.7.0

一共19个tag.执行
git push --mirror https://github.com/yanzi1225627/glide_test.git将本地的这个裸仓库push到自己的仓库上。可以看到git的信息如下:

To https://github.com/yanzi1225627/glide_test.git
* [new branch]      2.0 -> 2.0
 * [new branch]      3.0 -> 3.0
 * [new branch]      4.0a -> 4.0a
 * [new branch]      gh-pages -> gh-pages
 * [new branch]      master -> master
 * [new branch]      palette -> palette
 * [new tag]         v2.0-alpha -> v2.0-alpha
 * [new tag]         v2.0.0 -> v2.0.0
 * [new tag]         v2.0.1 -> v2.0.1
 * [new tag]         v2.0.2 -> v2.0.2
 * [new tag]         v2.0.3 -> v2.0.3
 * [new tag]         v2.0.4 -> v2.0.4
 * [new tag]         v2.0.5 -> v2.0.5
 * [new tag]         v3.0.0a -> v3.0.0a
 * [new tag]         v3.1.0a -> v3.1.0a
 * [new tag]         v3.2.0a -> v3.2.0a
 * [new tag]         v3.3.0 -> v3.3.0
 * [new tag]         v3.3.1 -> v3.3.1
 * [new tag]         v3.4.0 -> v3.4.0
 * [new tag]         v3.5.0 -> v3.5.0
 * [new tag]         v3.5.1 -> v3.5.1
 * [new tag]         v3.5.2 -> v3.5.2
 * [new tag]         v3.6.0 -> v3.6.0
 * [new tag]         v3.6.1 -> v3.6.1
 * [new tag]         v3.7.0 -> v3.7.0

把所有的分支和tag都push到自己的仓库了。这种方式实乃迁移git仓库的最正统方式,没有之一!

备注:1,这里第一步的git clone --bare 也可以用git clone --mirror,这个稍后再讲;2,使用mirror clone下来的东西再push的时候会发现很多被拒绝的refs,这个正常,如下图所示

方法二

鉴于我们通常工作时不会用裸仓库,都是git clone https://github.com/bumptech/glide.git下载的,这样即包含工作空间(work tree)又包括代码库(.git文件夹).

执行:

git remote add myorigin https://github.com/yanzi1225627/glide_test.git
git push myorigin +refs/remotes/origin/\*:refs/heads/\*
git push myorigin --tags

就ok了,注意这种方法branch和tags是分开推送的,而且会多出一个head分支,这个可以忽略。

关于bare和mirror

1.定时同步

假设我们需要定时从origin取下来东西,然后push到myorigin上。则可以在方法1的基础上,将git clone --bare https://github.com/bumptech/glide.git换成git clone --mirror https://github.com/bumptech/glide.git,然后执行:

git remote set-url --push origin https://github.com/yanzi1225627/glide_test.git
git fetch -p origin
git push --mirror

其中第一句话是指定origin对应的push地址,这样remote只有一个origin,但是fetch和push对应不同的地址。第二句话里的-p 的意思是:remove any remote tracking branches that no longer exist remotely,即如果origin里远端有分支不存在了,则把对应的本地跟踪分支删掉.如果要做同步只需要定时执行后两句就可以了。

2.bare和mirror的区别

共同点

两者clone下来的都是裸仓库,不含工作空间。mirror clone下的空间略大于bare,但是基本一样。这两种方式都能clone下来所有的branch和tag.

区别
  1. mirror clone下来的东西除了branch和tag外,还有其他refs,如merge request之类的。
  2. mirror clone的时候会在仓库里指定fetch.
    也许大家还不够明白,先来看看官方的解释:
--mirror

Set up a mirror of the source repository. This implies --bare. Compared to --bare, --mirror not only maps local branches of the source to local branches of the target, it maps all refs (including remote branches, notes etc.) and sets up a refspec configuration such that all these refs are overwritten by a git remote update in the target repository.

再来个更直白的解释:
git clone --mirror $URL这句话等同于下面两句:

git clone --bare $URL
(cd $(basename $URL) && git remote add --mirror=fetch origin $URL)

也就是在bare的基础上,增加了fetch的设置,如图所示:

看到这应该真相大白了!

3.bare和no-bare互转

即如何从裸仓库恢复到带有工作空间的正常目录。
新建一个工程文件夹,然后将bare clone下来的xxx.git名字改为.git拖到工程文件夹中。然后

git config --local core.bare false
git reset --hard  git checkout master

其实懂得了如何bare转no-bare,也完全可以no-bare转bare,这样在带工作空间的目录里,只要对.git目录稍作修改就可以进行备份了。
另外一种思路是参考http://haohetao.iteye.com/blog/1490001,使用如下命令可以快速的在bare和no-bare间转换:

//假设sw目录是带工作空间的git目录
//no-bare 转bare
git clone --bare /home/project/sw sw.git 
touch sw.git/git-daemon-export-ok

//bare转no-bare
git clone /home/chen/sw.git sw 

但是上述方法切记,在通过git clone --bare /home/project/sw sw.git导bare时只会将本地存在的分支导出去,跟origin上的分支没有关系,所以这种方式仅供参考,必要时候配合使用.

4.使用裸仓库好处

基本上体积是带工作空间体积的1/2.

参考

  1. https://help.github.com/articles/duplicating-a-repository/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值