【Git】Git是目前世界上最先进的分布式版本控制系统(没有之一)

Git是什么?——Git是目前世界上最先进的分布式版本控制系统(没有之一)。

最近重新学习了Git,相比以前感觉自己对Git有了全新的认识,于是将学习Git时的笔记整理成文,分享给有需要的朋友。本文面向的读者是了解过Git的,而不是对Git一无所知(即对小白可能有阅读压力)。更适合温习提升阅读。

本文主要介绍Git的工作流程和使用方法。主要内容有:什么是版本控制,搭建Git环境,Git的一些历史背景;本地仓库,远程仓库,仓库的分支管理;

目录

什么是Git

分布式&集中式

Git与Github

Git环境搭建

配置Git

配置文件

忽略特殊文件

Git GUI工具

Git发展历史

本地仓库

创建仓库

文件提交

文件版本前进回退

操作工作区

操作暂存区

标签

远程仓库

分支管理

分支合并冲突

分支实例


什么是Git

Git是什么?——Git是目前世界上最先进的分布式版本控制系统(没有之一)。

版本控制系统:设计师在设计的时候做了很多版本

 

经过了数天去问设计师每个版本都改了些啥,设计师此时可能就说不上来了。这个时候如果能有一个软件能记录每次的文件改动,并且还能协调多用户编辑,那岂不是美滋滋?这个软件应用起来应该像这个样子:

版本

文档名

操作用户

日志

修改时间

1

shejigao.txt

zhangsan

修改标题

2019-10-01 10:10:31

2

shejigao.txt

lisi

删除备注信息

2019-10-01 10:11:49

3

shejigao.txt

lisi

增加了许可协议

2019-10-03 11:31:00

4

shejigao.txt

zhangsan

修改版权信息

2019-10-05 09:32:11

恰好,Git就能实现这样的功能!

分布式&集中式

Linus一直痛恨的CVS及SVN都是集中式的版本控制系统,而Git是分布式版本控制系统,集中式和分布式版本控制系统有什么区别呢?

集中式版本控制系统:

版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活,推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。

集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊。

分布式版本控制系统:

首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。

既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。

和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。

在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。

 

一些后话:

CVS作为最早的开源而且免费的集中式版本控制系统,直到现在还有不少人在用。由于CVS自身设计的问题,会造成提交文件不完整,版本库莫名其妙损坏的情况。同样是开源而且免费的SVN修正了CVS的一些稳定性问题,是目前用得最多的集中式版本库控制系统

除了免费的外,还有收费的集中式版本控制系统,比如IBM的ClearCase(以前是Rational公司的,被IBM收购了),特点是安装比Windows还大,运行比蜗牛还慢,能用ClearCase的一般是世界500强,他们有个共同的特点是财大气粗,或者人傻钱多。

微软自己也有一个集中式版本控制系统叫VSS,集成在Visual Studio中。由于其反人类的设计,连微软自己都不好意思用了。

分布式版本控制系统除了Git以及促使Git诞生的BitKeeper外,还有类似Git的Mercurial和Bazaar等。这些分布式版本控制系统各有特点,但最快、最简单也最流行的依然是Git!

Git与Github

Git是一个分布式版本控制系统,简单的说其就是一个软件,用于记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的软件。

Github(https://www.github.com)是一个为用户提供Git服务的网站,简单说就是一个可以放代码的地方(不过可以放的当然不仅是代码)。Github除了提供管理Git的web界面外,还提供了订阅、关注、讨论组、在线编辑器等丰富的功能。Github被称之为全球最大的基友网站

Git环境搭建

Windows安装

  1. 去Git官网下载:https://git-scm.com/
  2. 安装exe可执行文件
  3. 当安装完毕后在桌面右键可以看到以下内容,表明安装成功:

 

配置Git

  1. 在开始菜单里找到“Git”->“Git Bash”、或者在某个文件夹右键打开“Git Bash Here”,打开一个命令行窗口
  2. 配置用户名和电邮。
    1. git config --global user.name "Your Name"
    2. git config --global user.email "email@example.com"

配置文件

当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中:C:\Users\KYLE\.gitconfig

配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。

配置文件放哪了?每个仓库的Git配置文件都放在.git/config文件中

忽略特殊文件

在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。

不需要从头写.gitignore文件,GitHub已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore

忽略文件的原则是:

  1. 忽略操作系统自动生成的文件,比如缩略图等;
  2. 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
  3. 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

常见规则写法有如下几种:

1)/mtk/               过滤整个文件夹

