本文是对之前Git速查手册的更新,增加了一些这段时间使用到的命令。
配置git
笔者使用的是v2.1.0,推荐大家使用v1.8以上的版本。 查看git版本:
1 | $ git --version |
配置命令git config
分为三个级别:
1 | --system : 系统级,位于 /etc/gitconfig . |
首先需要删除global用户信息,防止不同git软件之间的冲突:
1 | $ git config --global --unset user.name |
设置用户信息.若同时使用gitlab和github,推荐配置local用户信息:
1 | $ git config --local user.name "username" |
git支持https和ssh等协议.https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,而ssh支持的原生git协议速度最快。
检查本机SSH公钥:
1 | $ ls ~/.ssh |
若存在,则将id_rsa.pub
添加到github的SSH keys中。若不存在,则生成:
1 | $ ssh-keygen -t rsa -C "your_email@youremail.com" |
当ssh配置完成后,再次检查ssh连接情况:
1 | $ ssh -T git@github.com |
若出现上述信息,则表示设置成功。
若使用https访问, 则进行如下配置,并且设置超时时间避免重复输入密码:
1 | $ git config --global http.sslverify false |
设置可视化diff和merge工具, linux系统上推荐使用meld或者diffuse:
1 | $ git config --global diff.tool meld |
保存用户名,密码, 避免每次pull/push
操作都需要手动输入:
1 | $ git config --global credential.helper store |
设置颜色,利于使用:
1 | $ git config --global color.ui.true |
设置别名:
1 | $ git config --global alias checkout co |
上面的命令将
checkout
设置为别名co
。
最后,查看一下所有的设置:
1 | $ git config --local --list |
工作流
工作区就是你的本地仓库文件夹,不过其中的.git
目录不属于工作区,而是版本库。里面存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
现在来解释一下前面的添加和提交操作:
git add
把文件添加进去,实际上就是把文件修改添加到暂存区;git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
基本操作
获取远程仓库:
1 | $ git clone git@github.com:USERNAME/repo.git |
将本地的仓库添加到远程:
1 | $ cd repo |
origin
就是一个名字,是git
为你默认创建的指向这个远程代码库的标签。
添加修改:
1 | $ git add <filename> |
提交修改:
1 | $ git commit -m "commit message" |
commit message
的填写可以参考写好 Git Commit 信息的 7 个建议。am
将添加和提交合并为一步,但只对本来就存在的文件有效。
推送修改:
1 | $ git push -u origin <feature-branch-name> |
-u
选项可以将本地分支与远程分支关联,下次git pull
操作时可以不带参数.具体参见这里。
查看远程仓库:
1 | $ git remote -v |
fork后同步上游仓库的更新:
1 | # 第一次需要添加上游仓库 |
引用公共代码:
代码引用在git上有两种方式:submodule
和subtree
,推荐使用subtree方式。
1 | # 第一次初始化 |
使用标签
查看标签 :
1 | $ git tag |
创建标签 :
1 | $ git tag -a <tagname> -m "tag message" # 创建标签在当前最新提交的commit上 |
推送标签到远程:
1 | $ git push origin <tagname> # 推送一个本地标签 |
删除标签:
1 | $ git tag -d <tagname> # 删除一个本地标签; |
撤销与回退
查看当前仓库状态:
1 | $ git status |
查看文件更改:
1 | $ git difftool <filename> |
查看提交历史:
1 | $ git log |
撤销工作区Tracked files
的修改:
1 | $ git checkout -- <filename> |
撤销工作区Untracked files
的修改:
1 | ##### |
回退版本区(git commit
)和暂存区(git add
),不删除工作空间代码:
1 | $ git reset --mixed HEAD^ # --mixed为默认参数 |
回退版本区(git commit
),暂存区(git add
)不回退,不删除工作空间代码:
1 | $ git reset --soft HEAD^ |
回退版本区(git commit
)和暂存区(git add
),并删除工作空间代码(不包括Untracked files
),执行后直接恢复到指定<commit-id>
状态:
1 | $ git reset --hard <commit-id> |
HEAD
表示当前版本,HEAD^
表示上个版本,HEAD^^
表示上上个版本,上100个版本可以表示为HEAD~100
以此类推。
回退版本后,若需要返回原来的版本,会发现找不到未来的commit id
,则需要查看操作命令历史进行查找:
1 | $ git reflog |
从版本库删除文件:
1 | $ git rm <filename> |
若你的代码已经push
到线上,则推荐使用下面这个命令回滚:
1 | $ git revert <commit-id> |
revert
是用一次新的commit
来回滚之前的commit
,更安全;reset
则是直接删除指定的commit
,若直接push
会导致冲突。
分支
查看所有分支,有*
标记的是当前分支:
1 | $ git branch -a |
创建本地分支:
1 | $ git branch <newbranch> |
创建并切换本地分支:
1 | $ git checkout -b <newbranch> |
从标签创建分支:
1 | $ git branch <branch> <tagname> |
推送新建本地分支到远程:
1 | $ git push -u origin <remote-branch-name> |
删除本地分支:
1 | $ git branch -d <branch> |
若当前分支因为有修改未提交或其它情况不能删除,请使用
-D
选项强制删除。
删除远程分支(三种方法):
1 | $ git push origin --delete <remote-branch-name> |
清除无用的分支:
1 | $ git remote prune origin |
说明:remote上的一个分支被其他人删除后,需要更新本地的分支列表。
获取远程分支到本地已有分支:
1 | $ git branch --set-upstream <local-branch> origin/branch |
获取远程分支到本地并新建本地分支:
1 | $ git checkout -b <local-branch> <remote-branch> |
同步当前分支的更新,使用git pull
并不保险:
1 | # 下载最新的代码到远程跟踪分支, 即origin/<branch-name> |
同步其它分支的更新,本例拉取master
分支更新:
1 | $ git fetch origin master |
查看某个<commit id>
属于哪个分支:
1 | $ git branch -a --contains <commit id> |
暂存
当你需要切换分支时,若当前工作区还有些修改没有完成,又不适合提交的,操作切换分支是会提示出错的.这时就需要将这些修改暂存起来:
1 | $ git stash save "message" |
查看:
1 | $ git stash list |
恢复:
1 | $ git stash pop [--index] [stash@{num}] |
--index
表示不仅恢复工作区,还会恢复暂存区;num
是你要恢复的操作的序列号,默认恢复最新进度.
删除进度:
1 | $ git stash drop [stash@{num}] # 删除指定进度 |
清理仓库
清理无用的分支和标签
1 | $ git branch -d <branch-name> |
清理大文件
查看
git
相关文件占用空间:1
2$ git count-objects -v
$ du -sh .git寻找大文件
ID
1
$ git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10
输出的第一列是文件
I
D,第二列表示文件(blob)
或目录(tree)
,第三列是文件大小,此处筛选了最大的10条获取文件名与
ID
映射1
$ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')"
从所有提交中删除文件
1
2$ git filter-branch --tree-filter 'rm -rf xxx' HEAD --all
$ git pull清理
.git
目录:1
$ git gc --prune=now
tips: 在执行
push
操作时,git
会自动执行一次gc
操作,不过只有loose object
达到一定数量后才会真正调用,建议手动执行。
处理大型二进制文件
由于git在存储二进制文件时效率不高,所以需要借助第三方组件。
忽略特殊文件
当你的仓库中有一些文件,类似密码或者数据库文件不需要提交但又必须放在仓库目录下,每次git status
都会提示Untracked
,看着让人很不爽,提供两种方法解决这个问题
本地
在代码仓库目录创建一个.gitignore
文件,编写规则如下:
1 | tmp/ # 忽略tmp文件夹下所有内容 |
全局
在用户目录创建一个.gitignore_global
文件,编写规则同.gitignore
,并修改~/.gitconfig
1 | [core] |
如果添加的忽略对象已经Tracked
,纳入了版本管理中,则需要在代码仓库中先把本地缓存删除,改变成Untracked
状态
1 | $ git rm -r --cached . |
奇技淫巧
重写历史(慎用!)
1 | $ git rebase -i [git-hash| head~n] |
其中
git-hash
是你要开始进行rebase
的commit
的hash
,而head~n
则是从HEAD
向前推n
个commit
全局更换电子邮件
1 | git filter-branch --commit-filter ' |
帮助
查看帮助:
1 | $ git --help |