前言

在个人使用 git 时,你可能只需要记住 git add , git commit , git push 这 3 个常用命令就可以了,但一旦进入团队合作,或者项目逐渐变得复杂起来的时候,这些命令就显得不足了。本篇为弥补之前学习 git 的漏洞,方便查询指令之用,粗略地划分了门类,指令下面是简单的解释,可以让你迅速拾起对指令的认识,免去查询手册之苦。


多人工作模式

git分支开发模型

Git 常用命令速查 - 图1

  • 首先,可以试图用git push origin branch-name推送自己的修改;
  • 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
  • 如果合并有冲突,则解决冲突,并在本地提交;
  • 没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功;
  • 如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,
    用命令git branch --set-upstream branch-name origin/branch-name;

注意: 不要直接在迭代分支上写代码: 比如这次我们迭代分支是 dev,那么在 dev 上 checkout 出自己的开发分支,一个功能完成后提交 MR 到 dev 上,由其他同学来 review,有问题的地方进行整改,全部 ok 后合并入 dev。等 dev 也稳定之后合并入 master。


关联本地分支和远程分支

  • 第一种,远程分支如dev,本地分支如 dev ,用git branch --set-upstream dev origin/dev命令连接。
  • 第二种,本地创建分支如 dev,用git push -u origin dev,将本地分支上传到远程仓库,并关联起来,如果远程没有 dev 分支,会自动创建。
  • 第三种,抓取远程分支并在本地建立关联的分支,用git checkout -b local-branchname origin/remote_branchname

如何在现有工程中删除讨厌的.DS_Store

  1. $ find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch

向顶层的 .gitignore 文件中增加行.DS_Store,然后

  1. $ git add .gitignore
  2. $ git commit -m '.DS_Store banished!'

如何下载github上的单个文件夹

/tree/master/ 换成 /trunk/ ,然后用 svn checkout,例如:

  1. $ svn checkout https://github.com/Mooophy/Cpp-Primer/trunk/ch03

Commit 提交规范

根据 angular 规范提交 commit,这样 history 看起来更加清晰,还可以自动生成 changelog。

  1. <type>(<scope>): <subject>
  2. <BLANK LINE>
  3. <body>
  4. <BLANK LINE>
  5. <footer>

(1)type

提交 commit 的类型,包括以下几种

  • feat: 新功能
  • fix: 修复问题
  • docs: 修改文档
  • style: 修改代码格式,不影响代码逻辑
  • refactor: 重构代码,理论上不影响现有功能
  • perf: 提升性能
  • test: 增加修改测试用例
  • chore: 修改工具相关(包括但不限于文档、代码生成等)
  • deps: 升级依赖

(2)scope

修改文件的范围(包括但不限于 doc, middleware, proxy, core, config)

(3)subject

用一句话清楚的描述这次提交做了什么

(4)body

补充 subject,适当增加原因、目的等相关因素,也可不写。

(5)footer

  • 当有非兼容修改时可在这里描述清楚
  • 关联相关 issue,如 Closes #1, Closes #2, #3
  • 如果功能点有新增或修改的,还需要关联 MR,如 xxx/doc!123

示例:

  1. fix($compile): couple of unit tests for IE9
  2. Older IEs serialize html uppercased, but IE9 does not...
  3. Would be better to expect case insensitive, unfortunately jasmine does
  4. not allow to user regexps for throw expectations.
  5. Document change on xxx/doc!123
  6. Closes #392
  7. Breaks foo.bar api, foo.baz should be used instead

查看具体文档


提交 Merge Request

如果你有仓库的开发者权限,而且希望贡献代码,那么你可以创建分支修改代码提交 MR,让负责人 review 代码合并到主干。

  1. // 先创建开发分支开发,分支名应该有含义,避免使用 updatetmp 之类的
  2. $ git checkout -b branch-name
  3. // 开发完成后跑下测试是否通过,必要时需要新增或修改测试用例
  4. $ tnpm run test
  5. // 测试通过后,提交代码,message 见下面的规范
  6. $ git add . // git add -u 删除文件
  7. $ git commit -m "fix(role): role.use must xxx"
  8. $ git push origin branch-name

提交后就可以在 gitlab 创建 MR 了。