2)*.zip                过滤所有.zip文件

3)/mtk/do.c           过滤某个具体文件

4) !index.php                  不过滤具体某个文件 

在文件中,以#开头的都是注释。

Git GUI工具

Github for Desktop

  1. Github出品的软件,功能完善,使用方便。
  2. 界面干净,用起来非常顺手,顶部的分支时间线非常绚丽。

 

Source tree

号称是最好用的Git GUI工具。功能丰富,基本操作和高级操作都非常流畅,适合初学者上手。

TortoiseGit

与SVN相似却是针对Git的GUI工具

它与其前辈TortoiseSVN都是非常优秀的开源版本控制客户端软件。

Git发展历史

Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。

Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢?

事实是,在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码

你也许会想,为什么Linus不把Linux代码放到版本控制系统里呢?不是有CVS、SVN这些免费的版本控制系统吗?因为Linus坚定地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,而且必须联网才能使用。有一些商用的版本控制系统,虽然比CVS、SVN好用,但那是付费的,和Linux的开源精神不符。

不过,到了2002年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是Linus选择了一个商业的版本控制系统BitKeeper,BitKeeper(软件系统名)的东家BitMover公司(公司名)出于人道主义精神,授权Linux社区免费使用这个版本控制系统。

安定团结的大好局面在2005年就被打破了,原因是Linux社区牛人聚集,不免沾染了一些梁山好汉的江湖习气。开发Samba的Andrew试图破解BitKeeper的协议(这么干的其实也不只他一个),被BitMover公司发现了(监控工作做得不错!),于是BitMover公司怒了,要收回Linux社区的免费使用权。

Linus可以向BitMover公司道个歉,保证以后严格管教弟兄们,嗯,这是不可能的。实际情况是这样的:

Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下。

Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。

历史就是这么偶然,如果不是当年BitMover公司威胁Linux社区,可能现在我们就没有免费而超级好用的Git了。

上面是对Git的初步认识,接下来开始正式使用Git来管理代码了!Enjoy.^.^.

本地仓库

仓库,英文名repository,又叫版本库,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

 本地仓库的三个操作区域和工作流程:

创建仓库

创建一个仓库

  1. 选择一个合适的地方,创建一个空目录。如果你使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。
  2. 在这个空目录处右键,点击“Git Bush Here”或者“Git GUI Here”。
  3. 通过git init命令把这个目录变成Git可以管理的仓库。

文件提交

交给仓库管理:

  1. 在该文件夹创建你想要让Git管理的文件。强烈建议使用标准的UTF-8编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。
  2. 用命令git add告诉Git,把文件添加到仓库:git add 文件名
  3. 用命令git commit告诉Git,把文件提交到仓库:git commit -m "提交时的说明"。另外运行git status看看当前仓库的状态

 

此时,我们可以解释提交文件到仓库在Git中的执行过程了:

 

  1. 正在编辑的文件存放在工作区,使用git add命令提交到暂存区
  2. 暂存区的文件使用git commit命令提交的仓库存储做真正的存储

 

文件版本前进回退

版本回退前进:

  1. HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。
  2. 版本回退:用git log可以查看提交历史,以便确定要回退到哪个版本。
  3. 重返未来:用git reflog查看命令历史,以便确定要回到未来的哪个版本。

版本回退实例:

1、进行三次提交

2、查看提交历史

3、回退到第一次提交时的内容:

4、前进到以前的最终版本:

操作工作区

丢弃工作区的修改,用命令git checkout -- 文件名

操作暂存区

 

丢弃暂存区中的修改:

 

  1. 用命令git reset HEAD 文件名,就回到了工作区
  2. 再用工作区的丢弃操作即可

 

改名文件,并且将这个改名放入暂存区:git mv [file-original] [file-renamed]

 

标签

发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。

Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支(branch)可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。

Git有commit,为什么还要引入tag?

  1. “请把上周一的那个版本打包发布,commit号是6a5819e...”
  2. “一串乱七八糟的数字不好找!”
  3. 如果换一个办法:
  4. “请把上周一的那个版本打包发布,版本号是v1.2”
  5. “好的,按照tag v1.2查找commit就行!”
  6. 所以,tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。

 

  • 命令git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个commit id;
  • 命令git tag -a <tagname> -m "blablabla..."可以指定标签信息;
  • 命令git tag可以查看所有标签。

标签:就是给某个commit设置容易记住且有意义的名字;

对分支创建标签

  1. 切换到需要打标签的分支上:git branch <name>
  2. 打标签:git tag <name>
  3. 查看所有标签:git tag

