注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

网易杭研后台技术中心的博客

 
 
 
 
 

日志

 
 

GIT常用命令使用笔记  

来自genww   2013-04-11 13:35:18|  分类: 代码管理 |举报 |字号 订阅

  下载LOFTER 我的照片书  |
概述

git的相关网站:

http://git-scm.com/

git与svn的主要区别

1.git的服务端仓库要比svn要小很多
2.分支代价小,svn分支是一份拷贝,而git分支是一棵树,包含了整个历史
3.合并容易,不需要记住分支版本号和复杂操作
4.备份简单,有几个开发人员就有几个备份

git仓库模型

与svn最主要的区别在于大多数VCS(如svn)都是保存基于文件变化的列表数据,如p1.png。但是git不是这样的,当你提交一个版本状态到git时,相当于做了一个镜像,这个镜像保持和你提交的内容一致,为了高效,如果某个文件未改动,则git不会再在镜像中保存重复的文件,而是link到之前已存储的文件如p2.png

git使用sha-1来check区分文件,实际上git保存所有数据都是依据该hash而不是使用文件名。

在git的所有操作中,都是对git数据库的增加操作,包括删除文件等操作,这是为了保证所有的操作都能够undo

git3个状态
committed:表示数据已安全的递交到本地database
modified:表示你更新了文件数据但还未提交(实际上也还没stage)
staged:表示你标记了当前版本modified的文件到准备要commit的镜像
注意:
1.未tracked的文件不属于上面任意一种状态(未add),文件状态关系如p4.png
2.如果把属于staged状态的文件再次修改,则运行git status则会在modified和staged两个list中都显示出来,如果commit则只会提交你上次staged状态的文件,如果提交最新更改,则需要重新git add到staged状态
这将让git工程产生三个部分(存放在三个位置中):
git directory:存放git工程的meta信息和对象database,也是你从其他计算机clone一个repository到本地的地方
working directory:git工程中一个独立版本的check out,用于在上面进行开发
staging area:它是一个简单的文件,包含了git directory信息,也包含了在下次commit中要提交的文件的索引信息
一般基本的git工作流程是(p3.png):
1.你在working directory修改文件
2.你stage这些文件到staging area
3.做提交,它会将staging area描述的文件提交到git directory中


git分支对象模型
(http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is):
当git提交后,它将生成这些对象,并打成一个snapshot:
blob:用于存放具体文件数据
tree:用于存放提交的文件列表及sha-1,并指向对应的blob
commit:用于存放提交信息如commit,用户等,并指向对应的tree
然后:
1.如果你再次提交,下次提交的commit对象将保存上次提交的commit对象位置,这样依次形成一个commit链,git把commit链前面的snapshot称为下游,当提交新的commit后,追加到链中的新的snapshot为上游
2.初始的branch,一般为master,会指向这个commit链的链尾
3.如果你创建一个新的分支(git branch myBranch1),它将会创建一个新的和当前分支一样都指向同一个链的分支。
4.git如何知道当前分支是什么?通过HEAD(和svn中HEAD不同),它用于指示当前工作的分支是哪条。如果你新建了一个分支。默认情况下,HEAD还是指向的之前工作分支(master)而不是你新建的分支(myBranch1)
5.如果要切换当前工作分支为myBranch,则需要git checkout testing。这时HEAD将指向myBranch1。当你下次提交后,新的分支将始终指向你最后提交的commit链的链尾,而master分支指向的commit链的snapshot位置将不再改变
6.如果再切回到master,则git会做两件事,吧master指向的commit链中的snapshot恢复到working copy中,同时HEAD指向master。若这是再提交新的变化,这时整个commit链才会真正分叉
7.merge分两种情况:假设有master分支和hotfix分支,当你调用git merge hotfix时
若hotfix分支指向的snapshot是在master分支指向的snapshot上游:实际上git简单的将当前分支的指向切换到了和hotfix的指向相同snapshot上。在git中该merge叫Fast forward
若hotfix分支和master分支是两个不同分支:则在合并时git会创建一个新的snapshot,并指向这两个分支(该snapshot有两个父亲)。该snapshot会自动取两个分支中最优的父亲作为母本,把另个父亲不同的部分合并进来。如果遇到冲突,它将不会提交这次合并,你需要git status来查看冲突的文件,它会把冲突变化放在冲突文件里(和svn冲突后类似)。当你解决了冲突文件后,用git add命令标示已解决。最后git commit
8.对于远程来讲,如果远程有master分支,你clone下来后,在本地标示的就是origin/master分支。这意味着若远程master分支指向变更了后,本地的origin/master分支不会变更,这时如果想同步远程的master分支,则使用git fetch origin。它会获取本地没有的数据更新到本地数据库,移动origin/master分支到和远程一致的snapshot位置。通过这种方法,可以使本地reportory能够关联(git remote add)多个远程服务器(则另一个远程服务器对应的分支就是origin2/master),即多个远程branch。
9.由于本地可以关联多个远程的branch,故需要指定哪个远程branch是track的,这样当用户git push和git pull时git就能识别对应的远程branch是哪个。默认情况下,当clone后git会自动创建master的分支来tracks对应的origin/master分支


