CentOS 7 学习(四)Git配置(一)
1、对于版本管理系统,目前常用的是Subverion和Git,Subversion是集中式版本管理系统中最好的,所有人的代码都要提交到服务器上,如果要知道修改历史,就需要访问服务器;Git的哲学不同,是分布式管理版本,即本地也维护一个或者多个版本或分支,需要的时候才会提交到主服务器上,提供了非常优秀的分支合并功能,这种方式非常适合于分布式开发,即可以在本机开发完成,再同步到主干上,同时本机也可以拥有所有的历史修改信息。 2、环境: 主服务器:CentOS 7, 192.168.1.14 从服务器:CentOS 7, 192.168.1.12 3、CentOS 7带的git版本太低了,是1.8.3,为方便起见,从主站上下载了git-2.0.4.tar.gz,运行命令 tar xvf git-2.0.4.tar.gz cd git-2.0.4 ./configure make make install 在make命令,可能会出现错误,我遇上的如下: /usr/bin/perl Makefile.PL PREFIX='/usr/local' INSTALL_BASE='' --localedir='/usr/local/share/locale' Can't locate ExtUtils/MakeMaker.pm in @INC (@INC contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at Makefile.PL line 3. BEGIN failed--compilation aborted at Makefile.PL line 3. make[1]: *** [perl.mak] 错误 2 make: *** [perl/perl.mak] 错误 2 这是缺少一些Perl的扩展包,运行命令yum install perl-ExtUtils-* 再执行make指令就可以了 [ git-2.0.4]# git --version git version 2.0.4 这说明安装成功了 按照相似的步骤,在另外一台机器上创建同样的git 4、在从服务器上做些测试 1)创建一个用户git,主目录为/opt/git,这个用户是将来连接git服务器的用户名,/opt/git是git仓库的起始目录 useradd git -d /opt/git -U -m -s /bin/bash 2)创建版本库 [ ~]$ su - git [ ~]$ mkdir mysite [ ~]$ cd mysite [ mysite]$ ls [ mysite]$ git init 初始化空的 Git 版本库于 /opt/git/mysite/.git/ 3)配置 git的配置通常用git config命令完成,这个命令有很多参数,大致如下 [ mysite]$ git config 用法:git config [选项] 配置文件位置 --global 使用全局配置文件 --system 使用系统级配置文件 --local 使用版本库级配置文件 -f, --file <文件> 使用指定的配置文件 --blob <数据对象ID> 从给定的数据对象读取配置 操作 --get 获取值:name [value-regex] --get-all 获得所有的值:key [value-regex] --get-regexp 根据正则表达式获得值:name-regex [value-regex] --get-urlmatch 获得 URL 取值:section[.var] URL --replace-all 替换所有匹配的变量:name value [value_regex] --add 添加一个新的变量:name value --unset 删除一个变量:name [value-regex] --unset-all 删除所有匹配项:name [value-regex] --rename-section 重命名小节:old-name new-name --remove-section 删除一个小节:name -l, --list 列出所有 -e, --edit 打开一个编辑器 --get-color <slot> 找到配置的颜色:[默认] --get-colorbool <slot> 找到颜色设置:[stdout-is-tty] 类型 --bool 值是 "true" 或 "false" --int 值是十进制数 --bool-or-int 值是 --bool or --int --path 值是一个路径(文件或目录名) 其它 -z, --null 终止值是NUL字节 --includes 查询时参照 include 指令递归查找 可以看到配置的等级有3层,全局、系统、本地版本库,使用-l或--list命令可以看到已有的配置,目前还什么都没有。 [ mysite]$ git config --global user.name "Shi Yongqiang" [ mysite]$ git config --global user.email "" [ mysite]$ git config --global --list user.name=Shi Yongqiang user.email= 用户名和用户邮件是必须的,这是用来标识你的个人身份,会体现在你的提交历史中。 4)常用命令 git add file_name #增加文件到暂存区 git commit file_name -m "file comment" 提交到本地 git log #查看log git status #显示状态,即是否有文件修改了没有提交 git branch RB1.0 master #创建分支(必须主分支有了内容这个命令才生效),前一个参数为分支名,后一个为源分支名,系统默认创建的分支,即根分支,叫master git checkout RB1.0 #切换到RB1.0分支,这时候查看当前目录,会发现已经变成RB1.0的内容了,如果创建了分支RB1.0之后修改了master分支的文件,会看的更清楚 git checkout -b RB2.0 RB1.0 #创建一个新分支,并切换到新分支 git merge RB1.0 #当前分支为master,这个命令将RB1.0的内容合并到master分支上,这时候有可能会出现冲突,需要手工解决之后才能提交,这时候其内容已经提交到master的当前目录了,但是还没有最后提交,你可以修改文件内容,提交,合并完成了,如果没有冲突,这个命令很容易就完成了。 日常来说,这些命令就够了,不过很少有人会这么用,一般都会使用开发工具如Eclipse带的git工具来实现。 5)协同工作 本机工作的git没什么特别之处,其实和本机安装一个SubVersion没太多区别,其优势在于其分布式开发。 a)连接远程服务器 git clone #从远程服务器下载git项目到本地,这个地址指向的阿里巴巴的mysql同步项目-otter b)自己架设服务器 在从服务器上按照上述办法架设一个git服务器,这样主从服务器就都有了git环境,理想环境是在从服务器上开发,主服务器上发布。 对于分布式管理git项目,对于分支的选择会很麻烦,可以参考这个博客 一般来说,都会有至少两个分支,一个主分支master,一个开发分支developer,开发结束之后,将开发分支合并到主分支上发布,如果出现同时开发的现象,可以将developer分支再创建一个分支,修改完毕之后,合并到开发分支和主分支上,这个分支在主分支发布之后要立刻删除,否则会不好管理。需要注意的是,这种情况下开发分支和主分支再次合并很可能会出现冲突,需要耐心解决。 访问git服务器常用的协议有ssh、git、http,通常来说ssh适合小团队读写,http适合大范围读,git相对来较难架设,且使用非标准端口,只能在内部系统使用。更详细的说明,可以看git官方文档。 使用ssh协议连接服务器有两种办法,一种是通过用户名密码连接,一种是通过公钥私钥连接,前者容易配置,但是没法区分人群,除非不停的增加系统用户,为简单起见,都试验一下: i)使用用户名密码 在主服务器(192.168.1.14)上创建一个git仓库,如下命令 [ ~]$ mkdir gitsite [ ~]$ cd gitsite/ [ gitsite]$ git init 初始化空的 Git 版本库于 /opt/git/gitsite/.git/ [ gitsite]$ vim test.txt [ gitsite]$ git add test.txt [ gitsite]$ git commit -m "git 测试" [master(根提交) 82e77f9] git 测试 1 file changed, 1 insertion(+) create mode 100644 test.txt 记得要设置用户git的密码在从服务器上(192.168.1.12)运行命令 [ ~]$ git clone :/opt/git/gitsite 正克隆到 'gitsite'... 's password: remote: 对象计数中: 3, 完成. remote: Total 3 (delta 0), reused 0 (delta 0) 接收对象中: 100% (3/3), 完成. 检查连接... 完成。 本地出现一个目录gitsite,进入目录,可以看到text.txt文件,运行git log可以看到提交历史。 这样就创建了一个本地版本, [ gitsite]$ git status 位于分支 master 您的分支与上游分支 'origin/master' 一致。 无文件要提交,干净的工作区 本地编辑一个文件,提交到14服务器上,如下 [ gitsite]$ vim t.txt [ gitsite]$ git add . [ gitsite]$ git commit -m "add by 12" [master d1cd89a] add by 12 1 file changed, 1 insertion(+), 1 deletion(-) [ gitsite]$ git commit -m "add by 12" 位于分支 master 您的分支领先 'origin/master' 共 1 个提交。 (使用 "git push" 来发布您的本地提交) 无文件要提交,干净的工作区 可以看出本地创建了t.txt,提交到本地,在第二次提交的时候,系统给了提示,可以用git push来更新到远程目录 运行命令如下 [ gitsite]$ git push warning: push.default 尚未设置,它的默认值在 Git 2.0 已从 'matching' 变更为 'simple'。若要不再显示本信息并保持传统习惯,进行如下设置: git config --global push.default matching 若要不再显示本信息并从现在开始采用新的使用习惯,设置: git config --global push.default simple 当 push.default 设置为 'matching' 后,git 将推送和远程同名的所有 本地分支。 从 Git 2.0 开始,Git 缺省采用更为保守的 'simple' 模式,只推送当前 分支到远程关联的同名分支,即 'git push' 推送当前分支。 参见 'git help config' 并查找 'push.default' 以获取更多信息。 ('simple' 模式由 Git 1.7.11 版本引入。如果您有时要使用老版本的 Git, 为保持兼容,请用 'current' 代替 'simple') 's password: 对象计数中: 6, 完成. Delta compression using up to 2 threads. 压缩对象中: 100% (4/4), 完成. 写入对象中: 100% (6/6), 591 bytes | 0 bytes/s, 完成. Total 6 (delta 0), reused 0 (delta 0) remote: error: refusing to update checked out branch: refs/heads/master remote: error: By default, updating the current branch in a non-bare repository remote: error: is denied, because it will make the index and work tree inconsistent remote: error: with what you pushed, and will require 'git reset --hard' to match remote: error: the work tree to HEAD. remote: error: remote: error: You can set 'receive.denyCurrentBranch' configuration variable to remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into remote: error: its current branch; however, this is not recommended unless you remote: error: arranged to update its work tree to match what you pushed in some remote: error: other way. remote: error: remote: error: To squelch this message and still keep the default behaviour, set remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'. To :/opt/git/gitsite ! [remote rejected] master -> master (branch is currently checked out) error: 无法推送一些引用到 ':/opt/git/gitsite' 这是个常见错误,看提示信息可以看出很多东西,首先来说,提示设置push.default变量,2.0之前默认是matching,提交所有和远程同名的分支,2.0之后默认是simple,只提交当前分支。后面的提示是远程的分支正处于checkout状态,所以无法推送。 可以在服务器上配置,可以提交当前分支,如下 [ gitsite]$ git config --global receive.denyCurrentBranch "ignore" 这样12服务器就可以提交了。 所以如果是大型的项目,多个分支、多个版本,一般来说,主服务器上的版本库都会建立裸库,即没法进行checkout,add,commit的库,不过对于小型项目,主版本库还是能操作比较好,如果已经比较成熟了,就可以采用裸库。 有些情况下,是先有本地的版本库,然后采用主版本库,需要将本地的版本库复制到主本版本库,然后可以同步 在12机器创建版本库gitsite1,然后 [ ~]$ git init --template=/opt/git/gitsite1 gitsite1.git 初始化空的 Git 版本库于 /opt/git/gitsite1.git/.git/ [ ~]$ cd gitsite1.git/ [ gitsite1.git]$ ls [ gitsite1.git]$ pwd /opt/git/gitsite1.git [ gitsite1.git]$ cd .. [ ~]$ scp -r gitsite1.git/ ssh::/opt/git 's password: test.txt 100% 28 0.0KB/s 00:00 HEAD 100% 23 0.0KB/s 00:00 config 100% 92 0.1KB/s 00:00 这样就传输到了主目录 在本地和远程建立连接 [ gitsite1]$ git push :/opt/git/gitsite1.git master 's password: 对象计数中: 3, 完成. 写入对象中: 100% (3/3), 234 bytes | 0 bytes/s, 完成. Total 3 (delta 0), reused 0 (delta 0) To :/opt/git/gitsite1.git * [new branch] master -> master master是分支名称 也可以为远程服务器建立名称,这样用起来会舒服一些 [ gitsite1]$ git remote add orign :/opt/git/gitsite1.git [ gitsite1]$ git push orign master 's password: Everything up-to-date 远程的常用命令 git push #推送 git pull #下载远程代码 ii)使用密钥 密钥的使用非常简单,客户端创建公钥和密钥,设置密钥密码,将公钥上传到服务器,服务器将公钥加入信任文件中,然后客户端操作会提示输入密码,就是密码密码,具体如下 [ gitsite1]$ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/opt/git/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /opt/git/.ssh/id_rsa. Your public key has been saved in /opt/git/.ssh/id_rsa.pub. The key fingerprint is: 20:70:11:47:f8:ca:91:37:6d:5d:43:cd:13:1c:40:61 The key's randomart image is: +--[ RSA 2048]----+ | . +=o oE*oo | | o.. .o = | | .o.. . . . . | | o.+.o . | | . + oS | | o | | | | | | | +-----------------+ [ gitsite1]$ cd [ ~]$ cd .ssh [ .ssh]$ ls id_rsa id_rsa.pub known_hosts [ .ssh]$ mv id_rsa.pub id_rsa_shiyq.pub [ .ssh]$ scp id_rsa_shiyq.pub :/opt/git Enter passphrase for key '/opt/git/.ssh/id_rsa': 's password: id_rsa_shiyq.pub 100% 395 0.4KB/s 00:00 [ .ssh]$ scp id_rsa_shiyq.pub :/opt/git Enter passphrase for key '/opt/git/.ssh/id_rsa': id_rsa_shiyq.pub 服务器端 [ ~]$ mv id_rsa_shiyq.pub .ssh/. [ ~]$ cd .ssh/ [ .ssh]$ ls authorized_keys id_rsa id_rsa.pub id_rsa_shiyq.pub known_hosts [ .ssh]$ cat id_rsa_shiyq.pub >> authorized_keys 客户端 [ gitsite1]$ vim test.txt [ gitsite1]$ git add . [ gitsite1]$ git commit -m "add by 12 下午" [master 77801a8] add by 12 下午 1 file changed, 6 insertions(+), 1 deletion(-) [ gitsite1]$ git push :/opt/git/gitsite1.git master Enter passphrase for key '/opt/git/.ssh/id_rsa': 对象计数中: 3, 完成. Delta compression using up to 2 threads. 压缩对象中: 100% (2/2), 完成. 写入对象中: 100% (3/3), 304 bytes | 0 bytes/s, 完成. Total 3 (delta 0), reused 0 (delta 0) To :/opt/git/gitsite1.git 4cbda98..77801a8 master -> master 从远程服务器下载数据常见的办法是git fetch和git pull git pull比较危险,因为直接从服务器上下载,覆盖本地 git fetch是将远程的分支下载到本地的临时分支上,可以看有多大区别,然后可以选择是否合并。