Git是目前世界上最先进的分布式版本控制系统 .
git的故事
很多人都知道,Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。
在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码!
Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了 !
集中式版本控制系统(svn)
版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。
缺点:
1.集中式版本控制系统最大的毛病就是必须联网才能工作
2.合并的时候冲突解决起来麻烦
3.版本控制系统安全性差(集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了 )
分布式版本控制系统(git)
分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
注意:实际使用分布式版本控制系统的时候 ,版本控制系统通常也有一台充当“中央服务器”的电脑 。
git安装(在linux上安装git)
1.测试git是否安装
> git
2.若没有安装则使用以下命令来安装
>sudo apt-get install git
版本管理库
版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
1.选择一个合适的地方创建一个空目录:
> mkdir gitdemo >cd gitdemo >pwd
2.通过git init命令把这个目录变成git可以管理的仓库
>git init
现在仓库以及创建完毕,并且是一个空的仓库,在这个目录下多了一个.git目录【不要手动修改此目录】
3.创建一个文件,demo1.txt
> echo "hello world!" > demo1.txt
注意:一定要将此文件放在gitdemo的目录下或者其子目录下
4.使用git add,使文件添加到仓库
>git add demo1.txt
5.使用命令git commit将文件提交到仓库
>git commit -m "add hello" #在此命令中-m后面表示的是本次提交的时候的说明,为了以后方便找到改动记录
注意:我们可以一次性提交多个文件
git版本管理
修改内容
1.现在我更改了demo1.txt的内容
>echo "good" >> demo1.txt
2.使用git status可以查看结果
> git status
注意:git status命令可以让我们时刻掌握仓库的当前状态。
3.git diff 文件
> git diff demo1.txt
注意:此命令可以查看文件不同【文件修改了哪些地方都会高亮起来】
4.提交修改
> git add demo1.txt
5.在执行commit之前查看仓库状态
> git status
6.提交文件
> git commit -m "add good"
7.提交之后查看仓库状态
> git status
版本回退
1.使用git log查看历史纪录
> git log
git log会显示从最近到最远的提交日志,若输出的信息太多则可以添加以下参数:
>git log --pretty=oneline
注意:在这里会显示类似1093ab...之类的是commit id(版本号),每提交一个版本则会生成一个版本号【版本号都不相同】
2.回退到上一个版本
> git reset --hard HEAD^
3.查看demo1.txt
>cat demo1.txt
4.查看现在版本的状态
> git log
注意:最新版本已经不见了,则证明你已经穿越成功!
回退回去
> git reset --hard 版本号
注意:这个版本号就是你要回退回去的版本号,只需要写前面几位即可。
git reflog记录你的每一次命令
>git reflog
工作区与暂存区
工作区
在电脑里能够看到的目录,比如gitdemo文件夹就是一个工作区
版本库
在工作区中有一个隐藏的目录.git,此目录为版本库.
暂存区
在版本库中存放了很多东西,其中最重要的就是成为stage的暂存区。还有git给我创建的一个master分支,以及指向master的指针head。
注意:我们提交文件的时候分为两部:
1.git add 此方法是将工作区中的内容提交到暂存区
2.git commit 则是将暂存区的内容提交到当前分支
因为在我们创建git版本库的时候,git自动的为我们创建一个master分支,所以我们现在所有的更改都是在master分支上进行的。
撤销修改
1.使用git checkout --file可以丢弃工作区的修改
> git checkout --demo1.txt
注意:这里有两种情况:
1.demo1.txt修改后还没放到暂存区,撤销修改则回到与版本库一模一样的状态
2.demo1.txt已经添加放到了暂存区,现在又做了修改,则撤销之后就会回到添加暂存区后一样的状态
总结:此命令可将文件回到最近一次git commit或者git add时候的状态。
注意:此命令中的--非常重要,必须添加,否则就变成了切换到另外一个分支的命令。
文件删除
1.提交一个文件到git仓库
> git add test.txt > git commit -m "add test.txt"
2.在工作区删除此文件【此文件没用】
> rm test.txt
3.当工作区与版本库不同的时候,git status则会显示不同
> git status
4.删除此文件你有两个选择
1》从版本库中直接删除该文件
> git rm test.txt
2》使用撤销修改的操作
> git checkout --test.txt
远程仓库
1.首先注册GitHub账号,本地git与GitHub仓库之间的传输是通过ssh加密的,所以需要以下设置。
2.创建ssh key,在用户主目录下查看是否存在.ssh目录,并且查看此目录下是否存在id_rsa和is_ras.pub这两个文件,若存在则忽略此步骤:
#注册githup的邮箱地址 >ssh-keygen -t rsa -C "[email protected]"
一路回车即可,顺利的话则会在.ssh目录中生成两个文件,id_rsa与id_rsa.pub这两个就是SSH Key的秘钥对,
id_rsa
是私钥,不能泄露出去,id_rsa.pub
是公钥,可以放心地告诉任何人。
2.登陆githup,打开account settings,“ssh keys页面”:然后点击“add ssh key”,填上任意的title,在key的文本框中粘贴id_rsa.pub文件的内容。然后点击add key,就可以看到已经添加的key。
添加远程仓库
登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库.
我们根据GitHub的提示,在本地的gitdemo仓库下运行命令
git remote add origin git@github.com:zhangjiao1/gitdemo.git
把上面的zhangjiao1替换成你自己的GitHub账户
添加后,远程库的名字就是origin
,这是Git默认的叫法,也可以改成别的,但是origin
这个名字一看就知道是远程库 .
把本地库的所有内容推送到远程库上
$ git push -u origin master
把本地库的内容推送到远程,用
git push
命令,实际上是把当前分支master
推送到远程。由于远程库是空的,我们第一次推送
master
分支时,加上了-u
参数,Git不但会把本地的master
分支内容推送的远程新的master
分支,还会把本地的master
分支和远程的master
分支关联起来,在以后的推送或者拉取时就可以简化命令。
从现在起,只要本地作了提交,就可以通过命令:
$ git push origin master
从远程仓库克隆
1.登陆GitHub,创建一个新的仓库,名字叫gitpro:
我们勾选Initialize this repository with a README
,这样GitHub会自动为我们创建一个README.md
文件。创建完毕后,可以看到README.md
文件 。
2.用命令git clone
克隆一个本地库:
git clone git@github.com:zhangjiao1/gitpro.git
分支管理
创建与合并分支
1.首先,我们创建dev
分支,然后切换到dev
分支:
git checkout
命令加上-b
参数表示创建并切换,相当于以下两条命令
git branch dev git checkout dev
2.用git branch
命令查看当前分支:
git branch * dev
3.创建一个新的文件
> echo "you are a good man!" > demo.txt > git commit -m "branch test"
4.dev分支的工作完成,切换为master分支
> git checkout master
5.把dev
分支的工作成果合并到master
分支上
> git merge dev
6.合并完成后,就可以放心地删除dev
分支了
> git branch -d dev
解决冲突
1.准备新的feature1
分支,继续我们的新分支开发
> git checkout -b feature1
2.创建一个新的文件
> echo "hello world!" > new.txt
在feature1分支上提交
> git add new.txt > git commit -m "and simple"
切换到master分支
> git checkout master
在master分支将new.txt追加:
> echo "hello worlds!" > new.txt
提交文件
> git add new.txt > git commit -m "add new"
合并代码
> git merge feature1
git 告诉我们,new.txt文件存在冲突,必须手动解决后才能 提交。
使用git status也可以告诉我们冲突文件
> git status
我们可以直接查看readme.txt的内容 ,Git用
<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容 .我们修改如下后保存:
"hello world!"
10.重新提交:
> git add new.txt > git commit -m "fixed"
最后删除feature1分支
> git branch -d feature1
用
git log --graph
命令可以看到分支合并图。
添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支
推送分支
推送分支
推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
git push origin master
如果要推送其他分支,比如dev
,就改成:
git push origin dev
但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?
master
分支是主分支,因此要时刻与远程同步;dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
标签管理
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。
创建标签
Git中打标签非常简单,首先,切换到需要打标签的分支上:
git branch * dev master git checkout master Switched to branch 'master'
然后,敲命令git tag <name>
就可以打一个新标签:
git tag v1.0
可以用命令git tag
查看所有标签:
git tag v1.0
对add merge
这次提交打标签,它对应的commit id是f52c633
,敲入命令:
git tag v0.9 f52c633
再用命令git tag
查看标签:
git tag
还可以创建带有说明的标签,用-a
指定标签名,-m
指定说明文字:
git tag -a v0.1 -m "version 0.1 released" 1094adb
用命令git show <tagname>
可以看到说明文字:
git show v0.1
操作标签
如果标签打错了,也可以删除:
git tag -d v0.1
如果要推送某个标签到远程,使用命令git push origin <tagname>
:
git push origin v1.0
一次性推送全部尚未推送到远程的本地标签:
git push origin --tags
搭建git服务器
1.安装git
:
sudo apt-get install git
2.创建一个git
用户,用来运行git
服务:
sudo adduser git
3.创建证书登录:
收集所有需要登录的用户的公钥,就是他们自己的id_rsa.pub文件,把所有公钥导入到/home/git/.ssh/authorized_keys文件里,一行一个。
4.初始化Git仓库:
先选定一个目录作为Git仓库,假定是/srv/sample.git
,在/srv
目录下输入命令:
sudo git init --bare sample.git
Git就会创建一个裸仓库,裸仓库没有工作区,因为服务器上的Git仓库纯粹是为了共享,所以不让用户直接登录到服务器上去改工作区,并且服务器上的Git仓库通常都以.git
结尾。然后,把owner改为git
。
$ sudo chown -R git:git sample.git
5.禁用shell登录:
出于安全考虑,第二步创建的git用户不允许登录shell,这可以通过编辑/etc/passwd
文件完成。找到类似下面的一行:
git:x:1001:1001:,,,:/home/git:/bin/bash
改为:
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
这样,git
用户可以正常通过ssh使用git,但无法登录shell,因为我们为git
用户指定的git-shell
每次一登录就自动退出。
6.克隆远程仓库:
现在,可以通过git clone
命令克隆远程仓库了,在各自的电脑上运行:
git clone git@server:/srv/sample.git
管理公钥
如果团队很小,把每个人的公钥收集起来放到服务器的/home/git/.ssh/authorized_keys
文件里就是可行的。如果团队有几百号人,就没法这么玩了,这时,可以用Gitosis来管理公钥。