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>,同时使用暂存区中文件更新工作区。