git show-branch
git show-branch显示分支和提交的版本情况,下面示例图可以参考此脚本生成。
- 输出分为上下两部分,使用若干个短划线
-分隔。两个分支使用两个短划线-,三个分支使用三个短划线-,依次类推,最多不超过29个分支。 - 上半部分为层次缩进的分支列表,下半部分为commit列表。
- 上半部分的分支列表中,使用
*标识当前分支,其他分支使用!标识(不同的分支的!标识颜色不一样)。分支前的标识符*或者!一直垂直贯通到下半部分,这一垂直列的符号都是属于这个分支的。 - 下半部分的commit列表中,前导的符号有
*、+和-号:*表示这一列上的分支(当前分支)有此commit。+表示这一列上的分支(非当前分支)有此commit。-表示这是一次合并操作。
- 标识符的颜色只是用于容易区分列,一个分支一个颜色,如图。
git show-branch! [br1] v15-br1 ! [br2] v12-br2 ! [br3] v13-br3 * [master] merge br2 into master---- - [master] merge br2 into master + * [br2] v12-br2 + * [br2^] v11-br2 + * [br2~2] v10-br2+ * [br1] v15-br1+ * [br1^] v14-br1+ * [br1~2] v7-br1 +* [br3] v13-br3 +* [br3^] v5-br3 * [master~3] v9-master * [master~4] v8-master * [master~5] v6-master +* [master~6] v4-br3 ++* [master~7] v3-br2+++* [master~8] v2-br1 |
git cat-file
可以使用git cat-file命令去查询特定对象的信息,并常与git ls-tree和git ls-files -s命令一起使用。git cat-file参数说明:
-t: 显示对象的类型。-s: 显示对象的大小。-e: 如果对象存在且有效,返回值为0。-p: 根据对象的类型,格式化打印对象内容。
git cat-file -t 34948cfcommit git cat-file -p 34948cftree df43c4f968f9329b7498b86eabb66a45229f21e2parent 90e415d6b6efa80d74c8fe7ec528b560fa0777f6author yuweijun <yuweijun@live.com> 1502198776 +0800committer yuweijun <yuweijun@live.com> 1502198776 +0800v9-master git cat-file commit 34948cftree df43c4f968f9329b7498b86eabb66a45229f21e2parent 90e415d6b6efa80d74c8fe7ec528b560fa0777f6author yuweijun <yuweijun@live.com> 1502198776 +0800committer yuweijun <yuweijun@live.com> 1502198776 +0800v9-master git ls-tree 34948cf100644 blob 626799f0f85326a8c1fc522db584e86cdfccd51f v1.txt100644 blob 8c1384d825dbbe41309b7dc18ee7991a9085c46e v2.txt100644 blob 29ef827e8a45b1039d908884aae4490157bcb2b4 v3.txt100644 blob c694117fd4e76c22ae04348c15861413019aa03b v4.txt100644 blob 9c0be88a7ecb5f679fe637f1b69838f6b46227d3 v6.txt100644 blob a00f43e3090a7d141b8d181468197f2f5e979040 v8.txt100644 blob cc406030c5d3ed8c4491977a8391e0d5c5850f89 v9.txt git cat-file -t a00f43eblob git cat-file blob a00f43ev8 |
git ls-files -s100644 626799f0f85326a8c1fc522db584e86cdfccd51f 0 v1.txt100644 e338b86593faf8b676070731c784a5493c8e98b2 0 v10.txt100644 882cecb02f7b120a45f2fd624811562095b35d1c 0 v11.txt100644 dae199aecb18022d9c525b7af95f6cd1bb44f43a 0 v12.txt100644 a2680a75e29da0261ba8354de83dd09ed700aa2e 0 v13.txt100644 958b5a36e1fad087be8e389960a6a09c50217c47 0 v14.txt100644 75701b22948d38da9f21cdaa720bd8ab26c4286d 0 v15.txt100644 8c1384d825dbbe41309b7dc18ee7991a9085c46e 0 v2.txt100644 29ef827e8a45b1039d908884aae4490157bcb2b4 0 v3.txt100644 c694117fd4e76c22ae04348c15861413019aa03b 0 v4.txt100644 47e5d40a50f8db1524f5308633ae3f0d1de58619 0 v5.txt100644 9c0be88a7ecb5f679fe637f1b69838f6b46227d3 0 v6.txt100644 02a819f21d4c6b8b8b26c4a840bfd54a99872bc1 0 v7.txt100644 a00f43e3090a7d141b8d181468197f2f5e979040 0 v8.txt100644 cc406030c5d3ed8c4491977a8391e0d5c5850f89 0 v9.txt |
git rev-parse
如果你想知道某个分支指向哪个特定的sha-1码(如HEAD),或者想看某个提交对应的sha-1码,你可以使用一个叫做rev-parse的git探测工具。
示例
git rev-parse HEAD@{"2 days ago"}96dea4282684bb249b4bb0e5964f9c8b2717bf27 |
帮助手册
git help rev-parse |
rev-parse是为了底层操作而不是日常操作设计的,rev-parse的帮助手册里一些关于版本定位的一些表示方式如下:
版本号表示及示例
@, shortcut forHEAD.<refname>@{<date>}, e.g. master@{yesterday}, HEAD@{"5 minutes ago"}, HEAD@{5.minutes.ago}<refname>@{<n>}, e.g. master@{1}@{<n>}, e.g. @{1}@{-<n>}, e.g. @{-1}<branchname>@{upstream}, e.g. master@{upstream}, @{u}<rev>^, e.g. HEAD^, v1.5.1^0<rev>~<n>, e.g. master~3<rev>^{<type>}, e.g. v0.99.8^{commit}<rev>^{}, e.g. v0.99.8^{}<rev>^{/<text>}, e.g. HEAD^{/"fix nasty bug"}:/<text>, e.g. :/"fix nasty bug":/^foo, search with regular expression<rev>:<path>, e.g. HEAD:README, :README, master:./README:<n>:<path>, e.g. :0:README, :README
提交的版本范围
<rev>: Include commits that are reachable from (i.e. ancestors of)<rev>,当前命令从<rev>版本(包括此版本)开始操作。^<rev>: Exclude commits that are reachable from (i.e. ancestors of)<rev>,从<rev>版本开始排除命令范围在外,这里注意:- 在提交版本号前的
^符是版本排除的作用,表示取反操作; ^在版本号之后是表示父提交版本。git log ^HEAD^ HEAD,HEAD所能到达的所有提交,减去其第一个父提交所能到达的所有提交。git log HEAD^..HEAD,含义同上。
- 在提交版本号前的
<rev1>..<rev2>: Include commits that are reachable from<rev2>but exclude those that are reachable from<rev1>. When either<rev1>or<rev2>is omitted, it defaults toHEAD,版本<rev2>能到达的版本号中排除<rev1>能到达的版本号,即<rev2>和<rev1>版本之间的集合差,主要用于比较分支之间的提交差别。<rev1>...<rev2>: Include commits that are reachable from either<rev1>or<rev2>but exclude those that are reachable from both. When either<rev1>or<rev2>is omitted, it defaults toHEAD,这是二个提交版本的并集再减去二者的交集,过滤后剩下的版本是2个版本互相缺失的那些提交。<rev>^@: e.g.HEAD^@, A suffix^followed by an at sign is the same as listing all parents of<rev>(meaning, include anything reachable from its parents, but not the commit itself),包含除了<rev>之外的所有它的祖先提交。<rev>^!, e.g.HEAD^!A suffix^followed by an exclamation mark is the same as giving commit<rev>and then all its parents prefixed with^to exclude them (and their ancestors),与上面刚好相反,仅只包括<rev>这一提交,但不包括其祖先提交。查看以下示例观察运行结果:git log HEAD^!git log HEADgit log HEAD^@
提交范围示例
git rev-list br1..br299812dcc3c700d044df84b1456d90fdd073ad92c849a0578c735f18182d7d587a1aaca381b9ca01bc3644e4c3af3705bfbc90751571551a328093bad8a1e833c512a1fc5d5592b7838b07226fb121a87 |
上面输出的4个提交都是在br2分支上的,而br1分支没有这些提交。
git log br1...br2b15012622287ee05af6ad288d218f1d13ad2526a7422cecd9c4c38ac64f4c58e0f664c4297928d913d040d06546df6eb9c8b5ac8343d759f74bc3d253c04f6148226468c197c53bac362769f8457ead9c1341c3453570ad06883df4b02f13ebe2c12d3b799812dcc3c700d044df84b1456d90fdd073ad92c849a0578c735f18182d7d587a1aaca381b9ca01bc3644e4c3af3705bfbc90751571551a328093bad34948cf11e372cf26107a1278042ff891f57b1ac90e415d6b6efa80d74c8fe7ec528b560fa0777f6265c7df31b9d9b40b68c0205e76f720b283f1de55886c7ae151cc431c87e3cc9654f369315e35e94c5f69516d0b0740904b51879224ad65a86f6cdd28a1e833c512a1fc5d5592b7838b07226fb121a87 |
输出的提交包含了2部分,一部分是br1分支所能到达而br2分支不能到达的提交,另一部分正好相反。
git rev-list
根据条件显示所有提交版本号。
根据日期来查询相应的版本号
git rev-list -n 2 --before="Aug 1, 2017 00:00:00" master git rev-list -n 3 --before="2017-05-08 15:51:12" master |
显示指定分支上文件的版本号
git rev-list master -- filename |
git show branch:filename
显示指定分支的文件内容,不用切到指定分支,直接查看该分支下的指定文件的内容。
git show master:index.html |
git log
跟踪指定文件的文件名和内容变化。
git log --follow -p -- filename |
如果你曾经与很多小伙伴工作在同一个持久分支上,也许会有这样的经历,父分支(例如: master)上的大量合并同步到你当前的分支。
这使得我们很难分辨哪些变更时发生在主分支,哪些变更发生在当前分支,尚未合并到master分支。
git log --no-merges master.. |
可以解决这个问题。注意--no-merges标志意味着只显示没有合并到任何分支的变更,master..选项,意思是指显示没有合并到master分支的变更(在master后面必须有..,省略了HEAD)。
常用日志显示格式化
git log --pretty=format:'%C(yellow)%h %C(green)| %C(white)%ad %C(green)| %C(blue)%>(15,trunc)%an %C(green)| %C(green)%d %C(reset)%s'c5f6951 | 2017-08-08 21:26:06 +0800 | test | v4-br38a1e833 | 2017-08-08 21:26:04 +0800 | test | v3-br2a908021 | 2017-08-08 21:26:00 +0800 | test | v2-br1b700e2e | 2017-08-08 21:25:57 +0800 | test | v1-master |
git checkout -m branch
有时,本地做了一些修改,忘记git stash时,切到另一个分支时,可能提示本地有内容修改,无法切换分支:
git checkout develop
error: You have local changes to 'develop'; not switching branches.You can give the -m flag to the command, which would try a three-way merge:
git checkout -m develop |
如果合并发生冲突,会有相应提示,解决冲突,并git add。
git stash branch
git stash branch会创建一个新分支,从stash中弹出一个暂存并应用修改到新分支上,在新分支上继续当时的工作。
git stashSaved working directory and index state WIP on master: 7422cec merge br2 into masterHEAD is now at 7422cec merge br2 into master git stash branch testSwitched to a new branch 'test'On branch testChanges not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: v9.txtno changes added to commit (use "git add" and/or "git commit -a")Dropped refs/stash@{0} (34e6c8eee86972f44676c86f6dac8306d1dabfa5) |
git reflog
需要注意的是,git reflog信息只存在于本地 —— 这是一个记录你在你自己的仓库里做过什么的日志。
其他人copy的仓库里的引用日志不会和你的相同;而你新clone一个仓库的时候,reflog是空的,因为你在仓库里还没有操作。
显示当前分支2个月前的提交
如下这条命令只有在你克隆了一个项目至少两个月时才会有用 —— 如果你是五分钟前克隆的仓库,那么它将不会有结果返回。
git reflog HEAD@{2.months.ago} |
显示master分支上所有提交的版本号
git reflog master |
git show-ref
git show-ref列出仓库中所有的引用,仓库中所有的分支和标签实际上都是对应于相应的某个提交版本。
git show-ref02ac3819c29fadc0f02f43da3991d969d1fc7afa refs/heads/br199812dcc3c700d044df84b1456d90fdd073ad92c refs/heads/br2c1341c3453570ad06883df4b02f13ebe2c12d3b7 refs/heads/br37422cecd9c4c38ac64f4c58e0f664c4297928d91 refs/heads/master7422cecd9c4c38ac64f4c58e0f664c4297928d91 refs/remotes/origin/master |
git pull --rebase
这是一个非常有用的变基用法。
举个例子,假设你正在master分支的一个本地版本上工作,你已经向仓库提交了一小部分变更。
与此同时,也有人向master分支提交了他一周的工作成果。
当你尝试推送本地变更时,git提示你需要先运行一下git pull:
To git-branch-test.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git-branch-test.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
尽管这不是什么大问题,也完全安全,但是不太有利于历史记录的整洁。
这种情况下,git pull --rebase是一个不错的选择。
git pull --rebase |
这个命令会迫使git将远程分支上的变更同步到本地,然后将尚未推送的提交重新应用到这个最新版本,就好象它们刚刚发生一样。
这样就可以避免提交一个像下面这样的合并信息了。
Merge remote-tracking branch ‘origin/master’
git remote
查看当前配置有哪些远程仓库,对应于.git/gitconfig文件中的配置。
git remote git remote -v git remote show remote git help remote |
git ls-remote
显示远程仓库的版本引用:
git ls-remoteFrom git-branch-test.git7422cecd9c4c38ac64f4c58e0f664c4297928d91 HEAD7422cecd9c4c38ac64f4c58e0f664c4297928d91 refs/heads/master |
git checkout --track
远程分支检出时自动跟踪分支
也可以在检出之后,用-u或--set-upstream-to选项运行git branch来显式地设置,甚至直接编辑配置文件.git/gitconfig。
git checkout --track origin/serverfixBranch serverfix set up to track remote branch serverfix from origin.Switched to a new branch 'serverfix' |
恢复当前文件夹下的文件变更
git checkout -- . |
git fsck
该命令显示所有未被其他对象引用的所有对象,可以从dangling commit找到丢失了的commit。
git fsck --fullChecking object directories: 100% (256/256), done.dangling commit 34e6c8eee86972f44676c86f6dac8306d1dabfa5 |
git gc
git gc指垃圾收集(garbage collect):收集所有松散对象并将它们存入packfile,合并这些packfile进一个大的packfile,然后将不被任何commit引用并且已存在一段时间(数月)的对象删除。
git gcCounting objects: 373923, done.Delta compression using up to 4 threads.Compressing objects: 100% (106664/106664), done.Writing objects: 100% (373923/373923), done.Total 373923 (delta 232320), reused 370405 (delta 228834)Checking connectivity: 373923, done. |
git clean
git clean可以帮你清理当前workspace中未被git版本控制的文件,比如临时文件,构建出来的二进制文件。
这个命令还有-x和-X参数要注意慎用,避免误删文件。
git clean -df |
git grep
用git grep命令查找git库里面的某段文字是很方便的。当然,你也可以用unix下的grep命令进行搜索, 但是git grep命令能让你不用签出git checkout历史文件,就能查找它们。
git grep -n 'v'v1.txt:1:v1v14.txt:1:v14v15.txt:1:v15v2.txt:1:v2v7.txt:1:v7 |
git bisect
利用二分法查找问题版本。
git bisect start git bisect bad git bisect good master@{7}Bisecting: 4 revisions left to test after this (roughly 3 steps)[3d040d06546df6eb9c8b5ac8343d759f74bc3d25] merge br1 into master$ git bisect goodBisecting: 2 revisions left to test after this (roughly 1 step)[849a0578c735f18182d7d587a1aaca381b9ca01b] v11-br2 git bisect goodBisecting: 0 revisions left to test after this (roughly 1 step)[7422cecd9c4c38ac64f4c58e0f664c4297928d91] merge br2 into master git bisect badBisecting: 0 revisions left to test after this (roughly 0 steps)[99812dcc3c700d044df84b1456d90fdd073ad92c] v12-br2 git bisect resetPrevious HEAD position was 99812dc... v12-br2Switched to branch 'master' |
git merge -s ours branch-name
使用ours策略将分支obsolete的合并进当前分支,但是忽略其他分支的所有改变:
Merge branch obsolete into the current branch, using ours merge strategy, ignoring all changes from all other branches.
git merge -s ours obsolete |
使用git merge -s回滚上一个提交,只回滚上一个提交的效果与git revert类似,但是这个方式可以一次回滚到之前任何一个指定提交上。
git checkout -b previous git reset --hard HEAD~ git merge -s ours master git checkout master git merge previous git branch --delete previous git push origin master:master |
git diff -w
给git部分命令加一个-w参数,git将会忽略空白的变更,如下所示:
git diff -w master^ git blame -w filename |
git help hooks
git 能在特定的重要动作发生时触发自定义脚本,有两组这样的钩子:
- 客户端的hooks,由诸如提交和合并这样的操作所调用;
- 服务器端的hooks,作用于诸如接收被推送的提交这样的联网操作。
钩子都被存储在.git目录下的hooks子目录中,即.git/hooks。更多使用说明可参考在线文档,或者查看帮助手册。