对以前的commit打标签:

  1. 先得到历史提交的commitID(git log --pretty=oneline --abbrev-commit)
  2. 再打标签:git tag <name> commitID
  3. 查看某个标签:git tag <tag_name>

操作标签

  1. 删除本地(即未提交到远程/GitHub)的标签:git tag -d <标签名>
  2. 删除已经提交了远程的标签:
  3. 先从本地删除:git tag -d <标签号>
  4. 然后,从远程删除。删除命令也是push,但是格式如下: git push origin :refs/tags/标签号

远程仓库

  • 内网仓库
  • GitHub
  • Gitee

使用步骤:

  1. 在合适的文件夹内,右键,打开Git命令行窗口,使用clone指令克隆线上仓库到本地:git clone 线上仓库地址
  1. 自己写完代码后的提交操作:git push
  2. 拉取别人写的代码更新操作:git pull
  3. 在每天工作的第一件事就是先git pull拉取线上最新的版本;每天下班前要做的是git push,将本地代码提交到线上仓库。

本地仓库上传至远程仓库(基于SSH协议):

 

  1. 建立连接SSH key:ssh-keygen -t rsa -C "kyleshawe@outlook.com"
  2. 关联远程仓库:git remote add origin git@github.com:michaelliao/learngit.git  注意:git@后面的完全取决于你的github的网址,然后追加".git";
  3. 将本地仓库推送至github:git push -u origin master (首次使用);git push origin master

 

分支管理

什么是分支:

在开发的时候往往是团队协作,多人进行开发,因此光有一个分支是无法满足多人同时开发的需求的,并且在分支上工作并不影响其他分支的正常使用,会更加安全,Git鼓励开发者使用分支去完成一些开发任务。

分支相关指令(增删改查):

  1. 创建分支:git branch 分支名
  2. 删除分支:git branch -d 分支名
  3. 合并某分支到当前分支:git merge 被合并的分支名
  4. 查看分支:git branch
  5. 创建+切换分支:git checkout -b 分支名
  6. 切换分支:git checkout 分支名

分支合并冲突

 

冲突的产生原因:

 

  1. 现在本地仓库文件a.txt的版本为V100。我提交到远程仓库后,该文件在远程仓库的版本为V100。
  2. 某位同事拉取了版本为V100的a.txt文件,做了修改,并提交到远程仓库,此时版本为V101。
  3. 此时,我也对a.txt文件进行了修改,提交时则会有冲突。此时我这里的版本是V101,远程仓库的版本理应是V100,由此提交失败,有冲突产生。

 

解决冲突:

 

  1. 先把自己的修改内容做个备份
  2. 执行git pull,拉取远程仓库上的最新代码。
  3. 再根据最新的代码进行修改,也即基于现在最新的代码上重新写
  4. 教训:上班第一件事先git pull,可以在一定程度上避免冲突的产生。

 

分支实例

分支合并

  1. 在已有master分支的基础上,创建一个dev分支:git checkout -b dev
  2. 查看当前分支:git branch  (当前分支前面会标一个*号。)在当前分支上做了修改,添加(git add <file>)并提交(git commit -m <message>);
  3. 切换回master分支:git checkout master
  4. 把dev分支的工作成果合并到master分支上:git merge dev
  5. 合并完成后,就可以放心地删除dev分支了:git branch -d dev

BUG临时分支:

  • 背景:在一个abab分支上进行自己的工作时,突然要去处理BUG;则需要保存现在的abab分支,然后去处理BUG;
  1. 把当前工作区储藏:git stash
  2. 转至BUG所在的分支:git checkout <BrunchName>
  3. 修改完毕后,添加(git add <file>)提交(git commit -m <message>)
  4. 回到master分支,合并分支:git merge --no-ff -m <message> <BrunchName>
  5. 回到自己的abab分支:git checkout dev
  6. 显示工作现场:git stash list
  7. 恢复工作现场:一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;另一种方式是用git stash pop,恢复的同时把stash内容也删了

Feature分支:

  • 背景:临时添加需求,然后又取消了需求;
  1. 新需求名为featureA(在分支dev下):git checkout -b featureA
  2. 开发完毕:git add <file>; git commit -m "featureA finished."
  3. 切回dev,准备(还未合并)合并:git checkout dev
  4. 就在此时,接到上级命令,因经费不足,新功能必须取消!虽然白干了,但是这个包含机密资料的分支还是必须就地销毁:git branch -D featureA;(由于没有被merge,所以-D删除后就找不回了)

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值