前言
Git 在生产工作中是使用频率很高的工具,但我发现很多文章只是对它做了简单的提交命令说明,真正遇到 版本冲突或 文件丢失 等问题又定位不到原因,浪费大量时间。本篇文章较长,但都是在实际项目中用到的点。
阅读本文大概需要6分钟
@[toc]
1.版本控制
1.1.什么是版本控制
版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。除了项目,你可以对任何类型的文件进行版本控制。
1.2.为什么版本控制
采用版本控制系统(VCS)是个明智的选择。 有了它就可以将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。 使用版本控制系统就算你对项目删除、修改错误,这也没有关系,你也照样可以很容易地就恢复到原先的样子。但额外增加的工作量却微乎其微。
1.3.本地版本控制
许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。而且不利于团队协作。
为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。图片来源 Git 官网。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VaOie3Fy-1593163259795)(https://static01.imgkr.com/temp/0290a168494d45e78ac618547785a09a.png)]
其中最流行的一种叫做 RCS,现今许多计算机系统上都还看得到它的踪影。 甚至在流行的 Mac OS X 系统上安装了开发者工具包之后,也可以使用 rcs
命令。 它的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。
1.2.集中化的版本控制
接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作? 于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS
)应运而生。 诸如 CVS
、Subversion(SVN
) 以及 Perforce
等。
集中化的版本控制系统是单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。如图(来源 Git 官网):
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gB5jAkgx-1593163259802)(https://static01.imgkr.com/temp/9b50cae4ff91436faf2a4ce66e9372cd.png)]
相对本地版本管理,集中化的版本控制每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。
它也有如下诟病:
- 单点故障
如果宕机,谁都无法提交更新,也就无法协同工作。 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。
- 需要联网
为什么需要联网?集中化的版本控制系统
仓库集中在一台服务器,也就受到服务器网络环境的影响。
1.2.分布式版本控制
于是分布式版本控制系统(Distributed Version Control System,简称 DVCS
)面世了。 Git
就是典型的分布式版本控制。还有 Mercurial
、Bazaar
以及 Darcs
等。
客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。图片来源 Git 官网。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ORRy1qEU-1593163259804)(https://static01.imgkr.com/temp/1093734883a94b9ca524fe3765997873.png)]
分布式版本控制系统的优势不单是不必联网这么简单,后面我们还会看到 Git 极其强大的分支管理等功能。
2.认识 Git
2.1.Git 简史
2002 年,Linux
内核开源项目整个项目组启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。
2.2.Git 与其他版本控制系统区别
集中式的缺点:集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快。
- 分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库。
比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
- 和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库。
某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。
在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
2.2.1.Git 和其他版本控制系统的存储区别
Git的存储方式是 快照技术
,而其他版本控制系统的存储基本上都是 增量存储
。以下图片来自网络。
2.2.1.1.快照技术
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iUqlWxYF-1593163259808)(https://static01.imgkr.com/temp/552da6c37c8444a7891da729ffcfc8a9.png)]
Git在每次 git add
即将内容添加到 缓存区
时会进行一次快照,快照
就像给当时的整个目录及文件照了一张相,在任何时候通过快照就能将目录及文件恢复到发起快照点的状态。Git 是这样生成快照的,对于没有变化的文件,会生成一个引用指向原文件的位置以节省空间提高效率,对于变化了的文件则将整个文件存储。git每个版本存储的是一个快照。
2.2.1.2.增量存储
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YwdgU57E-1593163259811)(https://static01.imgkr.com/temp/d37764af6543482688e61867634c1724.png)]
所谓 增量存储
,指的是除了第一个版本存储的是每个文件的完整内容,之后的版本存储的是每个文件相对于上一个版本对应文件的变化的内容。
2.3.Git 三种文件状态
Git 在未进行commit
操作之前,存在三种状态:Untracked files
,Changes not staged for commit
及Changes to be committed
,每种状态之间可以随意进行互相转换。了解这三种状态各自所对应的不同情况,能够帮助你方便有效的使用 Git 来管理项目。
在 Git 中,文件状态是个非常重要的概念。
为了更清楚的说明 文件状态
的概念,使用网络上三张图片。
- 初始化一个项目,也就是将项目所在目录纳入Git的管理之下。假设项目目录为hello_world,初始化之后,在目录下新建README.txt文件,接着,使用“git status”查看文件状态,如图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jOANJp4E-1593163259813)(https://static01.imgkr.com/temp/2c73b205df274321b4afa96b4c6b27f7.png)]
- 可以看到,Git友好的标示出README.txt为“Untracked files”,并且提示使用“git add ...”的命令将文件包含到待提交清单中。按照提示,使用“git add README.txt”命令,然后,使用“git status”查看文件状态,如图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EREM9oi2-1593163259815)(https://static01.imgkr.com/temp/5421dbfba2844975b01a930fd5a5818c.png)]
- 文件README.txt状态变成了“Changes to be committed”,也就是说README.txt在暂存区域生成了快照,等待被提交。正如Git所提示的那样,通过“git rm --cached README.txt”命令,可以将文件状态还原为未暂存状态,即回到“Untracked files”文件状态。现在,README.txt已经可以被提交到git目录中了,但是暂时不提交。打开README.txt,向其中加些内容,保存之后,用“git status”查看,返回如图信息:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AyQcZ5w1-1593163259819)(https://static01.imgkr.com/temp/603089354e0542ca922b0741432c7608.png)]
可以看到,除了之前的“Changes to be committed”状态,现在又多了一条“Changes not staged for commit”状态,表明文件已经修改,但是还没有放入暂存区域,也就是没生成快照。如果现在进行commit操作,只是将修改之前的文件快照提交到了git目录,一定记住:只有暂存区域的文件(即:文件状态为“Changes to be committed”)才会被提交。正如提示,通过“git add README.txt”命令将已修改文件更新到暂存区域中,如果想撤销修改,可以使用“git checkout -- README.txt”命令。
3.Git 安装
3.1.Linux 安装
- Centos/RedHat 安装
$ yum install curl-devel expat-devel gettext-devel \
openssl-devel zlib-devel$ yum -y install git-core
$ git --version
git version 1.7.1
Linux 的其他版本系统需要其他方式安装。
3.2.Windows 安装
直接在官网下载。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QUvRilvv-1593163259820)(https://static01.imgkr.com/temp/cf9c3ce193d4460fa7bb454362b4cba6.png)]
另一种是在 Github
,搜索 GitHub for Windows
项目。
4.Git 快速入门
4.1.获取仓库
- 第一种:
新建一个存项目文件夹,在 git bash
执行 git init
,项目文件夹下出现 .git
的子目录。
- 第二种
从远程代码仓库拉去一个现有的:git clone [url]
也可以自定义本地仓库名字 git clone [url] dirName
4.2.完整一次的提交流程
进入 Git 项目目录
cd /myProject
提交所有修改到暂存区
git add .
提交暂存区修改内容到本地仓库
git commit -m "提交描述"
推送到远程仓库
git push
现在就可以拉去 JavaPub 的远程仓库了。
4.3.提交说明
- 忽略文件配置:
.gitignore
文件 - 移除文件:
git rm filename
(从暂存区移除,然后提交) - 查看文件状态:
git status
4.4.推送到远程仓库
- 推送到远程仓库:
git push origin master
推送到远程master
分支 - 如果没有远程仓库,现在想让本地和远程仓库关联,
如下命令添加:git remote add origin <server>
,比如我们要让本地的一个仓库和 Github 上创建的一个仓库关联可以这样 git remote add origin https://github.com/Rodert/test.git
现在就可以将项目推送到远程仓库了。
4.5.提交历史
有时我们需要查询以前的提交历史,使用命令 git log
。
只看某人提交记录
git log --author=bob
4.6.撤销操作
有时你提交过代码之后,发现一个地方改错了,你下次提交时不想保留上一次的记录;或者你上一次的 commit
message的描述有误,这时候你可以使用接下来的这个命令:git commit --amend
。
git commit --amend
取消上一步操作,如 git add
、 git commit
之后。
git reset filename
4.7.分支
分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master
是默认的。在其他分支上进行开发,完成后再将它们合并到主分支上。
不同的版本或系统模块并行开发时,我们一般会单独建立一个分支进行开发,最后再合并到主分支。
- 新建本地分支
git branch test
- 切换到
test
分支
git checkout test
也可以合并上面俩步,git checkout -b feature_x
。
- 切换到 master 分支
git checkout master
- 合并分支 (可能有冲突)
git merge test
- 把新建的分支删掉
git branch -d test
- 另外,也可以把分支推送到远程仓库
git push <远程主机名> <本地分支名>:<远程分支名>
git push origin test:test
声明:参考来源互联网,有任何争议可以留言。站在前人的肩上,我们才能看的更远。本教程纯手打,致力于最实用教程,不需要什么奖励,只希望多多转发支持。