git 高级操作
概述
本文介绍使用 git
版本控制系统过程中所涉的一部分高级操作命令。
查看提交记录
命令 git log
可以查看全部提交记录信息,而借助于命令 git show
,我们可以查看单个提交记录、区间提交记录的具体信息。
单个提交记录
对于提交记录而言,它们使用 <commit-id>
进行标识 (<commit-id>
实际为 SHA-1
散列值),因此我们可使用命令 git show <conmmit-id>
查看指定提交记录的具体信息。由于 <commit-id>
往往很长且难于记忆,所以 Git 提供快捷方式:允许使用不少于 4 个字符的 SHA-1
散列值代替 <commit-id>
,如果该散列值仅能对应到一个 <commit-id>
,则查询成功,否则查询失败。针对图例,等价命令可以是:git show f58af6ceb89e5e00
、git show f58a
。
借助于命令
git log --abbrev-commit --oneline
,Git 可为提交记录显示简短而唯一的SHA-1
散列值,默认截取<commit-id>
前 7 个字符。
除上面这种查看方式外,Git 仍提供其他多种方式拥有查看特定分支的提交信息:
如果特定提交记录为某分支的顶端提交,则可使用该分支名表示此提交记录,针对上图例中提交,我们可使用等价命令
git show 250
。使用工具工作之时,Git 会在本机本地的后台保存一个引用日志 (reflog),它用于记录
HEAD
和各分支所指向的提交记录。命令git reflog
可用于查看这些信息:那么
HEAD
和各分支对提交记录就存在一一对应关系,使用命令git show HEAD@{2}/250@{2}
可用于查看HEAD
或分支250
所指向的倒数第 2 个提交记录。借助于特殊字符
^<num>
,我们可以查看特定提交记录的第<num>
个父提交记录信息。例如:命令git show f58a^
用于查看f58a
所示提交记录的第 1 个父提交记录信息;命令git show f58a^2
用于查看f58a
所示提交记录的第 2 个父提交记录信息。第
<num>
个父提交记录仅对于分支合并所产生的提交记录有用。对于该记录而言,它的第 1 个父提交记录位于合并分支之上,第 2 个父提交记录位于被合并分支之上。借助于特殊字符
~<num>
,我们可以查看特定提交记录的祖父级提交记录信息,例如:命令git show f58a~/f582~1
与命令git show f58a^
具有相同作用,均用于查看f58a
所示提交记录的父提交记录信息;命令git show f58a~2
用于查看f58a
所示提交记录的父提交记录的父提交记录信息。默认均指代第 1 父提交记录。
区间提交记录
区间提交记录可用于解决问题 “某分支还有哪些提交记录尚未合并至特定分支?”。它共有三种语法:
双点
命令
git log <branchA>..<branchB>
用于查看在分支<branchB>
中且不在分支<branchA>
中的提交记录。多点
为弥补双点命令不能作用于多个分支,多点命令被提出。它使用
<branchA>
表示在分支<branchA>
、使用^<branchA>/--not <branchA>
表示不在分支<branchA>
,从而提供多分支支持。命令
git log <branchA> <branchB> ^<branchC>
或命令git log <branchA> <branchB> --not <branchC>
用于查看在分支<branchA>
或在分支<branchB>
且不在分支<branchC>
中的提交记录。三点
命令
git log <branchA>...<branchB> --left-right
用于查看被两分支之一包含且不被两分支同时包含的提交记录。借助于参数--left-right
,输出结果将标识哪些提交记录仅出现于哪个分支。
交互式暂存
交互式暂存 Git 命令可用于将项目文件的特定部分组合为一次提交。换言之,如果我们修改大量文件后,希望将这些改动拆分为若干提交而非一次提交,使用交互式暂存命令将会很容易做到这一点。
使用命令 git add -i/--interactive
后,我们将进入交互式终端模式。该模式界面比较特殊,它显示了已暂存文件区和未暂存文件区,同时下方列出可执行的命令。
如果希望列出交互式暂存状态,可在 What now>
提示符后键入 1
、s
或 status
。
如果希望暂存文件,可在 What now>
提示符后键入 2
、u
或 update
,随后选择文件对应数字以待暂存此文件 (数字前有 *
表示文件处于待暂存状态),如果某次待暂存文件集为空,则表示暂存文件工作完成。
如果希望取消暂存文件,可在 What now>
提示符后键入 3
、r
或 revert
,随后操作与暂存文件过程类似。
如果希望添加未追踪未经,可在 What now>
提示符后键入 4
、a
或 add untracked
。
如果希望暂存指定文件的特定部分,可在 What now>
提示符后键入 5
、p
或 patch
,随后选择待部分暂存文件对应数字,接下来 Git 会根据修改部分一一询问是否暂存。
如果希望查看已暂存文件 (指代真实位于暂存区的文件) 与暂存文件 (指代 staged
列表中文件)的区别,可在 What now>
提示符后键入 6
、d
或 diff
,随后选择待查看文件对应数字即可。
贮藏与清理
当对某分支的若干文件进行部分改动、且想要切换到另一个分支完成其他事宜时,按照 Git 使用规程,我们必须提交此次修改,然后才能完成分支切换,否则报如下错误。如果不想单独为此创建一次提交,我们可使用命令 git stash
加以解决。
命令 git stash
或命令 git stash push
用于将工作目录中未完成的修改 (包括已暂存和未暂存的已追踪文件) 保存至 Git 栈中,同时你可在任何分支中应用这些修改。
命令 git stash list
用于查看所有保存至 Git 栈中的修改列表。
命令 git stash apply [--index] [stash@{<num>}]
用于将修改 stash@{<num>}
应用于当前分支。如果不使用参数 --index
,则将所有改动恢复至工作区;如果使用参数 --index
,则将暂存区改动恢复至暂存区、工作区改动恢复至工作区。如果不添加参数 stash@{<num>}
,默认应用栈顶修改。,需要注意的是:如果当前分支相应内容已经修改,可能会发生合并冲突。
命令 git stash drop [stash@{<num>}]
用于从 Git 栈中删除指定修改 stash@{<num>}
。
命令 git stash pop
用于应用栈顶修改并从 Git 栈中删除之。
命令 git stash
存在若干变种,我们简单介绍一二:
git stash --keep-index
该命令不仅将工作目录中未完成的修改保存至 Git 栈中,同时将已暂存文件仍然保留在暂存区中。
git stash --include-untracked
该命令不仅将工作目录中未完成的修改保存至 Git 栈中,也会将未追踪文件保存至 Git 栈中。
git stash branch <new branchname>
创建新分支,并将栈顶修改应用至该分支,随后丢弃栈顶修改。
如果希望删除工作目录中未追踪文件或文件夹,可使用命令 git clean -d -f
(-f
表示强制删除)。为防止错删,可先行执行命令 git clean -d --dry-run
,它会列出将要删除的文件和文件夹。
搜索
Git 提供两个工具用于快速从其数据库中搜索指定内容。
命令 git grep <searchContent>
用于从工作目录中搜索指定内容,同时显示该内容所在文件名。该命令存在若干参数可以选择:
-n
用于显示搜索内容在相应文件中的行号。
-c/--count
搜索结果的统计信息,包括指定内容出现在哪些文件,指定内容在这些文件中出现的次数。
-p/--show-function
命令 git log -S <searchContent>
用于从提交记录中搜索指定内容。
重置
重置操作可用于任意切换仓库区中的历史版本,它具体通过命令 git reset
实现。
在具体说明命令 git rest
之前,简单回顾 Git 仓库:它由三部分组成 —— 工作区、暂存区、仓库区。借助于命令 git add
,工作区文件可转至暂存区;借助于命令 git commit
,暂存区文件转至仓库区。仓库区由一系列提交记录所组成,这些记录构成一个有向无环图。所谓分支便是一个指向提交记录的指针,HEAD
指针则指向当前分支。
命令 git reset <commit-id>
主要有三个版本:
git reset --soft <commit-id>
该命令仅会调整当前分支使其指向特定提交记录,从而切换仓库区中当前版本为某特定历史版本。
git reset [--mixed] <commit-id>
命令
git reset
默认使用参数--mixed
,除git reset --soft <commit-id>
所完成的工作外,该命令会使用仓库区中<commit-id>
所示提交记录的快照更新暂存区。git reset --hard <commit-id>
除
git reset --mixed <commit-id>
所完成的工作外,该命令会使用暂存区中内容更新工作区。
除使用 <commit-id>
执行重置外,还可根据文件或文件夹路径进行重置。由于此时可能涉及多个提交记录,因此仓库区中内容不会发生变化 (也即 git reset --soft
所指代过程不会发生) 。具体涉及如下命令:
git reset [--mixed] <commit-id> <file>
此命令使用
<commit-id>
所指代提交记录更新暂存区中的文件<file>
。如果命令中
<commit-id>
具体为HEAD
,则其等价于取消对文件<file>
的暂存。git reset --hard <commit-id> <file>
此命令使用
<commit-id>
所指代提交记录更新暂存区中的文件<file>
,同时使用暂存区中文件更新工作区。