底层命令
对象
读写对象
git hash-object -w --stdin
: 创建对象git cat-file -t <对象校验和>
: 查看对象类型git cat-file -p <对象校验和>
: 查看对象内容
tree对象
-
git update-index --add --cacheinfo <mode> <对象校验和> <file>
将已经保存的对象以文件加入到暂存区<mode: 100644为普通文件,100755为可执行文件, 120000为符号链接>
, 这里的<对象校验和>必须是全部sha1, 不能只输入前面几位,其它命令可以。 -
git update-index --index-info
通过stdin的方式一次性index多个对象,例如:git update-index --index-info
0 0000000000000000000000000000000000000000 test.txt 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 test.txt 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 test.txt
- 第一段(100644) 文件mode, 第二段是对象校验和,第3段是stage, 表示你对同一个文件修改的次数,最后一段是文件名。
- 第一行的mode为0,表示remove
-
git write-tree
以暂存区内容创建tree -
git ls-tree <Tree对象校验和>
查看Tree对象内容 -
git update-index test.txt
更新暂存区指定文件内容 -
git update-index --add new.txt
往暂存区中加入文件 -
git read-tree --prefix=目录 <tree对象校验和>
将另一棵树加入暂存区,并以目录形式存在 -
git commit-tree <tree对象校验和>
以tree对象产生一次commit -
git log --stat <commit对象校验和>
查看commit日志
引用
引用操作(refs)
git update-ref refs/heads/master <commit对象校验和>
生成master引用, 可将master改为你喜欢的名字,这个名字就是对应commit的别名git symbolic-ref HEAD refs/heads/test
设置当前所在分支的引用git symbolic-ref HEAD
查看当前分支引用
标签(tags)
git update-ref refs/tags/<tag名称> <任意对象校验和>
创建lightweight标签git tag -a <tag名称> <任意对象校验和> –m '<注释>'
创建有注释(annotated tag)的标签
远程(remotes)
git remote add origin http://10.5.38.201/test.git
增加远程引用git push origin master
推送本地master引用到远程origin引用git remote -v
查看当前配置的远程仓库git remote show <远程分支>
查看远程分支的详细信息git remote rename <原名称> <新名称>
修改本地远程配置名称git remote rm <远程名称>
删除本地远程配置
打包(packfiles)
git gc
打包git verify-pack -v <包文件>
查看包文件内容
Refspec
基本配置与操作
首先看执行上面的
git remote add origin http://10.5.38.201/test.git
命令后配置文件的变化:
它会在.git/config文件中增加一节:
[remote "origin"]
url = ```http://10.5.38.201/test.git```
fetch = +refs/heads/*:refs/remotes/origin/*
Refspec 的格式是一个可选的+ 号,接着是<src>:<dst>
的格式,这里<src>
是远端上的引用格式, <dst>
, 是将要记录在本地的引用格式。可选的+ 号告诉Git 在即使不能快速演进的情况下,也去强制更新它
以下三种历史访问方式是等同的
git log origin/master
git log remotes/origin/master
git log refs/remotes/origin/master
如果你想让Git 每次只拉取远程的master 分支,而不是远程的所有分支,你可以把fetch 这一行修改成这样:
fetch = +refs/heads/master:refs/remotes/origin/master
如果你只想做一次动作,可以用下面的命令从远程fetch然后保存到本地指定的分支, 如下面命令将远程master分支fetch到本地mymaster分支:
git fetch origin master:refs/remotes/origin/mymaster
也可以在命令行上指定多个refspec, 将远程master分支fetch到mymaster, 并将远程topic分支fetch到本地topic分支:
git fetch origin master:refs/remotes/origin/mymaster topic:refs/remotes/origin/topic
你也可以在配置中指定多个refspec:
[remote "origin"]
url = ```http://10.5.38.201/test.git```
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/experiment:refs/remotes/origin/experiment
如果有多个团队协作需要分组,你可以fetch指定组的所有分支:
[remote "origin"]
url = ```http://10.5.38.201/test.git```
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/qa/*:refs/remotes/origin/qa/*
推送Refspec
git push origin master:refs/heads/qa/master
将master分支push到远程qa组的master分支
如果他们想让Git 每次运行git push origin 时都这样自动推送,他们可以在配置文件中添加push 值:
[remote "origin"]
url = ```http://10.5.38.201/test.git```
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/master:refs/heads/qa/master
删除分支
git push origin :topic
因为refspec 的格式是<src>:<dst>
, 通过把<src>
部分留空的方式,这个意思是是把远程的topic 分支变成空,也就是删除它
基本命令
工作区
- 工作区: 是目前工作的目录的内容
- 暂存区:已经运行了git add命令,注意,如果运行git add后,继续修改了文件,该文件需要git add而不管之前的git add有没有增加该文件, git commit -a -m "comment"可以将当前工作区的内容全部提交
- 仓库:已经commit的内容
- 远程仓库: 已经push的内容
文件状态
- untracked: 在当前工作区,但不在暂存区,也不在仓库
- unmodified: 在当前工作区,在暂存区,在不在仓库不影响它的状态。
- modified: 在当前工作区,针对于暂存区的内容已经修改,也在暂存区,在不在仓库不影响它的状态
状态变化实例
git init
初始化git库git add .
将当前所有修改或新增的文件进暂存区git add *.c
将当前目录所有以.c结尾的文件加进暂存区git add test.txt
将指定文件加进暂存区git commit -m "comments"
提交到仓库git clone http://10.5.38.201/test.git [目录]
克隆远程仓库到本地
查看状态
git status
查看当前工作目录状态git diff
比较工作区内容与暂存区内容git diff --cached
或者git diff --staged
比较暂存区与仓库内容
查看日志
-
git log
查看仓库历史记录,即所有commit后的历史信息 -
git log –p -2
查看最近2次的历史信息 -
git log --stat
显示文件修改的行数 -
git log --pretty=oneline
将每次提交的注释一行显示 -
git log --pretty=format:"%h - %an, %ar : %s"
格式化输出日志内容格式化选项说明
%H
提交对象(commit)的完整哈希字串%h
提交对象的简短哈希字串%T
树对象(tree)的完整哈希字串%t
树对象的简短哈希字串%P
父对象(parent)的完整哈希字串%p
父对象的简短哈希字串%an
作者(author)的名字%ae
作者的电子邮件地址%ad
作者修订日期(可以用-date= 选项定制格式)%ar
作者修订日期,按多久以前的方式显示%cn
提交者(committer)的名字%ce
提交者的电子邮件地址%cd
提交日期%cr
提交日期,按多久以前的方式显示%s
提交说明
参数说明
git log 选项说明
-p
按补丁格式显示每个更新之间的差异。--stat
显示每次更新的文件修改统计信息。--shortstat
只显示–stat 中最后的行数修改添加移除统计。--name-only
仅在提交信息后显示已修改的文件清单。--name-status
显示新增、修改、删除的文件清单。--abbrev-commit
仅显示SHA-1 的前几个字符,而非所有的40 个字符。--relative-date
使用较短的相对时间显示(比如,“2 weeks ago”)。--graph
显示ASCII 图形表示的分支合并历史。--pretty
使用其他格式显示历史提交信息。可用的选项包括oneline,short,full,fuller 和format(后跟指定格式)。
限制选项说明:
-(n)
仅显示最近的n 条提交--since, --after
仅显示指定时间之后的提交。--until, --before
仅显示指定时间之前的提交。--author
仅显示指定作者相关的提交。--committer
仅显示指定提交者相关的提交。
-
git log --since=2.weeks
查看最近两周的提交 -
gitk
图形查看
文件操作
git rm removing.txt
从当前工作区中删除removing.txt文件, 加-f
是强制删除git rm --cached removing.txt
从暂存区中删除removing.txt文件,但工作区中不删除git mv removing.txt test.txt
将removing.txt改名成test.txt, 同理如果加--cached
是直接在暂存区中修改, 加-f
是强制改名
常用命令
撤销修改 (慎重)
git reset HEAD test.txt
从暂存区中撤销修改, 即取消你通过git add 加进暂存区的内容git checkout -- test.txt
取消本地工作区修改git fetch --all
然后git reset --hard origin/master
将会重置所有工作区和暂存区中内容,完全跟远程仓库相同
标签
git tag
显示所有标签git tag -l 'v1.4.2.*'
显示以v1.4.2.开头的标签git tag -a v1.4 -m 'my version 1.4'
创建带注释的标签git show v1.4
查看标签信息git tag -s v1.5 -m 'my signed 1.5 tag
标签签名git tag -v [tag-name]
验证标签git tag v1.4-lw
轻量级标签git tag -a v1.2 <commit对象校验和>
给任意commit打标签git push origin v1.5
将本地标签push到远程,注意,如果不运行此命令,标签将只在你本地git push origin --tags
一次推送所有本地标签
分支
git branch -a
: 显示所有分支git branch branch1
: 创建分支git checkout master
: 切换分支git merge branch1
: 合并分支git push origin branch1
: 推送分支git push origin :branch1
或者git push origin --delete
: 删除分支git branch -m devel develop
: 重命名分支
配置
配置别名
一些常用别名配置:
# 基本配置
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.bra branch -ra
git config --global alias.branch branch -ra
git config --global alias.ci commit
git config --global alias.cl clone
git config --global alias.cp cherry-pick
git config --global alias.r reset
git config --global alias.gr grep -Ii
git config --global alias.st status -s
git config --global alias.unstage 'reset HEAD --'
git config --global alias.visual "!gitk"
git config --global alias.logline "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
# 提交
git config --global alias.cm commit -m
git config --global alias.cma "commit -a -m"
git config --global alias.ca commit --amend
git config --global alias.caa "commit -a --amend -C HEAD"
# 日志
git config --global alias.ls log '--pretty=format:"%C(green)%h\\ %C(yellow)[%ad]%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=relative'
git config --global alias.ll 'log --pretty=format:"%C(yellow)%h%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --numstat'
git config --global alias.lc '!f() { git ll "$1"^.."$1"; }; f'
git config --global alias.lnc 'log --pretty=format:"%h\\ %s\\ [%cn]"'
git config --global alias.fl log -u
git config --global alias.filelog log -u
# 区别
git config --global alias.d diff --word-diff
git config --global alias.dc diff --cached
git config --global alias.dlc 'diff --cached HEAD^'
git config --global alias.dr '!f() { git diff -w "$1"^.."$1"; }; f'
git config --global alias.diff diff --word-diff
git config --global alias.diffr '!f() { git diff "$1"^.."$1"; }; f'
# 重置
git config --global alias.r1 'reset HEAD'^
git config --global alias.r2 'reset HEAD^^'
git config --global alias.rh 'reset --hard'
git config --global alias.rh1 'reset HEAD^ --hard'
git config --global alias.rh2 'reset HEAD^^ --hard'
# 暂存
git config --global alias.sl stash list
git config --global alias.sa stash apply
git config --global alias.ss stash save
# 假设
git config --global alias.assume 'update-index --assume-unchanged'
git config --global alias.unassume 'update-index --no-assume-unchanged'
git config --global alias.assumed '!git ls-files -v | grep ^h | cut -c 3-'
git config --global alias.unassumeall '!git assumed | xargs git update-index --no-assume-unchanged'
# 子树
git config --global alias.sba '!f() { git subtree add --prefix $2 $1 master --squash; }; f'
git config --global alias.sbu '!f() { git subtree pull --prefix $2 $1 master --squash; }; f'
# 冲突与合并
git config --global alias.ours '!f() { git co --ours $@ && git add $@; }; f'
git config --global alias.theirs '!f() { git co --theirs $@ && git add $@; }; f'
# 远程
git config --global alias.rem '!git config -l | grep remote.*url | tail -n +2'
# 补丁
git config --global alias.lap '!f() { git --git-dir=$1 format-patch -k -1 --stdout $2 | git am -3 -k; }; f'
# Markdown
git config --global alias.last '!gvim $(git show HEAD --format="" --name-only | grep -e .*md$ | xargs)'
git config --global alias.newmd '!gvim $(git status -s | awk {'print $2'})'
# 空提交
git config --global alias.empty '!git commit -am\"[empty] Initial commit\" --allow-empty'
# 查找
git config --global alias.gra '!f() { A=$(pwd) && TOPLEVEL=$(git rev-parse --show-toplevel) && cd $TOPLEVEL && git grep --full-name -In $1 | xargs -I{} echo $TOPLEVEL/{} && cd $A; }; f'
git config --global alias.f '!git ls-files | grep -i'
# 其它
git config --global alias.la '!git config -l | grep alias | cut -c 7-'
git config --global alias.ai add --interactive
git config --global alias.lasttag 'describe --tags --abbrev=0'
git config --global alias.lt 'describe --tags --abbrev=0'
git config --global alias.done '!f() { git branch | grep "$1" | cut -c 3- | grep -v done | xargs -I{} git branch -m {} done-{}; }; f'
git config --global alias.wl worktree list
git config --global alias.undo '!f() { git reset --hard $(git rev-parse --abbrev-ref HEAD)@{${1-1}}; }; f'
问题处理
自签名ssl证书错误,无法提交
git config --global http.sslVerify false
: 取消ssl证书验证
回车换行处理
git config --global core.autocrlf true
: LF会被转换成CRLFgit config --global core.autocrlf input
: 提交时把CRLF转换成LF,签出时不转换git config --global core.autocrlf false
: 不做转换
文件路径过长错误
git config --system core.longpaths true
忽略文件或目录
在目录中创建.gitignore文件,并按下面规则加入忽略文件:
#
: 此为注释– 将被Git 忽略*.a
: 忽略所有.a 结尾的文件!lib.a
: 但lib.a 除外/TODO
: 仅仅忽略项目根目录下的TODO 文件,不包括subdir/TODObuild/
: 忽略build/ 目录下的所有文件doc/*.txt
: 会忽略doc/notes.txt 但不包括doc/server/arch.txt
保存密码
git config --global credential.helper store
修改注释
git commit --amend
修改commit后的注释,但不能个性已经push过的注释git rebase -i HEAD~2
修改push后的注释,后面的2指当前提交的向前的第2次的提交,不带数字表示当前提交,之后需用git push -f
强制提交, 注意,这会让其它开发者的版本出现混乱,不得不重置,并且一般的git服务器都有权限管理,一般用户可能没有强制提交的权限,这个命令也就无法使用了。
查找
git grep text
在git库中查找text,结果会显示文件名和字符串所在行的内容。git grep text "*.txt"
在指定文件中查找内容git grep -n text
结果中会显示该字符串所在行号git grep --name-only text
如果中只显示包含该字符串的文件名git grep -c text
结果中显示文件名和该文件中有几处有该字符串git grep text v1.5.0
在某个标签中查找该字符串, 后面的v1.5.0是标签(tag)git grep -e 'using' --and -e 'System.Linq'
查找“和”条件内容git grep --all-match -e 'System.Linq' -e 'System.Text'
查找“或”条件内容git grep -e 'System' --and \( -e 'System.Linq' -e 'System.Text' \)
查找“和”与“或”组合条件内容- 其它用法可查阅linux grep用法
控制台分页显示
新版的git在显示分支和日志时采用分布处理,在一般情况下比较难看,这里禁止分页
git config --global pager.branch false
git config --global pager.log false