GIT版本控制和常用命令使用介绍
1. 版本控制
1.1 历史背景
同生活中的许多伟大事物一样,Git诞生于一个极富纷争且大举创新的年代。Linux内核开源项目有着为数众广的参与者。
1991-2002年间, 绝大多数的Linux内核维护工作都花在了提交补丁和保存归档的繁琐事务上。
直到2002年,整个项目组开始启用一个专有的分布式版本控制系统BitKeeper来管理和维护代码。
但在2005年,开发BitKeeper的商业公司同Linux内核开源社区的合作关系结束,他们收回了Linux内核社区免费使用BitKeeper的权力。这就迫使Linux开源社区(特别是Linux的缔造者Linus Torvalds)基于使用BitKeeper时的经验教训,开发出自己的版本系统,也就是后来的Git。
Git是目前世界上最先进的分布式版本控制系统,而且是是免费的、开源的,最初Git是为辅助Linux内核开发的,作为一种过渡方案来替代 BitKeeper。
1.2 什么是版本控制
版本控制(Revision control)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。
- 实现跨区域多人协同开发
- 追踪和记载一个或者多个文件的历史记录
- 组织和保护你的源代码和文档
- 统计工作量
- 并行开发、提高开发效率
- 跟踪记录整个软件的开发过程
- 减轻开发人员的负担,节省时间,同时降低人为错误
简单说就是用于管理多人协同开发项目的技术。没有进行版本控制或者版本控制本身缺乏正确的流程管理,在软件开发过程中将会引入很多问题,如软件代码的一致性、软件内容的冗余、软件过程的事物性、软件开发过程中的并发性、软件源代码的安全性,以及软件的整合等问题。
1.3 常见版本控制工具
主流的版本控制器有如下这些:
- Git
- SVN(Subversion)
- CVS(Concurrent Versions System)
- VSS(Micorosoft Visual SourceSafe)
- TFS(Team Foundation Server)
- Visual Studio Online
版本控制产品非常的多(Perforce、Rational ClearCase、RCS(GNU Revision Control System)、Serena Dimention、SVK、BitKeeper、Monotone、Bazaar、Mercurial、SourceGear Vault),现在影响力最大且使用最广泛的是Git与SVN。
Git与SVN最主要的区别:
SVN是集中式版本控制系统,版本库是集中放在中央服务器的。然而编写代码的时候,使用的是自己的电脑,所以首先要从中央服务器得到最新的版本,然后再编写代码。完成工作后,需要把自己编写的代码推送到中央服务器。集中式版本控制系统是必须联网才能工作,对网络带宽要求较高。
Git是分布式版本控制系统,没有中央服务器,每个人的电脑就是一个完整的版本库。编写代码的时候不需要联网了,因为版本都在自己电脑上。协同的方法是这样的:比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
Git是目前世界上最先进的分布式版本控制系统。
1.4 版本控制的分类
-
本地版本控制
记录文件每次的更新,可以对每个版本做一个快照,或是记录补丁文件,适合个人用,如RCS。
-
集中版本控制
所有的版本数据都保存在服务器上,协同开发者从服务器上同步更新或上传自己的修改。
所有的版本数据都存在服务器上,用户的本地只有自己以前所同步的版本,如果不连网的话,用户就看不到历史版本,也无法切换版本验证问题,或在不同分支工作。而且,所有数据都保存在单一的服务器上,有很大的风险这个服务器会损坏,这样就会丢失所有的数据,当然可以定期备份。代表产品:SVN、CVS、VSS。 -
分布式版本控制
所有版本信息仓库全部同步到本地的每个用户,这样就可以在本地查看所有版本历史,可以离线在本地提交,只需在连网时push到相应的服务器或其他用户那里。由于每个用户那里保存的都是所有的版本数据,只要有一个用户的设备没有问题就可以恢复所有的数据,但这增加了本地存储空间的占用。
2 Git介绍
2.1 Git 工作流程
一般工作流程如下:
- 克隆 Git 资源作为工作目录。
- 在克隆的资源上添加或修改文件。
- 如果其他人修改了,你可以更新资源。
- 在提交前查看修改。
- 提交修改。
- 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
可以概括为:
- 从远程仓库中克隆Git资源作为本地仓库,同时从本地仓库中checkout代码
- 提交代码:提交到暂存区–>提交到本地仓库–>代码push到远程仓库
注:
- 1本地仓库中保存修改的各个历史版本
- 代码push到远程仓库,因为需要和团队成员共享代码
2.2 基本概念
- 工作区:workspace。就是你在电脑里能看到的目录,平时存放项目代码的地方。
- 暂存区:stage 或 index。用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表的信息。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
- 本地仓库:Repository。就是安全存放数据的位置,这里面有你提交所有的版本的数据。其中HEAD指向最新放入仓库的版本。
- 远程仓库:Remote。托管代码的服务器,可以简单的认为是你项目组的一台电脑用于远程数据交换。
2.3 文件的四种状态
版本控制就是对文件的版本控制,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。
- Untracked:未跟踪。此文件在文件夹中,但没有加入git库,不参与版本控制,通过git add状态变为Staged。
- Unmodify:文件已经入库,未修改,也就是版本库中的文件快照内容与文件夹中完全一致。这种类型的文件有两种去处,如果它被修改,而变为Modified。如果使用git rm 移出版本库,则变成Untracked。
- Modified:文件已修改,仅仅是修改,并没有进行其他的操作,这个文件也有两个去处,通过git add 可进入暂存staged状态。使用git checkout 则丢弃修改过,返回到unmodify 状态,这个git checkout即从库中取出文件,覆盖当前修改。
- Staged:暂存状态。执行git commit 则将修改同步到库中,这时库中的文件和本地文件又变为一致,文件为Unmodify 状态。执行git reset HEAD filename 取消暂存,文件状态为Modified。
2.4 忽略文件
有时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等,在主目录下建立"gitignore" 文件,此文件有如下规则:
- 忽略文件中的空行或以#符号开始的行将会被忽略
- 可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2})代表可选的字符串等
- 如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略
- 如果名称最前面是一个路径分隔符(/),表示要忽略的文件在此目录下
- 如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录
# 为注释
*.txt 忽略所有 .txt结尾的文件
!lib.txt 但lib.txt除外
/temp 仅忽略项目根目录下的temp文件,不包括其他目录
build/ 忽略build/目录下的所有文件
doc/*.txt 忽略 doc/notes/txt 但不包括doc/server.arch.txt
2.5 Git命令
2.5.1 查看本地git配置命令
#查看全部config
git config -l
#查看系统config
git config --system --list
#查看当前用户全局config
git config --global --list
#设置用户名
git config --global user.name "[名称]"
#设置邮箱
git config --global user.email [邮箱]
2.5.2 远程库信息查看命令
#查看远程库信息
git remote
#远程库详细信息
git remote -v
#查看远程分支
git branch -r , git branch -a
#为远程仓库地址创建别名
git remote add origin https://github.com/sun766/Programming-art.git(此处举例)
#查看当前别名所对应的远程仓库地址
git remote show origin
#从远程仓库获取代码(拉取所有版本到本地)
git clone origin
#删除当前别名所对应的远程仓库地址
git remote remove origin
2.5.3 分支交互命令
#查看分支 (显示结果中 有* 代表当前所在分支)
git branch
#创建分支
git branch 分支名称
#建立本地分支和远程分支的关联
git branch –set-upstream branch-name origin/branch-name
#切换分支(工作区文件内容会立即变化成对应分支的内容 )
git checkout 分支名称
#创建+切换分支,git checkout -b dev,即origin/dev
git checkout -b 分支名称
#更新
git pull
#将远程主机 origin 的 master 分支拉取过来,与本地的 brantest 分支合并
git pull origin master:brantest
#远程分支与当前分支合并,冒号后面的部分可以省略
git pull origin master
#将当前分支推送到远程对应的分支(若远程无对应分支,则推送无效)
git push
#将分支dev提交到远程origin/dev(远程没有则创建, 远程没有dev则创建)
git push origin dev
#如果当前分支与多个主机存在追踪关系,则可以使用 -u 参数指定一个默认主机,这样后面就可以不加任何参数使用git push
#,不带任何参数的git push,默认只推送当前分支,这叫做simple方式,还有一种matching方式,会推送所有有对应的远程分支的本地分支, Git 2.0之前默认使用matching,现在改为simple方式
git push -u origin master
#删除分支 (如果分支没有被合并不允许删除)
git branch -d 分支名称
#删除分支(强制删除分支)
git branch -D 分支名称
#合并某分支到当前分支(当前目录主分支,将来源分支合并到主分支上。合并后来源分支仍然存在)
git merge 来源分支
#合并分支(禁用 Fast forward)
git merge –no-ff -m “描述” dev
#查看分支合并情况
git log –graph –pretty=oneline –abbrev-commit
2.5.4 标签常用命令
#创建标签
##对当前版本建立标签
git tag tagname
##对历史版本建立标签
git tag tagname commit_id
##commit_id 添加说明
git tag -a tagname -m “描述…”
##查看所有标签
git tag
##查看某个标签具体信息
git show tagname
#删除标签
##删除本地标签
git tag -d tagname
#推送标签
##推送本地的某个标签到远程
git push origin tagname
##一次性推送所有分支
git push origin –tags
2.5.5 暂存区命令
# 添加指定文件到暂存区
git add [file1] [file2] ...
# 添加指定目录到暂存区,包括子目录
git add [dir]
# 添加当前目录的所有文件到暂存区
git add .
#用暂存区中的文件覆盖工作目录中的文件
git checkout -- 文件名
#将暂存区中文件删除
git rm --cached 文件名
#查看当前的状态
git status
#提交文件(将暂存区的文件提交到本地git仓库)
git commit -m '添加内容'
git commit -F ~/gitcommit/gitcommit_bug
2.5.6 查看提交历史
Git 提交历史一般常用两个命令:
git log - 查看历史提交记录。
git blame <file> - 以列表形式查看指定文件的历史修改记录。
- git log
--oneline 选项来查看历史记录的简洁的版本
--graph 选项,查看历史中什么时候出现了分支、合并
--reverse 参数来逆向显示所有日志
--author查找指定用户的提交日志 git log --author=Linus
--since/--before 指定日期 git log --oneline --before={3.weeks.ago} --after={2010-04-18}
- git blame < file >
2.5.7 gitk
gitk是git图形化的界面软件版本,对仓库的管理更为直观,不需要在命令行中进行繁琐的控制,将各种信息合理的组织在不同的软件窗口中,让一些很繁琐的操作可以在图像软件中只需要一键获得。合理的结合命令行和图形工具可以大大提高软件开发和分支管理的效率。