《精通git第二版》读书笔记·ch07 git高级命令
《精通git第二版》读书笔记·ch07 git高级命令
选择提交
选择单个提交,可以用SHA-1(简短形式)、分支名、引用日志、祖先引用等方式,具体如下:
- 简短形式的SHA-1。提供不少于4个sha-1字符,且不含歧义时,即可访问单个提交。
- 分支名。当某个分支指向某个提交时,可以用该分支名来引用对应的提交。
git rev-parse <branchname>
可以查看分支对应的提交。 - 引用日志(reflog)。记录了HEAD和分支引用指向的历史,只存在于本地仓库。使用
git reflog
查看。通过@{n}
语法引用日志记录,例如git show HEAD@{5}
。 - 祖先引用。使用
xxx^
指明祖先引用,例如HEAD^
。HEAD^2
则表示第2个父提交(合并时)。~n
表示n个祖先提交。
选择提交区间,可以用双点、多点、三点。
- 双点。选出在一个分支,但是不在另一个分支的提交。例如
git log origin/master..HEAD
。 - 多点。在引用前添加
^
或者--not
表示,不包含此分支的提交。例如git log refA refB ^refC
,表示refA和refB包含,但是refC不含的提交。 - 三点。选择被两个引用包含,但是非共有的提交。例如
git log --left-right master...experiment
。
交互式暂存
修改一组文件后,如果想将改动放到若干个提交,从而确保提交是逻辑上独立的变更集,则可以使用交互式暂存。
git add -i
可以启动交互式暂存终端。通过“补丁”模式,可以暂存文件的部分内容,命令为git add -p|--patch
。
储藏与清理
git stash
命令,储藏工作目录中修改和暂存的文件,将未完成的修改储存在一个栈上,默认不储藏未跟踪的文件。常用命令如下:
1
2
3
4
5
6
7
8
9
10
11
12
git stash [save] # 储藏
git stash save --keep-index # 不要储藏已经暂存的文件
git stash -u # 储藏未跟踪的文件
git stash --patch # 交互式储藏
git stash list # 列出储藏列表
git stash apply [--index] [stash@{n}] # 应用储藏
git stash drop stash@{n} # 移除储藏
git stash pop # 应用并丢弃
git stash branch "xxx" # 创建一个新分支,检出储藏所在提交,重新应用工作并丢弃储藏
git clean
命令,从工作目录移除未被跟踪的文件,与.gitignore
模式匹配的文件不会移除。
1
2
git clean -x
git clean -f -d -n
签名
配置GPG并安装个人密钥。
1
2
gpg --list-keys
gpg --gen-key
配置git。
1
git config --global user.signingkey "xxx"
签署标签。
1
2
3
git tag -s "vxxx" -m "xxx"
git show "vxxx"
git tag -v "vxxx" # 验证签署的标签
签署提交。
1
2
3
4
5
git commit -a -S -m "xxx" # v1.7.9开始
git log --show-signature -1
git merge --verify-signatures # 验证签名,无效时不合并
git merge --verify-signatures -S "xxx" # 对生成的合并提交也签名
如果在流程中使用签名,确保每个人都理解该如何使用!
搜索
git grep
命令,从提交历史或者工作目录查找字符串或正则表达式。
git log
命令,通过提交信息和diff内容查找某个特定的提交。-L
启用行日志搜索,展示代码中一行或者一个函数的历史。
1
2
git log -S"xxx" # 显示字符串变动的提交
git log -L :git_deflate_bound:zlib.c # 查看zlib.c中函数git_deflate_bound的变动
重写历史
在与他人共享代码之前,可以考虑重写历史,但是建议不要操作已经共享的代码。
重写历史的方式如下:
git commit --amend
,修改最近一次提交。- 交互式变基。可以对提交进行修改、重新排序、移除、压缩、拆分。
filter-branch
,改写历史中大量的提交。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
git filter-branch --tree-filter 'rm -f passwords.txt' HEAD # 从整个提交历史删除文件
git filter-branch --subdirectory-filter "xxx" HEAD # 将某个子目录作为项目根目录
# 修改邮箱地址
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "xxx" ]
then
GIT_AUTHOR_NAME="xxx";
GIT_AUTHOR_EMAIL="xxx";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
重置和检出
git有三棵目录树:
- HEAD。当前分支的指针,总是指向分支的最后一次提交,作为下一次提交的父提交。可以看作最后一次提交的快照。
- 索引。即暂存区域,预期的下一次提交。
- 工作目录。可以看作沙盒,编辑区。
git reset
命令,用来移动HEAD分支的指向,更新暂存区域,更新工作区。利用reset命令,可以实现压缩提交。具体为回退后,重新提交。
1
2
3
4
5
git reset --soft "xxx" # 将代码库指向提交xxx
git reset --mixed "xxx" # 移动分支并更新暂存区
git reset --hard "xxx" # 移动分支并更新工作区
git reset --mixed "/xxx" # 路径只更新部分文件
git reset --patch # 一块块的取消暂存
git checkout
命令可以用来检出,移动HEAD自身的指向,用于切换分支,对于工作目录是安全的。带路径时,则会覆盖工作区的文件。
1
2
3
git checkout "branch" # 切换分支
git checkout "xxx" -- "/xxx"
git checkout --patch
未完成……
本文由作者按照 CC BY 4.0 进行授权