阅读完需:约 12 分钟
承接上篇关于Git的文章,这一次来具体的说一下Git的基本操作方式:
Git基本理论
工作区和暂存区
和 Svn 有很大的不同,Git 中引入了暂存区/缓存区 (Stage/Index) 的概念,如下图:
- 工作区很好理解,就是我们能看到的工作目录,就是本地的文件夹。
- 这些本地的文件夹我们要通过 git add 命令先将他们添加到暂存区中。
- git commit 命令则可以将暂存区中的文件提交到本地仓库中去。
在 Svn 中我们都是直接将文件提交到版本仓库中去,而在 Git 中,则多了一层关卡。
完整的流程图:
工作流程
git的工作流程一般是这样的:
1、在工作目录中添加、修改文件;
2、将需要进行版本管理的文件放入暂存区域;
3、将暂存区域的文件提交到git仓库。
因此,git管理的文件有三种状态:已修改(modified),已暂存(staged),已提交(committed)
基本操作
创建工作目录与常用指令
工作目录(WorkSpace)一般就是你希望Git帮助你管理的文件夹,可以是你项目的目录,也可以是一个空目录,建议不要有中文。
日常使用只要记住下图6个命令:
初始化仓库
仓库的初始化有两种方式:一种是直接从远程仓库克隆,另一种则是直接从当前目录初始化。
本地仓库搭建
# 在当前目录新建一个Git代码库
$ git init
执行后可以看到,仅仅在项目目录多出了一个.git目录,关于版本等的所有信息都在这个目录里面。
克隆远程仓库
# 克隆一个项目和它的整个代码历史(版本信息)
$ git clone [url] # https://gitee.com/kuangstudy/openclass.git
——————————————————————————————————————–
文件的四种状态(额外拓展)
版本控制就是对文件的版本控制,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。
- 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
——————————————————————————————————————–
查看仓库(文件)状态
我们可以通过 git status
命令来查看仓库中文件的状态,比如,在我们仓库刚刚初始化完成之后,我们执行 git status
命令,执行效果如下:
#查看指定文件状态
git status [filename]
#查看所有文件状态
git status
# git add . 添加所有文件到暂存区
# git commit -m "消息内容" 提交暂存区中的内容到本地仓库 -m 提交信息
执行结果首先展示了我们当前处于 master 分支下,然后又说暂时没有东西可以提交,因为当前仓库中还没有记录任何文件的任何状态。此时,我在当前目录下创建一个名为 git01.txt 的文件,然后再执行 git status
命令,如下:
此时执行结果中显示有一个未被追踪的文件就是我们刚刚添加的 git01.txt ,这个表示该文件目前并未被 git 仓库所管理,所以接下来我们要将这个文件添加到暂存区。
添加文件到暂存区
git add
命令可以将一个文件添加到暂存区,我们现在已经有一个 git01.txt 文件了,接下来,执行如下命令将文件添加到暂存区中:
$ git add git01.txt
文件添加到暂存区之后,我们再执行 git status
命令,可以看到如下结果:
文件提交到暂存区之后,我们看到此时的状态已经发生了变化。
提交到本地仓库
当文件提交到暂存区之后,此时我们可以通过 git commit
命令将当前暂存区的文件提交到本地仓库,如下:
注意,执行 commit 命令时,我们需要加上提交备注,即 -m 参数,提交成功之后,我们再执行 git status 命令,结果如下:
此时一切又恢复宁静了,没有需要 add 的东西,也没有需要 commit 的东西。
如果我们要写的备注非常多,我们可以直接执行 git commit 命令,此时会自动打开一个 vi 编辑器,我们直接在编辑器中输入备注信息即可。假设我在 git01.txt 中随意添加一行内容,然后依次执行 git add、git commit 命令,此时系统会自动打开一个 vi 编辑器,如下:
如图所示,我们在vi编辑器中按照既定的格式编辑内容,编辑完成之后保存退出,此时文件就 commit 成功了。如果在备注信息编辑的过程中我们不想提交了,则直接删除备注信息,保存退出,此时提交就终止了,如下:
提交成功之后,我们可以通过如下命令修改提交备注:
git commit --amend
运行该命令,会自动打开vi编辑器,此时我们可以重新编辑上次提交的备注信息。
查看提交日志
通过 git log
命令我们可以查看以往仓库中提交的日志,比如提交的版本号、提交者、提交者邮箱、提交时间、提交备注等信息,如下:
有的时候我们要查看的命令并不用这么详细,可以在 git log
后面加上 --pretty=short
,这样显示出来的就只是简略信息了:
此时显示出来的是我们这个仓库中的所有日志信息,如果我只想查看某一个文件的提交日志,在 git log
后面加上文件名即可。如下:
如果我还想查看提交时文件的变化,加上 -p 参数即可,如下:
绿色的 + 表示新增的行,红色的 – 表示删除的行(当然这里没有删除的行)。
但是 git log
有一个局限性,就是不能查看已经删除的 commit 的日志,举个例子:下班了,我发现今天下午提交的代码全都是有问题的,于是做了一个版本回退,回退到今天早上的状态,然后关机回家,第二天来了后我发现搞错了,其实那些代码都是 OK 的,于是我又想让仓库版本前进到昨天下午的状态,却发现 git log 命令查看不到昨天下午提交的版本号。此时,我们可以使用 git reflog
命令来实现这一个请求, git reflog
命令可以显示整个本地仓库的 commit , 包括所有 branch 的 commit , 甚至包括已经撤销的 commit , 只要 HEAD 发生了变化, 就会在 reflog 里面看得到,而 git log 只显示当前分支的 commit ,并且不显示删除掉的 commit。如下图:
查看更改前后的差异
使用 git diff
命令我们可以查看工作区和暂存区的区别以及工作区和最新提交的差别。我往 git01.txt 文件中再添加一行 hello world ,此时执行 git diff
命令,结果如下:
此时这里显示我们新增了一行。此时我们执行 git add 命令,将文件提交到暂存区,然后再执行 git diff ,如下:
此时没有任何信息输出,因此此时工作区的内容和暂存区的内容已经保持一致了。但是此时工作区和本地仓库中最新提交的内容还是不一致,我们可以通过 git diff HEAD
命令来查看,如下:
此时我们需要执行 git commit 命令将暂存区中的文件提交,提交成功之后,再执行 git diff HEAD
命令,则又恢复宁静了。如下:
压缩提交历史
git rebase -i
命令可以实现提交历史的压缩。比如我们在开发某一个功能时,提交了很多次,当所有功能都写完时,想将这些提交压缩为一个,就可以使用该命令。
该命令执行之后,会自动打开一个vi编辑器,在vi编辑器中将最新提交的日志的 pick 改为 fixup 即可。压缩之后,最新一次的提交日志就没了,但是数据还在。
关于提交的忽略文件
有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等
在主目录下建立”.gitignore”文件,此文件有如下规则:
- 忽略文件中的空行或以井号(#)开始的行将会被忽略。
- 可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,…})代表可选的字符串等。
- 如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。
- 如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。
- 如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。
#为注释
*.txt #忽略所有 .txt结尾的文件,这样的话上传就不会被选中!
!lib.txt #但lib.txt除外
/temp #仅忽略项目根目录下的TODO文件,不包括其它目录temp
build/ #忽略build/目录下的所有文件
doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt