git 基本操作
概述
本文介绍使用 git
版本控制系统过程中所涉的各种基本命令。
书写
git
命令时,如果参数使用[]
括起来,则表明其可使用也可不使用;如果参数使用/
进行分隔,则表示两者等价,可任选一个使用;如果某个参数使用<>
括起来,则表明此为一个取值。
获取仓库
通常有两种方式用于获取 git
仓库:
将尚未进行版本控制的本地目录转换为 Git 仓库。
进入到指定的本地目录,执行
git init
命令即可将当前目录转换为git
仓库。从其它服务器克隆一个已存在的 Git 仓库。
使用
git clone <url> [folderName]
命令可将位于url
位置的 Git 仓库克隆至本地,并将其文件夹名更改为folderName
。
git init
命令将会在本地创建一个.git
文件夹,克隆得到的git
仓库中同样存在.git
文件夹。对于git
仓库而言,此文件夹是十分重要的,它存放着当前git
仓库的各种信息。关于此文件夹的详细信息,具体见 git 基本原理。
文件追踪
Git 仓库所在目录中的文件共有五种状态 —— 未追踪 (untracked)、未修改 (unmodified)、已修改 (modified)、已暂存 (staged)、已提交 (commited)。如果一个文件处于未追踪状态,则表明其尚未被 Git 仓库所管理;如果一个文件处于未修改状态,则表明自上次提交后,该文件尚未被修改;如果一个文件处于已修改状态,则表明自上次提交后,该文件已被修改;如果一个文件处于已暂存状态,则表明其位于暂存区;如果一个文件处于已提交状态,则表明其刚被提交。
文件状态间转换关系及所涉操作具体如下图所示 (未修改和已提交其实是一种状态,之所以如此写,希望与上篇文章中所提文件状态保持一致):
首先,我们介绍用于查看文件状态的两个命令:
git status [--short]
此命令用于查看当前目录中各文件所处状态 (如果文件处于未追踪、已修改、已暂存状态,则会列出其文件名)。添加
--short
参数后,该命令将会以一种简洁方式查看当前目录中各文件所处状态。如图所示,输入
git status
命令后,它指出333.txt
处于未追踪状态、222.txt
处于已修改状态、111.txt
处于已暂存状态。git diff [--staged/--cached]
此命令用于查看工作区中文件与暂存区中文件的差异、暂存区中文件与仓库区中文件的差异 (此时需要使用
--staged
参数)。如图所示,输入
git diff
命令后,它就指出工作区中222.txt
与暂存区中222.txt
的差异 (diff
命令输出中,使用a/
、b/
标识不同区内的文件,a
用于标识具有较旧内容的文件,b
用于标识具有较新内容的文件)。
接下来,我们介绍与状态转换相关的命令:
git checkout -- <fileNmae>
此命令用于将处于已修改状态的文件回退为未修改状态的文件,即撤销工作区中文件的已有修改。如此操作,工作区中文件的已有修改将被完全覆盖,并永远不可恢复。
git add
此命令用于将处于未追踪或已修改状态的文件加入暂存区,从而将文件状态转换为已暂存。
此命令通常有三种用法:
git add .
:将当前目录中所有符合条件的文件加入暂存区。git add *.xxx
:将当前目录中满足*.xxx
通配符匹配规则的文件加入暂存区。git add xxx
:将当前目录中指定文件xxx
加入暂存区。
git reset HEAD <fileName>
此命令用于将处于已暂存状态的文件放回至工作区,从而将文件状态转换为已修改。该命令含有与
git add
命令含义刚好相反。git commit[-m "xxx"]
此命令用于将处于已暂存状态的文件提交到仓库区,这便形成一次快照。
如果直接输入
git commit
命令,则其会跳转到编辑器页面,需要你输入提交说明,随后退出编辑器页面以完成提交;如果输入git commit -m "xxx"
命令,则xxx
作为提交说明并完成提交。如果我们希望跳过暂存操作,直接执行提交操作,可使用
git comit -am "xxx"
命令,它等价于git add .,git commit -m "xxx"
命令。如果我们提交完一次快照后,发现若干文件忘记提交获取提交说明书写错误,此时可输入
git commit --amend
命令,它会将暂存区中内容提交至最新快照之中,同时启动编辑器页面,以允许你修改最新快照的提交说明。git rm [-r] [--cached] xxx
如果直接输入
git rm xxx
,则其会将文件xxx
从暂存区中删除,同时删除工作区中文件xxx
。如果输入
git rm --cached xxx
,则其仅会将文件xxx
从暂存区中删除,此时文件状态变更为未追踪 (将文件从暂存区中删除,此操作将等待被提交给仓库区,故而会出现于Changes to be commit
)。参数
-r
表明所删内容为文件夹。如果工作区中文件与暂存区中文件不一致,则系统报错,此时可使用
git rm -f xxx
强制删除,这种操作的后果便是:工作区中修改部分将会永远不可恢复。如果我们直接使用
rm xxx
命令,则其仅会删除工作区中文件xxx
,暂存区中的文件xxx
仍然保留存在。git mv [-r]
此命令用于移动或重命名文件或文件夹。
Git 并不显式跟踪文件移动,为实现跟踪文件移动功能,实际上我们需要借由如下三条命令加以实现:
mv old new,git rm old,git add new
。git rm
命令则是此三者命令的集合版本,可帮助简化跟踪文件移动操作。git
最后我们介绍一下 .gitignore
文件。
对于一个项目而言,当前目录中的编译结果、日志输出等文件都是无需交由 Git 管理的,而且我们也不会希望它们处于未追踪状态,此时便可使用 Git 提供的 .gitignore
文件记录它们。如此操作,Git 便会忽略其中文件。
文件 .gitignore
的格式规范如下:
- 所有空行或者以
#
开头的行都会被 Git 忽略。 - 可以使用标准的 glob 模式(正则表达式的阉割版) 匹配,它会递归地应用在整个工作区中。
- 匹配模式可以 (/) 开头防止递归。
- 匹配模式可以 (/) 结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上叹号 (!),以示取反。
.gitignore
所匹配文件集合应当为:前四条规范所示集合取并集,随后与第五条规范所示集合取交集 (个人理解)。假定存在 .gitignore
文件如下:
1 | *.a |
此文件表示忽略除 lib.a
以外的所有以 .a
结尾的文件。
.gitignore
位于哪个文件夹之中,它就仅对此文件夹中所有文件起作用。网址 https://github.com/github/gitignore 提供针对数十种项目及语言的
.gitignore
文件模板。
历史记录
我们可使用 git log
命令获取已提交的历史记录,其默认按照时间顺序排列。对于每条历史记录而言,它会列出此次记录的 SHA-1 校验值、提交人、提交人的电子邮件、提交时间及提交说明。
对于 git log
命令而言,它存在很多参数可以选择,我们在此列出若干经常使用的参数:
-p/--patch
使用此参数后,除显示基本记录信息外,它还会显示每次提交所引入的差异 (类似于
git diff 当前记录 上次记录
)。-<n>
此参数用于限制显示的历史记录条数。如果输入
git log -2
命令,它将仅显示最近的两条历史记录。另外还有若干用于筛选历史记录的参数,我们在此简单介绍一二:
--since=<date>
,筛选时间节点date
之后的历史记录;--until=<date>
,筛选时间节点date
之前的历史记录。--stat
使用此参数后,除显示基本记录信息外,它还会显示每次提交的一些统计信息。
--pretty
此参数存在若干选值:
online
、short
、full
、fuller
等,选择不同选值,可以不同于默认格式的方式显示历史记录。如果输入
git log --pretty=online
命令,它会简化记录信息,并将每个记录放在一行进行显示。此参数存在一个特殊选值
format
,它允许自定义显示方式 (具体比较麻烦,点到为止)。--graph
使用此参数后,除显示基本记录信息外,它狐疑在日志旁以 ASCII 图形显示分支与合并历史。
远程仓库
远程仓库是指托管在因特网或其他网络中你的项目的版本库。借助于远程仓库,我们可方便实现多人合作项目开发。
为完成协作开发,我们需要管理此远程仓库。此节首先给出管理仓库命令之间的关系,随后详细介绍他们。
git remote [-v]
此命令用于查看你所配置的远程服务器名。如果使用参数
-v
,则不仅可看到远程服务器名,也可看到远程服务器的具体 URL。git remote
命令除查看配置的远程服务器信息外,也可执行与远程服务器配置相关的若干功能。git remote add <serverName> <serverUrl>
:添加远程服务器。git remote show <serverName>
:显示指定远程服务器的详细信息。git remote rm <serverName>
:删除指定远程服务器。git remote rename <oldserverName> <newserverName>
:指定远程服务器重命名。
git fetch <serverName>
此命令用于从远程服务器
serverName
中拉取本地仓库中所没有的数据。需要注意的是:该命令只会拉取数据至本地仓库,而不会将其合并至工作区。git pull
命令不仅会拉取数据至本地仓库,同时将其合并至工作区。git push <serverName> <branch>
此命令用于将本地仓库当前分支推送至远程服务器
serverName
的branch
分支。
其他操作
与其他版本控制系统一样,Git 可以给本地仓库历史记录中的某一个提交打上标签,以示其重要性。实际使用中,人们常用此功能标记发布的不同版本。
我们这里介绍与标签相关的若干命令:
git tag [-l/--list "通配模式"]
此命令用于查看已有标签,其按照字母顺序列出。如果添加参数
-l
,则其会列出与通配模式匹配的标签。git tag ...
Git 支持两种标签 —— 轻量标签和附注标签。轻量标签只是某个特定提交的引用;附注标签则是存储于 Git 数据库中的完整对象,它包含打标签者的姓名、打标签者的电子邮件、打标签日期及标签信息 (可以看到,附注标签信息与提交快照信息基本一致)。通常情况下,建议使用附注标签。
git tag <tagName>
命令用于创建最新提交的轻量标签;git tag -a <tagName> -m <tagMessage>
命令则用于创建最新提交的附注标签。如果需要对以往提交打标签,则需使用
git tag <tagName> <以往提交的校验和>
或git tag -a <tagName> -m <tagMessage> <以往提交的校验和>
命令。git show <tagName>
此命令用于显示指定标签对应的详细信息。
git push <serverName> [<tagName>/--tags]
默认情况下,
git push
命令并不会将标签信息传送至远程服务器。创建完标签后,我们需要显式推送标签至远程服务器。git push <serverName> <tagName>
便可做到这件事。如果希望一次性推送很多标签,可使用
git push <serverName> --tags
命令,它会将远程服务器中不存在的标签全部传送过去 (两种标签都会传送过去)。git tag -d <tagName>
此命令用于删除指定标签。
此命令仅会删除本地仓库中的标签,而不会删除远程服务器中的标签 (如果远程服务器中有此标签的话),为删除远程服务器中的标签,我们可使用
git push <serverName> :refs/tags/<tagName>
(将冒号前的空值推送至远程服务器中的指定标签名) 或git push <serverName> --delete <tagName>
。git checkout <tagName>
此命令用于查看特定标签所指代的文件版本。此命令会使得本地仓库处于
detachecd HEAD
状态,它会存在一定副作用。
由于某些命令比较复杂,具体使用比较繁琐,Git 提供 别名 功能以允许用户自定义简洁命令以替代复杂命令。我们在此举一个例子:git config --global alias.unstage 'reset HEAD'
,它将 unstage
定义为 reset HEAD --
的别名。以往取消暂存区文件至工作区,需要使用命令 git reset HEAD <fileName>
,现在可使用命令 git unstage <fileName>
。