版本控制
在介绍Git之前,我们先了解一下什么是版本控制,具体可参考版本控制
Git概述
Git历史
同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代。Linux 内核开源项目有着为数众广的参与者。绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到 2002 年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,于是整个项目组开始启用分布式版本控制系统 BitKeeper 来管理和维护代码。
到 2005 年的时候,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了免费使用 BitKeeper 的权力。这就迫使 Linux 开源社区(特别是 Linux的缔造者 Linus Torvalds )不得不吸取教训,只有开发一套属于自己的版本控制系统才不至于重蹈覆辙。他们对新的系统订了若干目标:
速度
简单的设计
对非线性开发模式的强力支持(允许上千个并行开发的分支)
完全分布式
有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)
Git是什么
Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
官网地址为:https://git-scm.com/
Git特点
优点:
适合分布式开发,强调个体;
公共服务器压力和数据量都不会太大;
速度快、灵活;
任意两个开发者之间可以很容易的解决冲突;
离线工作。
缺点:
代码保密性差,一旦开发者把整个库克隆下来就可以完全公开所有代码和版本信息;
权限控制不友好;如果需要对开发者限制各种权限的建议使用SVN。
Git与SVN的区别
SVN是集中式版本控制系统,而Git是分布式版本控制系统,Git与SVN的区别可参考Git与SVN的区别
Git工作流程
一般工作流程如下:
从远程仓库中克隆 Git 资源作为本地仓库;
从本地仓库中checkout代码然后进行代码修改;
在提交本地仓库前先将代码提交到暂存区;
提交修改,提交到本地仓库;本地仓库中保存修改的各个历史版本;
在需要和团队成员共享代码时,可以将修改代码push到远程仓库。
Git 的工作流程图如下:
Git的几个核心概念
工作区、暂存区、版本库、远程仓库
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
Workspace:工作区,就是你平时存放项目代码的地方
Index / Stage:暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息
Repository:仓库区(或版本库),就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本
Remote:远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换
分支
每次的提交Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里这个分支叫主分支,即master分支。HEAD指针严格来说不是指向提交,而是指向master,master才是指向提交的。
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:
每次提交,master分支都会向前移动一步,这样随着不断提交,master分支的线也越来越长。
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:
Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!
不过切换到了dev分,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后就剩下了一条master分支:
远程仓库
远程仓库分为公有远程仓库和私有远程仓库。
公有远程仓库
本质和本地仓库无异,只是这个仓库①不在本地②大家可能都知道③需要将代码共享到远程仓库④可以被其他人克隆同步代码等。
一般情况下在企业中会有一个搭建在公司的远程仓库,可以让本公司内部的开发人员同步开发。而业界最富盛名的远程仓库则为github;它上面存放了非常多的开源组织、个人、企业等的开放源码库,任何都可以从上面获取源码。
私有远程仓库
远程仓库实际上和本地仓库一样,纯粹为了7x24小时开机并交换大家的修改。GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护费,那就只能自己搭建一台Git服务器作为私有仓库使用。
GitHub远程仓库
在本地创建了一个Git仓库,又想让其他人来协作开发,此时就可以把本地仓库同步到远程仓库,同时还增加了本地仓库的一个备份。
常用的远程仓库就是github:https://github.com/
Github支持两种同步方式“https”和“ssh”。如果使用https很简单基本不需要配置就可以使用,但是每次提交代码和下载代码时都需要输入用户名和密码。而且如果是公司配置的私有git服务器一般不提供https方式访问。
忽略文件
在工程中,并不是所有文件都需要保存到版本库中的,例如“target”目录及目录下的文件就可以忽略。
在工程中,并不是所有文件都需要保存到版本库中的,例如“target”目录及目录下的文件就可以忽略。在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件或目录。
Git 忽略规则优先级
在 .gitingore 文件中,每一行指定一个忽略规则,Git 检查忽略规则的时候有多个来源,它的优先级如下(由高到低):
从命令行中读取可用的忽略规则当前目录定义的规则父级目录定义的规则,依次递推$GIT_DIR/info/exclude 文件中定义的规则core.excludesfile中定义的全局规则
Git 忽略规则匹配语法
在 .gitignore 文件中,每一行的忽略规则的语法如下:
空格不匹配任意文件,可作为分隔符,可用反斜杠转义开头的文件标识注释,可以使用反斜杠进行转义! 开头的模式标识否定,该文件将会再次被包含,如果排除了该文件的父级目录,则使用 ! 也不会再次被包含。可以使用反斜杠进行转义/ 结束的模式只匹配文件夹以及在该文件夹路径下的内容,但是不匹配该文件/ 开始的模式匹配项目跟目录如果一个模式不包含斜杠,则它匹配相对于当前 .gitignore 文件路径的内容,如果该模式不在 .gitignore 文件中,则相对于项目根目录** 匹配多级目录,可在开始,中间,结束? 通用匹配单个字符* 通用匹配零个或多个字符[] 通用匹配单个字符列表
常用匹配示例
bin/: 忽略当前路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件/bin: 忽略根目录下的bin文件/*.c: 忽略 cat.c,不忽略 build/cat.cdebug/*.obj: 忽略 debug/io.obj,不忽略 debug/common/io.obj 和 tools/debug/io.obj**/foo: 忽略/foo, a/foo, a/b/foo等a/**/b: 忽略a/b, a/x/b, a/x/y/b等!/bin/run.sh: 不忽略 bin 目录下的 run.sh 文件*.log: 忽略所有 .log 文件config.php: 忽略当前路径的 config.php 文件
.gitignore规则不生效
.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。
解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:
git rm -r --cached .git add .git commit -m 'update .gitignore'
你想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore忽略了:
$ git add App.classThe following paths are ignored by one of your .gitignore files:App.classUse -f if you really want to add them.
如果你确实想添加该文件,可以用-f强制添加到Git:
$ git add -f App.class
或者你发现,可能是.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:
$ git check-ignore -v App.class.gitignore:3:*.class App.class
Git会告诉我们,.gitignore的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
Java项目中常用的.gitignore文件
# Compiled class file*.class# Eclipse.project.classpath.settings/# Intellij*.ipr*.iml*.iws.idea/# Maventarget/# Gradlebuild.gradle# Log file*.loglog/# out**/out/# Mac.DS_Store# others*.jar*.war*.zip*.tar*.tar.gz*.pid*.origtemp/
常用Git命令
经常使用 Git ,但是很多命令还是记不住。但要熟练掌握,恐怕要记住40~60个命令,所以整理了一份常用Git命令清单。可以参考Git命令