git版本

MsysGit:常用
tortosiseGit:速度较慢且ui经常失效

git推荐使用方式:用gui查看变动,用命令行做其他操作

安装

ubuntu:
sudo apt-get install git
centos:
yum install git
windows:
http://msysgit.github.com

配置

//配置git-completion
# msysgit不需要
PS1=
GIT_PS1_SHOWDIRTYSTATE="true"
GIT_PS1_SHOWSTASHSTATE="true"
GIT_PS1_SHOWUNTRACKEDFILES="true"
GIT_PS1_SHOWUPSTREAM="auto"
EDITOR=vim #指定git编辑用的editor,也可配置config来指定

//配置git config
linux下系统配置在/etc/gitconfig,用户配置在~/.gitconfig,仓库配置在对应的git repertory下的.git/config
window下系统配置%USERPROFILE%

//配置用户:当第一次使用git时需要指定用户:
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
//如果使用ssh验证则还要配置对应的私钥
如果是rsa算法的私钥,将自己的private key放在~/ssh/id_rsa即可


// 配置editor
git config --global core.editor emacs
// 配置diff tool
git config --global merge.tool vimdiff

//配置简写
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.unstage 'reset HEAD --'
$ git config --global alias.visual '!gitk' #前面加!表示执行外部shell命令
这样你可以用git ci来代替git commit

