这个远程仓库通常是一个“空仓库”(bare repository),可以使用命令git init --bare来初始化一个空仓库,所谓空仓库就是只有.git目录里面的内容,而没有提交的文件副本(有点不好理解)。
git可以使用四种主要的协议来传输数据:本地传输协议、ssh协议、git协议和http协议,除了http协议之外,其他协议都要求服务器端安装并运行git。
1. 本地传输协议
本地传输即远程仓库就在硬盘的另一个目录中,这常见于对一个共享文件系统具有访问权(例如NFS文件系统),或者多人共用一台电脑(称为服务器)。
例如:
$ mkdir gitserver $ cd gitserver $ git init --bare
创建好git仓库之后,就可以使用git clone命令来克隆远程仓库,克隆时需要指定仓库的路径,例如:
$ git clone /home/tracy/work/git/gitserver
或者:
$ git clone file:///home/tracy/work/git/gitserver
使用file://和不使用它只是运行方式稍微有些不同,这里并没有去深究它,一般使用不带ffile://的,这样运行速度会很快。
克隆了之后,你就可以在你的工作目录中使用git了,例如添加了一个文件README.txt:
$ echo "hello git">README.txt $ git add README.txt $ git commit -m 'add README.txt file to repository'
在执行了git commit命令之后,README.txt文件已经提交到了你的本地仓库中,那么如何推送到远程仓库呢,使用git push命令:
$ git push origin master
origin表示仓库的源头,master表示主分支。
可以使用命令git remote show origin显示远程分支信息:
* remote origin Fetch URL: file:///home/tracy/work/git/gitserver Push URL: file:///home/tracy/work/git/gitserver HEAD branch: master Remote branch: master tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)
2. ssh协议
git中最常使用的协议就是ssh协议了,ssh也是唯一一个同时便于读和写的网络协议了,另外两个网络协议(http和git)通常都是只读的。
前面使用的git init --bare命令来初始化一个空仓库(其实不应该叫做空仓库),那么如果需要将一个已有的git仓库导出为新的空仓库,可以使用git clone命令,新的空仓库目录以.git结尾,例如:
$ git clone --bare my_project my_project.git
上面命令大体相当于:
$ cp -r my_project/.git my_project.git
即只保留了仓库中的.git目录。
可以使用ssh的scp命令将空仓库复制到服务器中去:
$ scp -r my_project.git user@git.example.com:/opt/git
通常git.example.com在局域网内就是服务器的ip地址。
那么具有ssh访问权限的用户就可以使用git clone命令来克隆远程仓库了:
$ git clone user@git.example.com:/opt/git/my_project.git
看上去架设一个git服务器不是那么困难,但要注意的是这里是假设ssh已经配置好并具有读写权限,而这里也是假设git服务器困难的地方(对账户的管理,比如对某些用户具有读写权限,而某些用户只有的读的权限)。
假设服务器上已经安装好了ssh服务,如果需要团队中的每个成员对仓库都具有读写权限,有几种办法:
一是给每个人建立一个账户(使用sudo adduser)并为每个用户设定临时的密码,这种方法呢简单但是过于繁琐。二是在服务器上建立一个git账户,让每个需要写权限的人发送一个ssh共钥,然后将其加入到git账户的~/.ssh/authorized_keys文件,这样所有的人都将通过git账户访问主机。
注意:在创建git这个账户时你可能会设置一个密码,只要有了这个密码,任何人都是可以访问git仓库的(即使没有将密钥加入authorized_keys文件中),所以作为git仓库管理者这个密码是要严格保密的,其他开发者如果要访问git仓库,就让他通过生成密钥的方式来访问,而且通过生成密钥的访问访问git仓库时,在拉取和推送代码时是不需要输入密码的(根本就没有密码验证)。
那么ssh公钥如何生成呢,首先确保自己是否已经有了公钥了,很简单,ssh公钥默认存储在~/.ssh目录中,进去一查便知。
如果没有公钥呢,可以使用ssh-keygen命令来生成,首先会询问公钥的存储位置(.ssh/id_rsa),然后会让你重复输入两次密码,如果不想在使用公钥的时候输入密码,可以为空。生成公钥时候,需要做的是将.pub文件复制给git服务器的管理员,而git服务器管理员在收到公钥之后,需要做以下事情:
$ sudo adduser git $ su git $ cd ~/ $ mkdir .ssh
然后需要将公钥添加到文件authorized_keys中,例如:
$ cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys $ cat /tmp/id_rsa.josie.pub >> ~/.ssh/authorized_keys $ cat /tmp/id_rsa.jessica.pub >> ~/.ssh/authorized_keys
注意:使用cat命令可以将文件内容添加到文件的末尾。
如果需要在John电脑上初始化一个仓库,并将该仓库推送到服务器端作为一个远程仓库,可以使用以下的命令:
$ cd myproject $ git init $ git add . $ git commit -m 'initial commit' $ git remote add origin git@gitserver:/opt/git/project.git $ git push origin master
其中git和gitserver为用户和仓库所在的ip地址。
这样其他人就可以方便的克隆和推送仓库到本地或服务器中。
$ git clone git@server:/opt/git/project.git $ vim README $ git commit -am 'fix for the README file' $ git push origin master
使用这种方法可以很方便快捷的为少数几个开发者搭建一个git服务。
使用ssh shell还会带来一个问题,因为这样用户就能任意访问服务器中的目录,可以使用git-shell工具来把git用户限制仅与git相关,方法是把它设置为git用户登入的shell,那么该用户就不能拥有主机shell访问权限。
$ sudo vim /etc/passwd
找到这样的类似行:
git:x:1000:1000::/home/git:/bin/sh
把/bin/sh改为/usr/bin/git-shell(可以使用which git-shell查看具体路径),修改后如下:
git:x:1000:1000::/home/git:/usr/bin/git-shell
修改后git用户只能使用ssh链接来克隆和推送git仓库,而不能直接使用主机shell,如果使用ssh git@gitserver这样的命令,将会出现拒绝信息。
3. git协议
git协议是一个包含在git中的特殊守护进程,他会监听一个类似于ssh服务的特定端口(9418),而无需任何授权。该服务没有任何安全措施,要么所有人都能克隆仓库,要么所有人都不能,也可以允许推送操作,然而由于没有授权机制,一旦允许,网络上的任何人都将具有推送权限,那么将造成十分严重的后果。
由于git协议没有授权机制,单独使用git协议是不可取的,一般做法是同时提供ssh接口,让几个开发者拥有推送权限,其他人通过git://拥有只读权限。
4. http协议
http或https协议优美之处在于架设的简便性,通常只需要将git空仓库放在http的根目录下,配置一个特定的post-update挂钩(hook)就可以了,例如:
$ cd /var/www/htdocs $ git clone --bare /path/to/git_project gitproject.git $ cd gitproject.git $ mv hooks/post-update.sample hooks/post-update $ chmod a+x hooks/post-update
之后,其他人就可以使用下面的命令来克隆仓库:
$ git clone http://example.com/gitproject.git
通过上面可以看到,最常用的还是ssh协议。
以上文档内容参考自:Pro.Git-zh_CN.pdf