由于谁也无法保证过了多久之后还记得多少,为了后期回溯历史的方便,请在提交 MR 时确保提供了以下信息。

  1. 需求点(一般关联 issue 或者注释都算)
  2. 升级原因(不同于 issue,可以简要描述下为什么要处理)
  3. 框架测试点(可以关联到测试文件,不用详细描述,关键点即可)
  4. 关注点(针对用户而言,可以没有,一般是不兼容更新等,需要额外提示)

指令集合

设置

  • git config --global user.name "Your Name"
  1. $ 全局设置用户名 "--global" 代表所有仓库使用这一配置
  • git config --global user.email "email@example.com"
  1. $ 全局设置你的邮箱
  • git config --global color.ui true 让Git显示颜色
  • .gitignore 编写
  • git config --global alias.<new order> order 为命令设置别名
  1. $ git config --global alias.st status 告诉Git,以后st就表示status,下面列一些常用设置
  2. $ git config --global alias.co checkout
  3. $ git config --global alias.ci commit
  4. $ git config --global alias.br branch
  5. $ git config --global alias.unstage 'reset HEAD' 撤销暂存区修改
  6. $ git config --global alias.last 'log -1' 显示最近一次提交
  7. $ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" 简直丧心病狂!
  8. 如果要修改别名,当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中,可以直接修改

基本操作

  • git init
  1. $ 初始化一个git仓库
  • git add <file>
  1. // 添加文件到仓库中
  2. $ git add readme.txt ,可多次add
  • git reset HEAD <file>
  1. // 从暂存区撤销一个add
  2. $ git reset HEAD 1.py
  • git commit -m <message>
  1. // 快速提交代码
  2. $ git commit -m "this is a commit",多次add,一次commit
  • git checkout -- <file>
  1. // 丢弃工作区的修改
  2. $ git checkout -- readme.txt
  3. $ git checkout . 丢弃所有本地修改
  4. $ 如果已经 add,可以用 git reset HEAD <file> 先撤销 add,再丢弃更改
  5. $ 如果你已经commit了,可以用 git reset --hard HEAD^ 进行回退到上一版本
  6. $ 如果你还推送到了远程分支,那就 gg 了...
  • git rm <file>
  1. $ 从版本库中删除某文件
  2. $ git rm test.txt

仓库状态

  • git status
  1. $ 查看仓库当前状态
  • git diff <file>
  1. $ 查看仓库中的文件和现在的文件的改动
  2. $ git diff readme.txt ,如果输入git diff 会列出所有文件的改动。
  3. $ 注意 git diff 会比较仓库中的文件和不在仓库中的同一文件间的差异,即 git add 的文件A,以及git add后改动的文件A
  4. $ 如果没有改动,git diff 甚至智能地不自动匹配文件
  • git log
  1. // 查看提交历史
  2. $ 从最近到最远 可以加 --pretty=oneline git 显示得更清楚些
  3. $ git log --graph --pretty=oneline --abbrev-commit 用--graph查看分支合并图
  • git reset --hard <commit id>
  1. // 版本回退
  2. $ git reset --hard HEAD^, HEAD代表当前版本,HEAD^代表上个版本,Head^^代表上上版本,HEAD-100代表往上100个版本
  3. $ 不过过去了回不来怎么办, 只要命令行窗口没关闭,就可以找到你要回去的commit id,然后再用如 git reset --hard 3628164 回到该版本.
  4. $ 如果第二天后悔了怎么办?用 git reflog 查看所有命令,再找到相应的commit id即可
  • git reflog
  1. // 查看命令历史
  2. $ 配合 git rest 使用

