首先,请不要安装 gitosis:使用最新的V3+ Gitolite,一个更完整的授权层:请参阅“ gitosis vs gitolite? ”和“为什么需要 Gitosis 或 Gitolite? ”。
其次,您不会丢失任何分支信息。
这是解决同一问题的另一种方法,更长,但它说明了您如何仍然保留所有分支。
您的任何克隆都可能没有所有本地分支,没错,但所有这些分支仍位于这些克隆的远程命名空间中,因为它们是从同一个(现已消失的)“中央”存储库克隆的。
一旦你在新的中央服务器上克隆回来(作为一个裸仓库)这些仓库之一,你所需要的只是清理一下它,你可以将它作为新的祝福仓库引用。
注意:如果您无法从服务器访问本地存储库,请捆绑所述本地存储库,并将代表该捆绑包的一个文件复制回您的服务器:您将能够从所述捆绑包中克隆。
请参阅“ git bundle
: bundle tags and heads ”以正确创建捆绑包。
简洁版本
# Let's re-create a bare "blessed" repo on the server
git clone --mirror /path/to/a/local/repo repo.git
# or git clone --mirror /path/to/repo.bundle repo.git
# restore the local branches
remote=origin ; for brname in `git branch -r | grep $remote | grep -v HEAD | awk '{gsub(/[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream $brname $remote/$brname ; done
# delete the remotes branches
# (your blessed repo doesn't track anything)
remote=origin ; for brname in `git branch -r | grep $remote | grep -v HEAD | awk '{gsub(/[^\/]+\//,"",$1); print $1}'`; do git branch -r -d origin/$brname ; done
# delete the remote 'origin'
# Not needed for your blessed repo
git remote rm origin
# Let's make sure master is the current branch
# for that bare repo:
git symbolic-ref HEAD refs/heads/master
就是这样。准备好出发。
长版(演示)
让我们创建一个 repo,有 4 个分支:master
、b1
、b2
、b3
,每个分支都有自己的文件:
C:\Users\VonC\prog\git\tests>mkdir c
C:\Users\VonC\prog\git\tests>cd c
C:\Users\VonC\prog\git\tests\c>git init r1
Initialized empty Git repository in C:/Users/VonC/prog/git/tests/c/r1/.git/
C:\Users\VonC\prog\git\tests\c>cd r1
C:\Users\VonC\prog\git\tests\c\r1>echo m > m.txt && git add . && git commit -m "first commit"
[master (root-commit) 1ffe5c1] first commit
1 file changed, 1 insertion(+)
create mode 100644 m.txt
C:\Users\VonC\prog\git\tests\c\r1>git checkout -b b1
Switched to a new branch 'b1'
C:\Users\VonC\prog\git\tests\c\r1>echo f1 > f1.txt && git add . && git commit -m "f1 in b1"
[b1 1e64d01] f1 in b1
1 file changed, 1 insertion(+)
create mode 100644 f1.txt
C:\Users\VonC\prog\git\tests\c\r1>git checkout -b b2 master
Switched to a new branch 'b2'
C:\Users\VonC\prog\git\tests\c\r1>echo f2 > f2.txt git add . && git commit -m "f2 in b2"
[b2 4462b8f] f2 in b2
1 file changed, 1 insertion(+)
create mode 100644 f2.txt
C:\Users\VonC\prog\git\tests\c\r1>git checkout -b b3 master
Switched to a new branch 'b3'
C:\Users\VonC\prog\git\tests\c\r1>echo f3 > f3.txt && git add . && git commit -m "f3 in b3"
[b3 7ada753] f3 in b3
1 file changed, 1 insertion(+)
create mode 100644 f3.txt
现在,如果我克隆r1
intor2
和r2
into r3
,是的,r3
会丢失分支信息:
C:\Users\VonC\prog\git\tests\c>git clone r1 r2
Cloning into 'r2'...
done.
C:\Users\VonC\prog\git\tests\c>git clone r2 r3
Cloning into 'r3'...
done.
C:\Users\VonC\prog\git\tests\c>cd r3
C:\Users\VonC\prog\git\tests\c\r3>git br -a
* b3
remotes/origin/HEAD -> origin/b3
remotes/origin/b3
但是在您的情况下,大多数存储库都是从受祝福的存储库中克隆的直接结果。
r2
拥有所有必要的分支(一个本地,4 个远程跟踪分支,因为没有“本地跟踪分支”):
C:\Users\VonC\prog\git\tests\c\r2>git br -a
* b3
remotes/origin/HEAD -> origin/b3
remotes/origin/b1
remotes/origin/b2
remotes/origin/b3
remotes/origin/master
如果我可以clone --mirror r2
进入一个裸仓库 r4
,我仍然会得到所有的分支。
请参阅“和之间有什么区别git clone --mirror
git clone --bare
”了解原因。
C:\Users\VonC\prog\git\tests\c>git clone --mirror r2 r4
Cloning into bare repository 'r4'...
done.
C:\Users\VonC\prog\git\tests\c>cd r4
C:\Users\VonC\prog\git\tests\c\r4>git br -a
* b3
remotes/origin/HEAD
remotes/origin/b1
remotes/origin/b2
remotes/origin/b3
remotes/origin/master
它的遥控器仍然指向r2
VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:b3)
$ git remote -v
origin C:/Users/VonC/prog/git/tests/c/r2 (fetch)
origin C:/Users/VonC/prog/git/tests/c/r2 (push)
但这不再需要了。
让我们确保r2
(或r1
就此而言)不再可访问:
VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:b3)
$ cd ..
VonC@HOSTNAME ~/prog/git/tests/c
$ mv r1 r1.old
VonC@HOSTNAME ~/prog/git/tests/c
$ mv r2 r2.old
VonC@HOSTNAME ~/prog/git/tests/c
$ cd r4
现在我们可以通过将本地分支指向远程跟踪分支来恢复本地分支
:
请参阅“将所有远程 git 分支跟踪为本地分支”:
VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:b3)
$ remote=origin ; for brname in `git branch -r | grep $remote | grep -v HEAD | awk '{gsub(/[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream $brname $remote/$brname ; done
Branch b1 set up to track remote ref refs/remotes/origin/b1.
Branch b2 set up to track remote ref refs/remotes/origin/b2.
Branch b3 set up to track remote ref refs/remotes/origin/b3.
Branch master set up to track remote ref refs/remotes/origin/master.
让我们master
为该裸存储库创建默认分支:
请参阅“ Git:在裸存储库中更改活动分支的正确方法? ”和“如何更改 Git 远程HEAD
以指向除“<code>master”之外的其他内容</a >”。
VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:b3)
$ git symbolic-ref HEAD refs/heads/master
VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:master)
origin
不再需要任何引用“ ”的内容。
让我们摆脱远程跟踪分支:
参见“删除列出的分支git branch -a
”和“删除远程分支? ”
VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:master)
$ remote=origin ; for brname in `git branch -r | grep $remote | grep -v HEAD | awk '{gsub(/[^\/]+\//,"",$1); print $1}'`; do git branch -r -d origin/$brname ; done
Deleted remote branch origin/b1 (was 1e64d01).
Deleted remote branch origin/b2 (was 4462b8f).
Deleted remote branch origin/b3 (was 7ada753).
Deleted remote branch origin/master (was 1ffe5c1).
让我们恐慌并检查我们的本地分支是否仍然引用我们刚刚“删除”的内容:(
参见“在 git 中显示每个分支的最新提交”)
VonC@HOSTNAME ~/prog/git/tests/c/r4 (BARE:master)
$ git br -v
b1 1e64d01 f1 in b1
b2 4462b8f f2 in b2
b3 7ada753 f3 in b3
* master 1ffe5c1 first commit
是的,一切都很好。