原创做者,公众号【程序员读书】,欢迎关注公众号,转载文章请注明出处哦。git
最近终于把本身负责的一些很古老的项目从SVN
迁移到了Git
,整个项目线均可以从SVN
中解放出来,不须要在SVN
和Git
之间来回切换使用,所以总算能够静下心来好好学习一下Git
的用法了。程序员
说到Git
,做为程序员的你,在项目开发中必定会使用到或未来也必定会使用到的,可是我相信,不少在使用Git
的人,都只是停留一些简单的操做上,好比提交(commit
)、拉取(pull
)、推送(push
)。github
而对于Git
的工做原理,如何解决Git
的版本冲突以及如何使用Git
进行源码管理等问题可能并无太深的认识,那么接下来,咱们从最基础的开始,一块儿由浅入深来探讨一下。数据库
Git
目前最流行和最强大的开源分布式版本控制管理系统。vim
Git
做者是Linus Torvalds
,这个名字是否是听着很熟,没错,是Linus Torvalds
也是Linux
操做系统的做者。安全
Git
的做者由于很讨厌集中式版本控制管理系统,因此才会想开发分布式版本管理系统,这才有Git
的诞生。bash
Git
开发的初衷也是为了方便Linux
社区更好地管理和维护Linux
系统的代码。服务器
Git
与SVN
之间的比较,也能够看做是分布式版本管理系统
与集中式版本管理系统
的比较,Git
是分布式版本管理系统,而SVN
是集中式版本管理系统。编辑器
对于集中式版本管理系统
而言,版本库是放在远程服务器上的,开发人员经过与服务器上的版本库链接进行代码版本提交,若是没法链接到服务器上,根本没有办法进行代码的版本管理,如:分布式
而分布式版本管理系统,代码提交与版本管理均可以本地进行,没必要连到服务器就能够进行各类版本管理操做。
只有当咱们以为须要与其余人同步代码时,才须要连到其余版本库进行同步操做,以下图所示:
Git
虽然很是强大好用,但其学习难度比SVN
大,虽然上手很容易,只须要学习git add
,git commit
,git push
和git pull
,但要真正学会且能很好地应用于复杂的项目开发管理,其学习周期仍是比较长的,而SVN
则相对比较容易掌握。
Git
的版本库是存储在咱们的本地,因此会占用咱们本地的存储空间,另外,因为Git
版本库包含每一个文件的的副本,所以相比集中式的版本控制管理系统,也会占用更多的存储空间。
Git
是分布式版本控制系统,经过Git
提供的工具集,咱们能够管理本地版本库,并能够将代码提交到远程版本库或拉回其余人提交的版本。
Github
是基于Git
的在线Web
代码托管服务,咱们能够在Github
上建立本身的公有或私有的版本库(私有库要钱的
),并能够经过Web
页面进行管理,而在咱们本地还能够经过Git
与之交互,将代码提交到Github
上面的远程版本库中与团队其余成员共享。
若是咱们对本身的项目源代码的安全性要求更高呢?这时候咱们须要搭建本身的代码托管服务,这时候GitLab
即是很好的选择了。
GitLab
是一套用于搭建咱们本身的私有Web
代码托管服务项目,经过使用GitLab
,咱们能够在本身的服务器上搭建与Github
同样的Web
代码托管服务器,一样,GitLab
也提供同样的Web
页面管理操做。
若是你完成了Git
的安装,那么在使用Git
以前你须要完成一个小小的配置,就是配置用户信息。
Git
的全部配置使用git config
命令来完成,而用户信息只须要配置user.name
和user.email
便可,以下:
# 配置用户名
git config --global user.name '你的用户名'
# 配置邮箱
git config --global user.email '你的邮箱'
复制代码
上面git config
命令用参数--global
指定的配置为全局配置,也就是对全部版本库都会生效,除了--global
外,git config
命令还能够经过--local
、-- system
两个参数来指定配置的级别。
参数 | 说明 |
---|---|
--global | 全局有效 |
--system | 对当前全部登陆的用户有效 |
--local | 对当前版本库有效 |
若是有相同的配置,经过--local
指定的配置优先大于--system
,而--system
的优先级大于--global
。
在git config
后面跟上--list
参数能够查看Git
配置,再指定--global
,--system
,--local
,能够查看不一样级别的配置,如:
git config --list --global
复制代码
git config --list --system
复制代码
git config --list --local
复制代码
若是指定--local
时,当前执行命令的目录必须在一个版本库下,不然会报如下的错误:
fatal: --local can only be used inside a git repository
复制代码
版本库是Git
中最重要的概念,在一个版本库中,包含了当前项目全部的提交。
安好Git
以后,即可以经过Git
提供的命令来建立版本库了,经过版本库,将添加到版本库里面的文件进行版本管理。
先建立目录,再建立版本库
# 建立空目录
$ mkdir test
# 进入空目录
$ cd test
# 初始化版本库
$ git init
复制代码
咱们也能够将上面的的步骤简化为:
$ git init test
$ cd test
复制代码
上面咱们经过git init
命令在本地初始化一个版本库,一种这种称为裸库
,而有时候,咱们会直接经过git clone
命令将远程的版本库克隆到本地,如:
git clone https://www.github.com/test/test.git
复制代码
经过这种方式,咱们能够将远程版本库中项目克隆到本地,当咱们参与一些老的项目时,通常就是采用这种方式来建立本地的版本库。
经过上面的两种方式,咱们已经在本地建立好了版本库,接下来咱们就能够开始将本身的文件添加到版本库了。
首先咱们在工做目录建立名为test.txt
的文件,内容能够随意,好比:
这是我添加到版本库中的第一个文件
复制代码
这时候咱们经过git status
命令查看工做目录的状态,以下所示:
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
test.txt
nothing added to commit but untracked files present (use "git add" to track)
复制代码
能够看到,Git
提示咱们要执行git add <file>
操做,这是将文件到添加Git
的暂存区,咱们执行一下:
# 下面三个命令均可以将test.txt添加到暂存区
git add test.txt
git add .
git add all
复制代码
再使用git status
查看状态,以下表示已经添加到暂时区了。
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: test.txt
复制代码
接下来即是将暂存区中的文件提交到版本库了,使用git commit
命令,后面的-m
表示提示说明。
git commit -m "添加test.txt文件"
复制代码
提交后,结果以下:
[master 23811d4] 添加test.txt文件
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.txt
复制代码
上面结果提示中,23811d4
表示本次的提交的ID
,这个ID
是其实是由40个十进制数字组的SHA1散列值,上面结果中显示只是这个提交ID的前7位值。
这里须要明确几个概念,那就是工做区
、暂存区
、版本库
,该项目全部目录,咱们称为工做区
,而在该目录下,会生成一个.git
的隐藏目录,这个目录咱们称为版本库
,暂存区(stage)
是Git
独有的概念,暂存区
是版本库
的一部分,这三者之间的关系,咱们以下图所示:
若是想把文件从暂存区移除,可能使用下面的命令:
git rm --cached test.txt
复制代码
咱们知道在Git
中,每一个提供都会产生一个40
位十六进制数字组成的SHA1
散列值,而由这些值串成的一条时间线,即是分支,在上面的演示中,咱们一直在Git
的master
分支上。
master
是Git
的默认分支,除了master
外,咱们任意建立本身的分支,分支老是向指最新的提交(commit
),而在Git
版本库中,还保留着一个指针HEAD
,默认指向当前分支,因此分支、HEAD与commit的关系是HEAD
是一个指针,指向当前分支的最新提交(commit
),而且将HEAD
保存在.git/HEAD
文件当中。
经过下面的图,咱们能够更好地理解不一样分支,提交与HEAD
的关系:
在git branch
命令后面跟上分支名
能够基于当前的分支再建立一个新的分支,如:
git branch deveolp
复制代码
git branch
复制代码
执行结果以下:
develop
* master
复制代码
也可使用下面的方式查看分支列表
$ git show-branch
! [develop] develop
* [master] develop
--
+* [develop] develop
复制代码
经过git branch
命令建立好分支后,Git
并不会帮咱们检出该分支,咱们可使用git checkout
命令检出该分支,这样即可以在该分支下进行开发了,如:
$ git checkout develop
复制代码
若是检出的分支不存在,则会报错,好比咱们检出不存在的dev
分支,会报以下所示的错误:
error: pathspec 'dev' did not match any file(s) known to git
复制代码
若是在检出分支不存在时,想基于当前分支直接建立分支,也能够在git checkout
跟上参数-b
,如:
git checkout -b dev
复制代码
这样即可以直接建立分支了,固然,若是分支已经存在,也会报错,好比:
git checkout -b develop
复制代码
因为咱们建立了develop
,所以会报出如下错误:
fatal: A branch named 'develop' already exists.
复制代码
对于不想的分支,可使用git branch -d
命令进行删除,如:
git branch -d develop
复制代码
强制删除
git branch -D develop
复制代码
当咱们开发完成后,从develop
合并到master
,这时的操做应该切到master
分支下,在master
执行合并命令。
git merge develop
复制代码
Git
支持打标签(tag
)的操做,标签有时候也称为里程碑,当咱们开发到必定阶段有必定的成果,咱们能够在当前分支上打上一个标签,好比说咱们在开发到某个阶段时,在分支打上v1.0
的标签,表示1.0
版本已经完成。
在打标签以前,咱们先看一下如何查看全部的标签,如:
$ git tag
v1.0
v1.1
v1.2
v2.3
复制代码
上面的命令会简单显示全部的一个简单的标签列表,若是想查看标签的说明,能够这样
$ git tag -n1
v1.0 develop
v1.1 develop
v1.2 develop
v2.3 develop
复制代码
使用通配符查看本地标签
$ git tag -l v1.*
v1.0
v1.1
v1.2
复制代码
建立标签有如下几种方式:
git tag <tag_name> [commit_id]
git tag -a <tag_name> [commit_id]
git tag -m message <tag_name> [commit_id]
git tag -s <tag_name> [commit_id]
git tag -u <key> <tag_name> [commit_id]
复制代码
不带commit_id
,建立没有说明的tag
:
git tag v1.0
复制代码
使用-a
参数添加标签说明,这种方式会打一个vim
编辑器让咱们输入说明:
git tag -a v1.1
复制代码
在某个commit
之上打标签
git tag v1.2 c22be11
复制代码
Git
标签不容许修改,若是咱们对某个标签不满意,能够删除标签,再从新建立,删除标签语句以下:
git tag -d v1.2
复制代码
在项目开发时,有一些文件咱们不想添加到怎么版本库中进行版本控制,好比IDE
自动生成的配置文件、项目数据库配置文件或者编译后生成的临时目录等等。
这时候咱们能够在工做目录中添加.gitignore
文件来指要忽略哪些目录或文件,并将.gitignore
文件添加到版本库,由于.gitignore
文件须要进行版本控制。
固然,除了经过.gitignore
文件指定忽略文件外,也能够经过命令行直接指定。
在工做区根目录建立.gitignore
文件是最经常使用的方式,这种方式能够控制整个项目的文件。
在某个子目录上建立.gitignore
文件来覆盖上层目录中.gitignore
的忽略规则对当前目录的影响。
当咱们在工做区建立忽略文件后,若是咱们经过push
操做把项目推送到远程版本库,那么忽略文件一样也要推送上去,这里别的开发者也会获得一样的的忽略规则,若是有时候忽略规则只是咱们本地独有的,不想与别人共享,那咱们能够经过下面的方式,配置一个全局的
git config --global core.excludesfile ~/.gitignore
复制代码
在.git/info/exclude
也能够添加忽略规则,这种方式并不经常使用,与全局.gitignore
文件同样,这种方式也是本地独有,并不会与其余开发者共享。
既然能够经过这么多种方式来指定.gitignore
文件,那么不一样的.gitignore
就有不一样的优先级,其优先级由高到低以下所示:
从命令行中读取可用的忽略规则最高
当前目录定义的规则
父级目录定义的规则,依次递推,直到工做区根目录
.git/info/exclude
文件中定义的规则
core.excludesfile
中定义的全局规则
#
:#用于注释说明
*
:通配符,表示任何个字符。
?
:表示一个任何字符。
!
:表示不忽略该文件或目录
/
:/
位置一行开始位置时,表示忽略这个目录下的文件,不忽略其余子目录的同名文件,若是/
位置一行的最后位置,则表示只忽略目录,而同名文件不忽略。
[abc]
:可选的字符范围
示例
# 这是一行注释
a* #忽略任何以a开头的文件和目录
!action # 不忽略action文件
/verdor #忽略根目录下的verdor文件
复制代码
忽略文件只对未跟踪的文件有效果,若是某个文件已经被提交到版本库了,这时候再把文件添加了忽略文件中,也不会有效果了。
其实,不管你是否是一名程序员,均可以把Git
做为管理一个本身文档或代码的工具,经过使用Git
,咱们能够更高效地管理和组织本身的项目和文档,在不断地修改和变动中,也不惧怕文档的丢失。
若是你以为文章不错,欢迎扫码关注,你的关注就是我写做的最大动力