// 配置git忽略的文件,配置文件为.gitignore。格式如下:
1.#开头的为注释,git会忽略该注释
2.支持标准的glob格式
3.在格式最后加"/"表示指定为目录
4.可以取反,使用!符号
下面举例(.gitignore文件内容):
# a comment - this is ignored
*.a       # no .a files
!lib.a    # but do track lib.a, even though you're ignoring .a files above
/TODO     # only ignore the root TODO file, not subdir/TODO
build/    # ignore all files in the build/ directory
doc/*.txt # ignore doc/notes.txt, but not doc/server/arch.txt

//配置git命令自动补全功能(auto-completion)
1.找到git源码下的contrib/completion目录,把git-completion.bash复制到你的家目录,然后配置~/.bashrc中添加:source ~/.git-completion.bash
2.如果想所有用户都有自动补全则,则复制git-completion.bash到/etc/bash_completion.d/(linux)或/opt/local/etc/bash_completion.d(mac os)


git命令参考

//配置系统信息(保存在/etc/gitconfig)
git config --system xxx xxx
//配置用户信息
git config --global xxx xxx

// 显示配置内容
git config --list
git config xxx 显示配置的key为xxx的内容

//新建仓库
进入目录:git init
git init 目录名

//克隆仓库(注意与svn的checkout区别,它将获得整个提交历史仓库,包括comment。都将放在.svn仓库里。同时会checkout一个最新版的working copy)支持ssh,git,https等各种协议
git clone https://xxx.com/xxx/bar.git
//可指定其他目录
git clone git://github.com/schacon/grit.git mygrit

//查看工作目录状态和修改内容(文件属于哪些状态:untracked,modified,delete等,当前的working copy属于哪个分支)
git status

//把修改的内容放到暂存区(该操作实际可以实现多种目的:使文件由untracked或modified状态变成stage状态,或把冲突的文件标记为resolved。开始version controll)
git add [文件名|目录名]

//把stage状态中的文件恢复为unstage状态
git reset HEAD xxx.txt
git reset xxxx #把当前分支的指向指到另一个snapshot上,并更新stage。如果--hard则工作目录也更新,如果--soft则stage也不变
git reset --hard HEAD~ 恢复到最新更新的前一次更新HEAD~表示最新版本的前一次版本

//查看变动(working copy与stage比较)
git diff 查看全局变动
git diff v0.1
git diff v0.1..v0.2
git diff master...devel

//查看暂存区的diff(stage与snapshot比较)
git diff --cached
//git1.6.1以后用
git diff --staged

//查看文件每行的最后变动
git blame [master|v0.1|...] --path 



//提交暂存区内容到本地仓库,shell下会弹出editor来编写comment,同时会有注释来展示当前的status(加-v参数则展示diff),保存后将会连comment一起提交,否则会取消本次commit
git commit [-v]
git commit -m "submit1" #直接加注释提交
git commit -a #自动将所有tracked文件放入stage并提交(你可以忽略git add部分)
git commit --amend #追加内容或修改内容到上次提交,换句话说就是上次提交的内容改变了

//删除(它将删除working copy、并提交变动到stage区域)
git rm
git rm -f #如果有stage的文件要删除,则需要添加-f参数
git rm --cached xxx.txt #清除statge中的文件
git rm log/\*.log # 删除目录log下*.log的所有文件。注意转义\可在window下省略,在linux下git在自己的命令参数下,故需要加上

//移动文件(git不直接记录mv操作,实际上他做了三个命令:mv a1 a2,git rm a1,git add a2)
git mv f1.txt f2.txt

//分支
git branch #查看分支
git branch 分支名 #新建分支
git branch -d hotfix #删除分支
git branch -v #显示所有分支最后提交的comment
git branch --merged #查看merged 的分支,或--no-merged查看未merged的分支

git checkout 分支名 # 切换分支
git checkout -b 分支名 # branch+切换分支
git checkout [标签|SHA-1] #切换到匿名分支
git checkout --track origin/serverfix #切换当前分支track的远程分支为origin/serverfix
git checkout -b sf origin/serverfix #和上面类似,指定了本地分支sf取track远程分支origin/serverfix


//git的checkout还用于从本地的repertory取最新的版本到working copy中。一般用于恢复modified状态的文件为unmodified
git checkout -- xxx.txt

//合并
git merge 另一个分支
git mergetool 使用图形界面来处理合并操作

//查看提交日志
git log -p -2 # 显示所有提交记录-p表示显示diff,-2显示最后2个实例
git log --stat # 显示提交摘要:多少文件添加,多少文件修改,多少文件删除
git log --pretty=oneline #以一行格式显示,类似的还有short,full,fuller
git log --pretty=format:"%h - %an, %ar : %s" #按格式显示,格式内容参见附录1
git log --pretty=format:"%h %s" --graph #显示分支树
git log --since=2.weeks # 显示最后2周
gitk 使用图形界面查看log


//推送到其他节点
//获取远程url信息
git remote -v

//对于新建库(需ssh)
git remote add origin ssh://xxx.com/sss/bar.git #添加远程repository,其中origin是别名(在同一个git directory可以支持多个远程repository,在fetch的时候选择具体要fetch的别名,对于git clone时,会默认rit remote add一个origin的url到当前目录。)
git remote show origin #查看远程信息(包括remote branch,tracked branch等)
git remote rename origin paul #修改别名
git remote rm paul #删除引用paul


//对于克隆的仓库
git push
git push [-u] origin master

//跟踪上游
git fetch origin #获取远程数据,origin是别名(参见git remote add注释)。注意它只取远程数据到本地,并自动merge
git merge origin #把分支origin合并到当前分支
git pull #如果你的分支track了远程的分支,则该命令可以自动fetch并merge到你当前分支中(默认git clone会自动使本地分支取track远程分支)
git push origin master #将本地master分支推到origin服务器上(本地repository备份到远程)
git push origin master:master2 #将本地master分支提交到服务器,更新服务器的分支名称为master2
git push origin :master2 #删除远程分支master2

//打tag(标记版本)
git tag #显示可用的tag列表
git tag -l 'v1.4.2.*' #选择性的显示tag
git tag v1.3-lw #创建一个轻量级的tag,该tag值保存tag值,不保存其他信息
git tag -a v1.4 -m 'my version 1.4' #创建一个annotated tag(会存储该对象的全部git数据库),版本v1.4
git show v1.4 #显示 tag 信息
git push origin v1.5 #默认情况下push命令不传输tags信息到远程server,你要显示的调用该命令
git push origin -- tags # 和上面类似,push所有tag
//----------------常见使用流程:
//创建一个新的本地reopsitory
git init
git add .
git commit -m 'initial project version'

附录

附录1:git log --pretty=format格式内容

Option  Description of Output
%H  Commit hash
%h  Abbreviated commit hash
%T  Tree hash
%t  Abbreviated tree hash
%P  Parent hashes
%p  Abbreviated parent hashes
%an Author name
%ae Author e-mail
%ad Author date (format respects the --date= option)
%ar Author date, relative
%cn Committer name
%ce Committer email
%cd Committer date
%cr Committer date, relative
%s  Subject

附录2

其他功能:
//rebase:
另一种merge方式http://git-scm.com/book/en/Git-Branching-Rebasing#The-Basic-Rebase

//subModules:
//添加submodule到你的工程中
git submodule add git://github.com/chneukirchen/rack.git rack

它会创建(创建的文件可提交):
.gitmodules文件:且需要被版本控制,以便其他用户也能够知道子模块
track目录:在working copy中是表现成目录,但是git认为它是一个子模块且如果你不在子目录中提交的话父modeule不会跟踪里面的数据。如果你在该目录中修改并提交的话,子工程会感知具体的变化并提交。这意味着在父工程中你无法去操作和提交子工程的内容

//如果clone一个包含submodule的工程时,你进入到submodule里面会发现目录为空,你需要进入目录下,做如下操作:
git submodule init #初始化本地配置
git submodule update #获取所有数据(每次拉数据到submodule时需要执行一下)

使用submodule警告:
//如果你创建了一个branch,并创建了一个submodules,如果你转换回原branch(没有submodlues的branch),则working copy中还是会有那个submodules留下的目录。你要手动删除。
//如果你把原来工程的一个子目录改为submodules时,除了注意删除原目录需要git rm外。弄好后,一旦哪天你想从包含submodules的branch切回到包含原子目录的branch时,再切回之前你需要手动mv。

  评论这张
 
阅读(847)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017