分支管理

  • git branch
  1. // 查看分支
  • git branch <branch name>
  1. // 创建分支
  2. $ git branch dev
  • git branch -d <branch name>
  1. // 删除分支
  2. $ git branch -d dev
  • git push origin :<branch name>
  1. // 删除远程分支
  2. $ git push origin :dev
  • git branch -D <branch name>
  1. // 强行删除分支
  2. $ git branch -D feature-vulcan 没有进行合并的分支用-d参数会销毁失败,
  3. $ 如果实在要丢弃一个没有合并过的分支,用-D参数强行销毁
  • git branch -m <old_branch_name> <new_branch_name>
  1. // 修改本地分支名称
  2. $ git branch -m feature-a feature-b
  • git checkout <branch name>
  1. // 切换分支
  2. $ git checkout dev
  • git checkout -b <branch name>
  1. // 创建新分支并切换
  2. $ git checkout -b issue-101
  • git merge <branch name>
  1. // 合并分支
  2. $ git merge dev
  • git merge --no-ff -m <message> <branch name>
  1. // 禁用fast forward
  2. $ git merge --no-ff -m "merge with no-ff" dev
  3. $ --no-ff表示禁用fast forward,在ff模式下删除分支后会丢掉分支信息,所以用--no-ff
  4. $ git就会在merge的时候生成一个新的commit,因为要有一个新的commit所以要加上-m参数
  • git stash
  1. // 储藏工作现场
  2. $ 可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作
  • git stash list
  1. // 列出储藏的工作现场
  • git stash apply
  1. // 恢复现场,但stash内容不删除
  • git stash drop
  1. // 删除现场
  • git stash pop
  1. // 恢复现场的同时删除现场
  • git stash apply <stash id>
  1. // 多个现场时指定恢复某一现场
  2. $ 先用 git stash list 查看
  • git rebase <branch name>
  1. $ 整合分支
  2. $ 变基
  3. $ 高危操作请清楚了解原理和后果后再操作

远程仓库

  • ssh-keygen -t rsa -C "youremail@example.com"
  1. // 创建ssh-key
  2. // 将公钥添加到github等网站上
  • git remote add origin <remote git repo>
  1. // 将本地仓库和远程仓库相关联,在本地仓库执行
  2. $ git remote add origin git@github.com:rdmclin2/learngit.git, 远程库的名字叫origin

可以添加多个远程仓库如git remote add rdmclin2 git@.... origin rdmclin2都是我们为远程仓库取的别名。

  • git remote set-url origin <remote git repo>,
  1. // 修改origin的地址
  2. $ git remote set-url origin git@lab.artemisprojects.org:menchenglin/fcws.git
  • git push origin <branch name>
  1. // 将本地内容推送到远程
  2. $ git push origin master , 第一次推送时加上-u参数,可以把本地分支和远程分支关联起来,以后就不要添加了
  • git clone <remote git repo>
  1. // 从远程仓库克隆
  2. $ git clone git@github.com:michaelliao/gitskills.git,非常常用的操作

clone时可以指定深度,git clone git://xxoo --depth 1

  • git remote
  1. // 查看远程库信息
  2. $ -v 参数显示更详细的信息
  • git pull
  1. // 抓取远程分支最新提交并合并分支
  2. $ git tag v0.9 6224937, 可以先用git log --pretty=oneline --abbrev-commit 查看历史提交
  • git fetch
  1. // 抓取远程分支最新提交(与pull区别的是fetch不直接合并)
  • git branch --set-upstream <local branch> <remote branch>
  1. // 指定本地分支和远程分支的链接
  2. $ git branch --set-upstream dev origin/dev 指定本地dev分支与远程origin/dev分支的链接

标签管理

  • git tag <name>
  1. // 打标签
  2. $ git tag v1.0
  • git tag
  1. // 查看所有标签
  2. // 按字母排序
  • git show <tagname>
  1. // 查看标签信息
  • git tag <name> <commit id>
  1. // 给某次提交打上标签
  2. $ git tag v0.9 6224937, 可以先用git log --pretty=oneline --abbrev-commit 查看历史提交
  • git tag -a <tagname> -m <message> <commit id>
  1. // 创建带有说明的标签
  2. $ git tag -a v0.1 -m "version 0.1 released" 3628164 ,-a 指定标签名, -m 指定说明文字
  • git tag -s <tagname> -m <message> <commit id>
  1. // 采用PGP签名一个标签
  2. $ git tag -s v0.2 -m "signed version 0.2 released" fec145a, -s用私钥签名一个标签
  3. $ 看[这篇文章](http://www.ruanyifeng.com/blog/2013/07/gpg.html)了解如何安装gnupg
  • git tag -d <tagname>
  1. // 删除标签
  2. $ git tag -d v0.1
  • git push origin <tagname>
  1. // 推送标签到远程
  2. $ git push origin v1.0
  • git push origin --tags
  1. // 一次性推送全部尚未推送到远程的本地标签
  • git push origin :refs/tags/<tagname>
  1. // git push origin :refs/tags/v0.9

参考资料