title: 版本控制之GIT:2.简单使用
categories: Linux
tags:
- GIT
timezone: Asia/Shanghai
date: 2019-02-19
环境
[root@centos181001 ~]# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
[root@centos181001 git]# git --version
git version 2.20.1
使用之前需要先搞清楚 Git
的三种状态
Git 有三种状态,你的文件可能处于其中之一:已提交(committed)、已修改(modified)和已暂存(staged)。
已提交表示数据已经安全的保存在本地数据库中。
已修改表示修改了文件,但还没保存到数据库中。
已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
由此引入 Git 项目的三个工作区域的概念:Git 仓库、工作目录以及暂存区域。
Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。
这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。
工作目录是对项目的某个版本独立提取出来的内容。
这些从 Git仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。
有时候也被称作`‘索引’',不过一般说法还是叫暂存区域。
基本的 Git 工作流程如下:
在工作目录中修改文件。
暂存文件,将文件的快照放入暂存区域。
提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。
如果 Git 目录中保存着的特定版本文件,就属于已提交状态。
如果作了修改并已放入暂存区域,就属于已暂存状态。
如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。 在Git 基础一章,你会进一步了解这些状态的细节,并学会如何根据文件状态实施后续操作,以及怎样跳过暂存直接提交。
1.初次运行 Git 前的配置
既然已经在系统上安装了 Git,你会想要做几件事来定制你的 Git 环境。 每台计算机上只需要配置一次,程序升级时会保留配置信息。 你可以在任何时候再次通过运行命令来修改它们。
Git 自带一个 git config
的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:
1./etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。
如果使用带有 --system 选项的 git config 时,它会从此文件读写配置变量。
2.~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。
可以传递 --global 选项让 Git 读写此文件。
3.当前使用仓库的 Git 目录中的 config 文件(就是 .git/config):针对该仓库。
注意:每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
用户信息
当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址。 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改:
git config --global user.name "xiaoliu"
git config --global user.email [email protected]
再次强调,如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。
很多 GUI 工具都会在第一次运行时帮助你配置这些信息。
2.获取Git仓库
有两种取得 Git 项目仓库的方法。 第一种是在现有项目或目录下导入所有文件到 Git 中; 第二种是从一个服务器克隆一个现有的 Git 仓库。
在现有目录中初始化仓库
## 如果你打算使用 Git 来对现有的项目进行管理,你只需要进入该项目目录并输入:
## 该命令将创建一个名为 .git 的子目录
## 这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。
## 但是,在这个时候,我们仅仅是做了一个初始化的操作,你的项目里的文件还没有被跟踪。
## 初始化仓库
git init
## 添加*.c文件到暂存区
git add *.c
## 添加LICENSE文件到暂存区
git add LICENSE
## 提交更改到Git仓库,-m是添加本次提交的备注
git commit -m 'initial project version'
克隆现有的仓库
## 如果你想获得一份已经存在了的 Git 仓库的拷贝
## 比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 git clone 命令。
## Git 克隆的是该 Git 仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件。
## 当你执行 git clone 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。
## 事实上,如果你的服务器的磁盘坏掉了,你通常可以使用任何一个克隆下来的用户端来重建服务器上的仓库
## 虽然可能会丢失某些服务器端的挂钩设置,但是所有版本的数据仍在。
## 克隆仓库的命令格式是 git clone [url] 。
## 比如,要克隆 Git 的可链接库 libgit2,可以用下面的命令:
git clone https://github.com/libgit2/libgit2
git clone https://github.com/libgit2/libgit2 mylibgit
## 这会在当前目录下创建一个名为 “libgit2” 的目录,并在这个目录下初始化一个 .git 文件夹
## 从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。
## 如果你进入到这个新建的 libgit2 文件夹
## 你会发现所有的项目文件已经在里面了,准备就绪等待后续的开发和使用。
Git 支持多种数据传输协议。
上面的例子使用的是 https:// 协议
不过你也可以使用 git:// 协议或者使用 SSH 传输协议,比如 user@server:path/to/repo.git 。
3.记录每次更新到仓库
现在我们手上有了一个真实项目的 Git 仓库,并从这个仓库中取出了所有文件的工作拷贝。 接下来,对这些文件做些修改,在完成了一个阶段的目标之后,提交本次更新到仓库。
请记住,你工作目录下的每一个文件都不外乎这两种状态:已跟踪或未跟踪。
已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区。
工作目录中除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。
初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态。
1.检查当前工作目录文件状态
git status
## 此命令会显示以下信息
## 1.当前工作目录是否有未被追踪的新文件
## 2.当前工作目录是否有被修改但是未提交的文件
## 3.显示当前分支,默认分支名为:master
git status -s
[root@centos181001 git]# git status -s
M 3.txt # 红色空格M:文件被修改、没有add、没有commit
D 4.txt # 红色空格D:已删除文件、没有commit
?? 5.txt # 红色??:新文件、没有add、没有commit
[root@centos181001 git]# git status -s
M 3.txt # 绿色M:文件被修改,位于暂存区、没有commit
D 4.txt # 红色空格D:已删除文件、没有commit
A 5.txt # 绿色A:新文件、位于暂存区、没有commit
2.跟踪新文件(提交文件到暂存区)
git add 1.txt
## 可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区
## 还能用于合并时把有冲突的文件标记为已解决状态等。
## 将这个命令理解为“添加内容到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。
## 未跟踪的文件意味着 Git 在之前的快照(提交)中没有这些文件
## Git 不会自动将之纳入跟踪范围,除非你明明白白地告诉它“我需要跟踪该文件”
## 这样的处理让你不必担心将生成的二进制文件或其它不想被跟踪的文件包含进来。
## 执行git add命令后会将文件提交到暂存区
## 此命令支持通配符比如git add *或者git add *.txt
## 此命令使用文件或目录的路径作为参数
## 如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。
3.提交更新(将暂存区提交到Git仓库)
git commit
git commit -v
git commit -m '本次提交说明'
## 需要先使用git add命令将文件提交到暂存区,然后才可以使用以下命令提交
## 第一种命令格式会启动文本编辑器以便输入本次提交的说明。
## 默认会启用 shell 的环境变量 $EDITOR 所指定的软件,一般都是 vim 或 emacs。
## 当然也可以,使用 git config --global core.editor 命令设定你喜欢的编辑软件。
## 第二种命令格式会详细记录本次修改内容,会将你所做的改变的 diff 输出放到编辑器中
## 第三种命令格式将备注和命令放到一行
## 每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。
## 注意:如果先git add后又修改了某文件,那在执行git commit的时候,只会将执行git add时候的状态提交到Git仓库,而不会提交执行git add之后又修改的新状态。
4.跳过使用暂存区域直接commit
尽管使用暂存区域的方式可以精心准备要提交的细节,但有时候这么做略显繁琐。 Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit
加上 -a
选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add
步骤:
git commit -a
5.删除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。
git rm 1.txt
git rm -f 1.txt
git rm --cached 1.txt
git rm log/\*.log
git rm \*~
## git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。
## 命令2:git rm -f 1.txt
## 如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f(译注:即 force 的首字母)。
## 命令3:git rm --cached 1.txt
## 另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。
## 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。
## 当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆文件添加到暂存区时,这一做法尤其有用。
## 为达到这一目的,使用 --cached 选项:
## 命令4:git rm log/\*.log
## 注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式
## 所以我们不用 shell 来帮忙展开。
## 此命令删除 log/ 目录下扩展名为 .log 的所有文件。
## 命令5:git rm \*~
## 命令为删除以 ~ 结尾的所有文件。
6.移动文件
不像其它的 VCS 系统,Git 并不显式跟踪文件移动操作。 如果在 Git 中重命名了某个文件,仓库中存储的元数据并不会体现出这是一次改名操作。 不过 Git 非常聪明,它会推断出究竟发生了什么,至于具体是如何做到的,我们稍后再谈。
要在 Git 中对文件改名,可以这么做:
git mv file_from file_to
## 其实,运行 git mv 就相当于运行了下面三条命令:
mv README.md README
git rm README.md
git add README
## 执行此命令时会自动将本地文件重命名,我们直接提交即可。
7.忽略文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。 来看一个实际的例子:
cat .gitignore
*.[oa]
*~
## 第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。
## 第二行告诉 Git 忽略所有以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。
## 文件 .gitignore 的格式规范如下:
## 所有空行或者以 # 开头的行都会被 Git 忽略。
## 可以使用标准的 glob 模式匹配。
## 匹配模式可以以(/)开头防止递归。
## 匹配模式可以以(/)结尾指定目录。
## 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
## 所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。
## 星号(*)匹配零个或多个任意字符
## [abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c)
## 问号(?)只匹配一个任意字符;
## 如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配
## (比如 [0-9] 表示匹配所有 0 到 9 的数字)。
## 使用两个星号(*) 表示匹配任意中间目录
##比如`a/**/z` 可以匹配 a/z, a/b/z 或 `a/b/c/z`等。
GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,你可以在 https://github.com/github/gitignore 找到它.
8.查看已暂存和未暂存的修改
如果 git status
命令的输出对于你来说过于模糊,你想知道具体修改了什么地方,可以用 git diff
命令。 稍后我们会详细介绍 git diff
,你可能通常会用它来回答这两个问题:当前做的哪些更新还没有暂存? 有哪些更新已经暂存起来准备好了下次提交? 尽管 git status
已经通过在相应栏下列出文件名的方式回答了这个问题,git diff
将通过文件补丁的格式显示具体哪些行发生了改变。
git diff
git diff --cached
git diff --staged
## 第一条命令:显示已修改但是还没有提交到暂存区的修改内容(没有执行git add)
## 第二条命令:显示已提交到暂存区(执行过git add)但是还没有commit的修改内容
## 第三条命令:等同于第二条命令,在Git 1.6.1 及更高版本中提供
4.查看提交历史
在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的工具是 git log 命令。
git log
git log -p
git log -p -2
git log --stat
git log --pretty=oneline
git log --pretty=format:"%h - %an, %ar : %s"
git log --pretty=format:"%h %s" --graph
git log 的常用选项
--shortstat 只显示 --stat 中最后的行数修改添加移除统计。
--name-only 仅在提交信息后显示已修改的文件清单。
--name-status 显示新增、修改、删除的文件清单。
--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
--relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。
--graph 显示 ASCII 图形表示的分支合并历史。
限制 git log 输出的选项
-(n) 仅显示最近的 n 条提交
--since, --after 仅显示指定时间之后的提交。
--until, --before 仅显示指定时间之前的提交。
--author 仅显示指定作者相关的提交。
--committer 仅显示指定提交者相关的提交。
--grep 仅显示含指定关键字的提交
-S 仅显示添加或移除了某个关键字的提交
第一条命令:git log
默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面。
第二条命令:git log -p
一个常用的选项是 -p,用来显示每次提交的内容差异。
你也可以加上 -2 来仅显示最近两次提交:
第四条命令:git log --stat
该选项除了显示基本信息之外,还附带了每次 commit 的变化。
--stat 选项在每次提交的下面列出所有被修改过的文件、有多少文件被修改了以及被修改过的文件的哪些行被移除或是添加了。
在每次提交的最后还有一个总结。
第五条命令:git log --pretty=oneline
这个选项可以指定使用不同于默认格式的方式展示提交历史。
这个选项有一些内建的子选项供你使用。
比如用 oneline 将每个提交放在一行显示,查看的提交数很大时非常有用。
另外还有 short,full 和 fuller 可以用,展示的信息或多或少有些不同
git log --pretty=oneline
git log --pretty=short
git log --pretty=full
git log --pretty=fuller
第六条命令:git log --pretty=format:"%h - %an, %ar : %s"
可以定制要显示的记录格式。
这样的输出对后期提取分析格外有用 — 因为你知道输出的格式不会随着 Git 的更新而发生改变
选项 说明
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 --date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按多久以前的方式显示
%s 提交说明
第七条命令:git log --pretty=format:"%h %s" --graph
当 oneline 或 format 与另一个 log 选项 --graph 结合使用时尤其有用。
这个选项添加了一些ASCII字符串来形象地展示你的分支、合并历史:
这种输出类型会在我们下一章学完分支与合并以后变得更加有趣。
来看一个实际的例子,如果要查看 Git 仓库中,2008 年 10 月期间,Junio Hamano 提交的但未合并的测试文件,可以用下面的查询命令:
git log --pretty="%h - %s" --author=gitster --since="2008-10-01" \
--before="2008-11-01" --no-merges -- t/
附录:
源码下载1:https://mirrors.edge.kernel.org/pub/software/scm/git/
源码下载2:https://www.kernel.org/pub/software/scm/git
源码下载3:https://github.com/git/git/releases。
git官网:https://git-scm.com/
git官网中文文档:https://git-scm.com/book/zh/v2