为什么学Git
在现在的真实企业开发中,项目一般是由很多程序员一起协同开发的,而协同开发所使用的工具一般就是Git
。使用Git
进行协同开发有很多好处:代码备份
、代码还原
、协同开发
、追责透明
等。并且大部分开源项目都是通过Git进行管理的,学习Git还可以参与一些开源项目的维护。总而言之,Git操作是程序员必备的技能!
Git是什么
版本控制
代码的每一次修改(提交)都定义一个版本。通过控制版本从而管理代码。
集中式版本控制
集中式版本控制工具,版本库是集中存放在中央服务器
中的,开发人员需要开发时,从中央服务器下载代码,修改代码后提交到中央版本库,此时就在中央版本库中产生了一个新的版本。这个过程是需要联网的。集中版本控制存在一些问题:
依赖网络连接:开发人员必须时刻保持与中央服务器的连接
才能进行提交、更新等操作。一旦网络出现问题,就无法继续工作或同步最新的代码变更。
单点故障风险:所有的版本都在中央服务器中,假如该服务器出现故障,可能会导致版本信息损坏或者丢失。
性能问题:假如项目扩大,频繁从中央服务器获取最新版本
代码或者推送更改
都会导致性能下降,影响效率。
代表性的集中式版本控制工具是SVN
和CVS
,但这两个工具早已过时。
分布式版本控制
分布式版本控制系统没有“中央服务器”,每个人的电脑都是一个完整的版本库,这样工作时就无需联网了,版本库就在本地电脑上。多人协作只需要将各自的修改推送给对方
,就可以互相看到对方的修改了。(但是这种方式使用较少,还是通过共享版本库
进行的协作开发。)
Git是一个分布式版本控制工具
,也是最具代表性、应用最广泛的分布式版本控制工具,开发者是Linux系统开发团队
,此处不做过多介绍。
Git工作流程
clone(克隆):从远程仓库中克隆代码到本地仓库。
checkout(检出):从本地仓库中检出一个仓库分支然后进行修订(切换使用的分支)。
add(添加):从工作区提交代码到本地仓库时,先将代码提交到暂存区(Index)。
commit(提交):从暂存区提交代码到本地仓库。本地仓库中也可以保存修改的各个历史版本。
fetch(抓取):从远程仓库抓取代码到本地仓库,不会进行任何版本合并,使用较少(一般是直接使用pull)。
pull(拉取):从远程仓库直接将代码拉取到本地仓库,并进行自动合并(merge),然后将其放在工作区(虽然pull
操作可以直接将代码放在工作区,但并非是直接到工作区的)。
push(推送):修改完成之后,需要和团队成员共享代码,需要将代码推送到远程仓库,然后团队其他开发者可以从远程仓库中pull
最新的代码,从而协作开发。
这些差不多就是在实际开发中Git
的工作流程了,下面会详细介绍Git
的使用。
GitBash操作Git
Windows系统
的电脑一般是使用GitBash
操作Git
的,所以说本文也是根据GitBash
进行讲解的。GitBash就像一个小的Linux操作系统
,可以理解为一个用来操作Git的Linux,在使用GitBash的时候会用到部分Linux操作命令。
准备工作
下载安装本文就不讲解了,可以去这个地址下载:Git - Downloads,建议选择默认安装。安装成功后单击鼠标右键就可以看到:
说明安装Git
成功,然后点击Open Git Bash here
,就可以打开GitBash进行git操作。
基本配置
用户信息
安装好Git之后,首先需要做的事情是设置用户名和Email地址,这是非常重要的,每次Git提交都会使用到该用户信息,这也是为什么Git能够方便追责的原因。需要在GitBash
中输入:
git config --global user.name “your username”
git config --global user.email “your email”
如图所示,成功配置了用户名和Email地址,可以通过以下命令查看配置的结果:
git config --global user.name
git config --global user.email
为常用指令配置别名
上文提到,使用GitBash和Linux有很多相通之处。在GitBash中有很多常用指令,这些指令有很多参数,每次使用这些指令都需要输入大量参数,这是很麻烦的,所以说可以使用别名
。
1.在Windows的用户目录中创建.bashrc文件,推荐在GitBash中使用touch
命令创建:
2.在.bashrc文件中输入以下内容:
#用于输出git提交日志
alias git-log='git log --pretty=oneline --all --graph --abbrev-commit'
#用于输出当前目录所有文件及基本信息
alias ll='ls -al'
3.添加到环境变量中:打开GitBash,执行source ~/.bashrc
命令。
GitBash还可以配置一些其他设置,此处就不做扩展。
获取本地仓库
要使用Git对我们的代码进行版本控制,首先需要获得本地仓库。可以在电脑中的任意位置创建一个空目录作为Git的本地仓库(建议是空目录,不是空目录也可以);然后在GitBash中执行命令git init
,这个命令就是将这个目录初始化为一个git本地仓库
,执行成功后就可以在本地看到隐藏的.git
目录,这就是git本地仓库:
Git本地操作
Git
在本地操作的过程如图所示:
当前的目录就是工作区,当我们在工作区中新建一个文件时,该文件就属于untracked(未跟踪)状态。此时Git知道有这个文件的存在,但是并未对其进行版本管理。
如图所示,使用git status
命令查询文件修改的状态,可以看见新建的file01.txt文件处于Untracked
状态,此时我们可以通过git add
命令将其添加到暂存区:
在实际开发中,我们一般会将工作区中所有文件都提交到本地仓库交给Git管理(无需Git管理的文件可以在.gitignore文件中
列出),所以说可以直接使用git add .
通配符进行添加。
在暂存区中的文件可以使用git commit
命令将其提交到本地仓库,-m
选项可以为其添加注释(不使用该选项也会让你输入注释的):
提交后我们可以使用git-log
(这是刚才在.bashrc
中配置的别名)查看提交记录:
可见我们成功将file01.txt
文件提交到了master
分支中(分支下文会讲解),成功将file01.txt
文件交给了Git
进行管理。
当我们对一个已经跟踪后的文件修改,那么该文件就会变成unstaged(未暂存)状态,此时仍然需要我们使用git add
将其添加到暂存区:
此时修改file01
的内容:
该文件已经是跟踪后,所以说此时是未暂存状态:
使用git add
将其加入暂存区:
发现file01
此时已经是待提交状态了,表明已经暂存了。(那个警告的内容是因为我在Windows系统上使用了vi编辑器,目前阶段可以忽略这个问题)。
此时我们再次使用git commit
将其提交到本地仓库:
发现提交日志中,已经有了两个版本了(一个是commit,一个是update),说明Git可以帮助我们管理不同版本!,既然Git可以帮助我们管理版本,我们自然可以使用版本回退
进行版本切换。通过git reset --hard commitID
可以将版本切换到对应的commitID的那个版本(commitID就是git-log提交日志的前面那一串哈希值
):
此时file01.txt
被切换到了修改前,里面是没有内容的,说明我们通过Git
切换版本成功。
我们也可以通过版本切换将版本切换到修改后,首先需要通过git-log
查询修改操作那一次的commitID,但是我们再次查询提交日志,发现更新操作的那一次提交也无法查询到了:
无法知道commitID,自然也就无法切换版本了,但是可以使用git reflog
指令,查看到已经删除的提交记录:
通过git reflog
指令,我们查询到update操作的commitID是409a4ff
,所以说我们就可以根据这个ID,将版本切换到update之后了:
如图所示,版本切换成功,可见Git的能力超乎想象!
.gitignore文件
我们总会有些文件无需纳入Git的管理,也不希望它们总出现在未跟踪文件列表。通常这些文件都是些自动生成的文件,比如日志文件
,或者编译过程中创建的临时文件
等。 在这种情况下,我们可以在工作目录中创建一个名为.gitignore
的文件(文件名称固定,必须是.gitignore,否则无效),列出要忽略的文件模式。下面是一个示例:
# no .a files
*.a
# but do track lib.a, even though you're ignoring .a files above
!lib.a
# only ignore the TODO file in the current directory, not subdir/TODO
/TODO
# ignore all files in the build/ directory
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory
doc/**/*.pdf
.gitignore
文件内容相对固定,忽略的内容也基本一致,一般都是提供好的。
分支
几乎所有的版本控制系统都以某种形式支持分支
。 使用分支意味着我们可以将个人的工作从开发主线上分离,比如从开发主线中分离Bug修改
、新功能开发
等,可以不影响开发主线。分支是Git中相当重要的内容!
查看本地分支
使用git branch
命令查看本地分支:
当前本地只有master
分支,master分支是主分支。
创建本地分支
使用git branch 分支名
可以创建一个新的本地分支:
切换分支
使用git checkout 分支名
可以切换当前使用的分支:
成功从master
主分支切换到了刚才创建的develop01
分支(命令行括号中显示的就是当前分支)。
还可以使用git checkout -b 分支名
创建一个不存在的分支(相当于创建一个新分支):
合并分支
在一个分支上的提交可以合并到另一个分支,这就是Git可以协作开发的最重要的原因,在当前分支中使用git merge 需要合并的分支
就可以将该分支合并到当前分支上:
在develop01分支上修改file01.txt内容:
提交更改:
如图所示,还未更改的develop02
分支和master
主分支还处于上一个版本;而更改后的develop01
分支已经领先于它们一个版本(在提交日志中的版本越靠前越领先),此时我们切换到master分支,将develop01
分支合并上来:
如图所示,成功将develop01
分支合并到了master
上。
(此处触发了Fast-forward快速合并机制:Fast-forward
是 Git 在合并分支时采用的一种简化方式,当目标分支(通常是 main
或 master
)是源分支(例如 feature-branch
)的直接祖先时发生。在这种情况下,Git 不需要创建一个新的合并提交,而是简单地将目标分支的指针向前移动到源分支的最新提交位置。)
删除分支
删除分支时,不能删除当前正在使用的分支,只能删除未使用的其他分支,git branch -d 分支名
,当删除分支时,需要进行各种检查(比如说当前分支还没有合并,就会删除失败);git branch -D 分支名
,删除时不做任何检查,强制删除:
当前使用develop02
分支,则无法删除:
使用git branch -D
强制删除也无法删除:
只能删除未使用的分支:
Git本地冲突
当多分支对文件进行修改时,可能会存在冲突,最常见于两个分支同时修改了同一个文件的同一个位置
,此时就需要手动解决冲突:
master分支修改file01:
develop01分支也修改file01的同一处位置:
此时将develop01
分支合并到master
分支上:
如图所示:合并失败,出现了合并冲突,此时需要我们手动去解决冲突。解决冲突的方式非常简单,我们只需要将冲突的文件修改为希望合并的样子:
因为有合并冲突,所以说file01文件中的内容是这样,此时我们只需要将其修改为我们希望合并后的样子即可解决冲突:
再次提交之后即可完成合并:
这样我们就解决了本地冲突。解决本地冲突的步骤可以概括为:出现冲突后,需要修改冲突文件的内容,将其修改为希望合并后的样子;修改完成后使用git add
和git commit
可以完成合并,成功处理冲突。
分支使用原则与流程
分支在开发中使用十分广泛,一般有以下使用原则与流程:
mater(生产)分支
master
分支是线上分支、主分支;还是一些中小规模的项目作为线上运行时的分支。在开发中,我们一般不会直接操作主分支。
develop(开发)分支
develop
分支是开发分支,是从master分支中创建的分支。一般作为开发部门的主要开发分支,如果没有其他并行开发不同期上线要求,都可以在此版本进行开发,阶段开发完成后,需要是合并到master分支,准备上线。
feature分支
feature
分支是从develop
分支中创建的分支,一般是同期并行开发,但不同期上线时创建的分支,分支上的研发任务完成后合并到develop分支。
hotfix分支
hotfix
分支是从master
分支中派生的分支,一般是作为线上修复bug
使用的分支,将bug修复完成后,将该分支合并到master
、test
、develop
分支。
还有一些其他分支,在此不再详述,例如test分支(用于代码测试)
、pre分支(预上线分支)
等。
总结
从上文可以看出,Git
是一个极其强大的分布式版本管理工具
,其性能强悍、功能完善。本文主要是介绍了Git的本地仓库
,但是Git
是存在两种类型的仓库的——本地仓库
和远程仓库
。我们可以通过互联网中一些代码托管平台来实现,这能更好的帮助我们协作开发。