Pro Git速查笔记

一、前言

  git是个性大神Linus自Linux内核而来的第二大发明。对于这个神器,个人也用了很久,相对其它的版本控制工具,其速度快、性能好、操作智能人性,是开发人员必备之利器;GitHub依托git作为程序员和开源项目代码首选托管网站,俨然同时也已成为全球最大的程序员基佬之交友网站。
  正如Linux下面的大多数命令行程序一样,只有常用的和用的多的才记得住,不常用的即使当时搞得很清晰,事后也容易忘记。这次在假期把Pro Git中文版看了一遍,这里打算对常用的命令和参数进行一次整理,方便后续复习查阅。
Pro Git

二、git常用命令记录

.gitignore文件格式
  • 所有空行以及用#开头的注释都会被忽略;
  • 匹配的模式是glob模式,*匹配零个或多个任意字符,[abc]匹配任何一个列在方括号中的字符,?只匹配一个任意字符;
  • 模式后面接/表示要忽略的是目录;
  • 要对某些模式或者目录提出例外情况,使用!进行取反;
  • doc/.txt只匹配doc直接目录下的.txt,而doc/*/.txt会递归匹配整个目录和子目录的*.txt;
git diff
  • git diff #默认查看的是当前修改的文件和暂存区快照文件的差异;
  • git diff –cached/–staged #查看暂存区快照文件和上一次提交的对比;
  • git reset HEAD #将文件从暂存区撤出来,和当前修改合并;
git rm
  • git rm #将文件从版本控制中剔除,默认会连同文件系统的文件一通删掉
  • git rm –cached #保留文件本身而脱离版本控制(常用于比如忘了添加到.gitignore)
git log
  • git log -p #以补丁的形式显示提交的内容差异
  • git log - #显示最近的n次提交
  • git log –word-diff #显示单词(而不是默认行)级别的差异,在处理文本的时候比较有用
  • git log -U #显示差异的上下文行数,默认是3
  • git log –stat #相比默认显示,添加了修改文件,及其行数信息
  • git log –pretty=[online,short,full,fuller,format:]
    git log –pretty=format:”%h %ae %cd %s” #这在提交数目太多的时候,可以方便的显示.
  • git log –author=xxx –since=”2015-01-12” –before=”2015-03-10” –grep=”CPP” #可以指定单条或者多条过滤格式.默认是满足任何一条就列出,如果需要满足多条,需要额外添加–match-all选项.
git commit
  • git commit –amend #对最后一次提交进行覆盖重新提交.(切记对于已经push的commit会引来麻烦)
  • git reset HEAD #可以对已经暂存的文件撤出暂存区并同当前目录文件合并
  • git checkout – #放弃当前文件的修改,文件内容跟暂存区内容一致.
git remote
  • git remote -v #显示远程仓库的信息
  • git remote add https://remote-url #添加远程仓库
  • git fetch #抓取远程仓库的内容,注意的是fetch只是抓取内容,而不会自动合并内容到本地
  • git push #推送内容到远程的某个分支
  • git remote show #显示远程仓库的详细信息(需要联网)
  • git remote rename/rm #重命名/删除远程仓库
git tag
  • git tag #显示当前仓库已有的标签.
  • git tag #打轻量级的标签
  • git tag -a -m “tag-message” #打带附注的标签
  • git config –global user.signingKey C0CC5261 #设置默认签名
    git tag -s -m “tag-message” #打带GPG签名的标签
  • git tag -v #验证带签名的标签
  • git push origin #默认push不会把tag推送到远程服务器的,可以用这个命令将推送到远程仓库
    git push origin –tags #推送本地所有tag到远程仓库
  • (1)Git的标签轻量级的和带附注的两种类型.前者其实就是对某个特定提交的引用;而后者是一个实际的标签对象,包含校验信息\标签名\email\日期\GPG校验等信息.

git branch
  • git branch #创建分支
  • git checkout #切换到对应分支(切换分支的时候最好保持一个干净的工作空间-stash)
  • git checkout master
    git merge devel #将devel分支的更新合并到master分支
    git branch -d devel #删除无用分支
  • git branch –merged #查看那些分支已经被并入到当前的分支,也就是那些分支是当前分支的直接上游,因为已经被合并了,所以当前分支已经包含了其所有的数据,可以安全删除这里列出的分支;
  • git branch –no-merged #与上面相反,包含尚未合并的数据,默认不能简单删除之
  • git log .. # 查看所有在[experiment]中而不在分支中的提交,显示的就是git merge 所用到的存在于中的所有提交;
  • git log origin/master..HEAD #预览你将会被那些推送给远程仓库;
  • git log –left-right .. #查看两个分支各自不同的提交信息
  • (1)上面这些分支都是本地的分支,跟服务器上的分支没有任何关系,服务器上的分支需要/这样的方式来引用;

  • (2)合并有快进合并(Fast-forward)和普通合并,当某个分支在被合并分支的下游,就会快进合并;否则在之前的某个提交开始分叉的话,会从两者的共同祖先开始进行一个三方合并;

  • (3)合并冲突:git会自动进行相关合并,如果合并冲突的话,冲突的文件会在Unmerged paths项目下,手动解决这些冲突(git mergetool会调用图形化的合并工具),然后再暂存提交这些修改,提交后合并就结束了;

git push
  • git push origin master: #将本地的master分支推送到远程分支(可以新建)上去
  • git fetch origin #通过fetch会把服务器上的分支信息同步下来,
    git merge origin/ #然后用将远程分支的修改合并到本地分支
  • git checkout -b origin/ #上面同步得到的origin/是一个你不能本地修改的远程分支,如果本地需要基于其修改,就必须依据其创建本地分支;同时此时本地的是跟踪远程的origin/的,可以简略git pull/push不加远程和分支名进行操作;
  • git push origin : #删除远程分支
git rebase (衍合)
  • git rebase master #将特新分支在master分支上衍合一遍
    git rebase –continue #如果有冲突会停止,此时手动修改,然后git add,再用这个命令继续衍合
    git checkout master && git merge #衍合后两个分支进行快进合并
    git branch -d #不包含其它数据了
  • git cherry-pick 2faf37cd1e57efacd11581ae1ae1175687c53a6c #只挑选某个感兴趣的提交来衍合
  • (1)针对两个分支,一种操作是merge,还有就是rebase.rebase的原理就是从两个分支的共同祖先开始,让需要衍合的分支从此处开始依次后续的提交生成相应的补丁,然后在基底分支(master)最后一个提交开始逐个应用上述补丁,在master之后生成一系列新的提交对象,从而成为了master的直接下游,master进行一次Fast-Forward就可以了.其好处是master可以看到一个清晰的提交历史,仿佛是在一个分支上的连续操作产生的.

  • (2)如果你要跟别人提交补丁,也最好使用衍合,你的补丁在origin/master最新代码上生成补丁,维护者只需要根据你的提交进行一次快进合并就可以了,将冲突等问题由你自己解决了.

  • (3)注意:你衍合的应该是你未公布的提交,否则别人之前同步了你的修改,然后你再发布衍合的提交,其实是相同的内容做了两次不同的提交,那么别人不断同步你的更新时候,代码仓库就会乱套.

git stash
  • git stash #保存当前的工作状态(包括跟踪被更改的文件和暂存的文件,未被跟踪的修改不会被保存)
  • git stash list #查看所有被保存的stash
  • git stash pop/apply #应用暂存数据,默认的情况是所有的更改被应用到跟踪修改状态,如果想让之前暂存的修改仍然在暂存中,添加使用–index参数.
  • git stash drop #删除对应的暂存
  • git stash show -p stash@{0} | git apply -R #取消暂存的修改,相当与unapply的效果
  • git stash branch #可以在你stash save时候的提交开始创建一个分支,然后将存储应用之,并删除存储
git修改提交
  • git rebase -i HEAD~3 #进入选择的编辑窗口

    • 需要修改提交注释的改为edit;
    • 可以重排顺序,就修改了提交顺序;
    • 删除某一项,就删除了那个提交本身;
    • squash合并到前一个提交,如果有多个要合并,接连用squash;
    • edit还可以拆分某个修改,git reset HEAD^将修改撤出,然后慢慢添加到暂存区慢慢提交;
    • 然后交互用git commit –amend, git rebase –continue逐步完成(与git log反序显示,实际上是从过去某个点慢慢重新提交这个过程)
  • (1)注意,这里修改的提交必须是没有同步到远程仓库的提交,否则会给别人带来困扰

git bisect
  • git bisect start #当前HEAD开始
    git bisect bad #设置当前HEAD的bad状态
    git bisect good [tag-name/commit-id…] #设定之前一个正常提交开始
  • git bisect start HEAD v1.0 #简化了上面的操作,设置二分查找的范围
    git bisect run test-error-not-zero.sh #脚本测试,正确返回0,错误返回非0
  • git bisect reset #切记要恢复HEAD值
git submodule
git svn
  • git svn clone svn://gcc.gnu.org/svn/gcc -T trunk -b branches -t tags
    git svn clone svn://gcc.gnu.org/svn/gcc -s #与上面等价,注意这里的路径,一般svn的项目根目录会有trunk,branches,tags等目录,如果你对整个项目都有权限的时候,才可以这样,如果你只对trunk某个目录有权限,就不能这么做了
  • git svn clone svn://gcc.gnu.org/svn/gcc/config #没有项目的根权限
  • git svn dcommit #向服务器推送更新
  • git svn rebase #向服务器拉取更新,时时运行他保证本地代码更新的

三、git其它

git alias
  • git config –global alias.co checkout
  • git config –global alias.st status
  • git config –global alias.last ‘log -p -1 HEAD’
发布自己的GPG(实际是将公钥信息存储在一个tag中)
  • gpg -a –export C0CC5261 | git hash-object -w –stdin
    git tag -a maintainer-pgp-pub 687224919a16ae0dcc4fb4aace4b2228a59805f1
    git push –tags
    git show maintainer-pgp-pub | gpg –import #别人导入你的公钥
代码发布
  • git archive master –prefix=’git_test’ | gzip > git describe master.tar.gz
    git archive master –prefix=’git_test’ –format=zip > git describe master.zip
git配置
  • git config –global credential.helper cache
  • git config –global user.signingKey C0CC5261
  • git config –global color.ui true
  • git config –global core.autocrlf input

四、感言

  git作为新生一代版本控制工具的代表,各种概念颠覆了传统的版本控制工具,虽然其看似复杂,但是如果能理解并熟练掌握,则可以大大提高开发和项目管理的效率。一般来说,越是历史悠久、传统保守、对代码掌控越严格的公司,其版本控制工具也越保守,使用如IBM Clearcase、Subversion、SVN等等。现在一般公司用Subversion的比较多,可以试着使用git-svn,虽然不如原生的git那么强大,但基本本地的功能都还能用。

本文完!

参考