Git命令多且灵活,可以写本厚厚的宝典了,但不必成为Git专家,满足常用开发需要才是咱的目的。以前也在使用Git,但过于浅显,且和svn同质化了,现在需要加深对Git的掌握。本文未完待续,以后在实际使用Git过程中会更新本文……
Git版本控制的基本思路
大的方面来说,Git、SVN、Hg、CVS等各种VCS(版本控制系统)的思路是有区别的。
Git的特点是:具有与众不同的分布式特点(即支持离线),可选支持其他VCS都支持的中心式特点。
中心式的好处很明显,这将允许多人协同工作,协同工作时中心节点(服务器)将必须存在,这是所有VCS的首要初衷,所以,这不是Git的优势,只是分内事而已。Git的分布式是这样设计的:除了在线同步操作,其他操作都可以在本地版本库上离线进行,无需中心服务器在线,而同步为最新版本之后,本地版本库将拥有一切版本历史记录,每个人以及服务器上的版本库拷贝都是完整且相同的。
Git的分布式设计给它带来的优势:A,版本库的完整备份将十分方便,而不必担心纯中心式VCS下中心服务器的损坏;B,支持离线,所以,你可以在无法连接中心服务器的离线情况下进行版本控制,比如提交/保存版本、版本间差异对比、追溯文件修改等等;C,支持离线,所以,除了上传操作都非常快速。
当然,除此之外,Git对版本控制的理解和实现细节上也和其他VCS有区别,这些区别是优点还是缺点,颇有争议,总的来说,Git的分布式设计,使其成为目前最优秀的VCS。
小的方面来说,Git对版本控制的实现是这样的。
要建立个人使用版本库的话,只需在本地初始化一个就可以了。这个做法拥有Git的必选分布式特性,丢弃了中心式这个可选特性,也就无法享受中心式带来的多人协作优点了。
要建立多人协作版本库的话,可以先本地建立离线式的版本库,再绑定到远程中心服务器,也可以在远程中心服务器建立版本库,再克隆到本地。这个做法将可以享受Git的所有特性。
一个版本库中的文件并不默认就会被纳入版本控制,而需要先人为确定是否进行跟踪,跟踪就是纳入版本控制的意思,多数后续工作一般都会忽略不被跟踪的文件,任之由之。跟踪之后,需要进行提交(Commit),提交就是保持版本的意思,由于Git是分布式的,所以提交实际上提交在本地,并没有同步到远程。提交之后,就可以同步到远程了,称之为上传(Push),这个动作时可选的,也可以在多次提交之后再进行这一动作。
Git关键概念
版本(version):每次提交就是一个版本。
跟踪(add):纳入版本控制系统管理的文件就是被跟踪了,大部分操作都是只针对被跟踪的文件,一般,临时中间文件无需被跟踪,比如编译过程中的obj、ncb等文件,这些文件体积大,没有保存价值。这应当就是设计跟踪这一操作的意图之一——可以人为选择哪些文件需要纳入管理。
别名(remote):git remote add
命令中首先出现的,它实际上是个远程url的缩写代号,免去记忆url,它默认为origin
分支(branch):下面有具体介绍
标签(tag):暂时用不着
缓存(cached):尚未commit提交的本地修改就是缓存
获取(fetch):从远程仓库拉取到本地,并缓存到一个名为tmp的分支
合并(merge):把一个分支的内容/修改合并到另一个分支上
撤销(revert):就是撤销
提交(commit):一次代码快照,所不同的是,其他VCS中的一次commit往往保存的是代码的差异
上传(push):把本地仓库的修改上传到远程仓库
分支
分支的价值
分支是N个代码提交快照所连接成的有向无环图。一个项目中可以不使用分支,但看明白下图,相信你也就明白使用分支的好处和必要性了。
E----F ("hotfix-001/issue-001")
/ \
A-----C----G----H---J ("master/stable")
\ /
B-----D-----I----K ("next/develop/new-idea")
1
2
3
4
5
E----F
("hotfix-001/issue-001")
/
\
A-----C----G----H---J ("master/stable")
\/
B-----D-----I----K
("next/develop/new-idea")
用master或stable分支保存发布到生产环境中的经过严格测试的稳定版本;用临时分支hotfix-***或者issue-***修复客户反馈的bug,测试通过后再合并入master分支,并发布到生产环境;用next或develop之类的分支来做开发预览,严格测试使用一段时间确保稳定后,再合并入master或stable分支。当然,客户的定制版也可以从master分支上分离新建出新的小分支。这就是分支存在的价值,Git中推荐多多使用分支。
本地分支与远程分支
git push origin test:master
会有这样的用法,也就是说,可以跨分支push或者在远程仓库和本地仓库中对实质上的同一分支使用不同的分支名,这是不被推荐的,会增加混淆,所以,本地分支名和远程分支名请注意保持一致,分支间的合并也要现在本地进行完毕再push到远程。
常用操作
克隆已有的远程版本库到本地版本库
Git GUI:克隆已有版本库
Git Bash:git clone
创建本地版本库,并上传到远程版本库
Git GUI:创建新的版本库 | 跟踪 | 提交 |
上传,具体跟踪、提交、上传操作请参考下文
Git Bash:git
init #初始化本地版本库
git remote add
#把本地版本库添加到远程版本库,所谓remote,实际上是url的别名/缩写代号,就是说下次提交代码就直接使用别名而不是长长的url了,别名默认是origin
重命名远程仓库
Git GUI:
Git Bash:git remote
rename
删除远程仓库
Git GUI:
Git Bash:git remote rm
查看改动
Git
GUI:进入首页就可以看到改动,未缓存的改动和已缓存的改动分别在左侧两个列表中,其中,文件名前面不同的ICON代表不同的改动
Git Bash:git status
查看远程仓库信息,可用于跟踪别人的push
Git GUI:
Git Bash:git remote show
origin
查看文件内容改动
Git GUI:点击左侧改动文件即可在右侧编辑框中看到文件内容改动
Git Bash:git diff
跟踪文件,也就是把指定文件纳入版本控制
Git
GUI:在“已缓存的改动”中,单击指定文件的前端icon,文件将被移动到“未缓存的改动”中,若要反悔,可以在“已缓存的改动”中点击文件icon
Git Bash:git add
注意:add(新增)之后还需要commit和push,才真的保存了修改,若要跟踪所有改动文件,则用.取代具体文件名
停止跟踪文件,但不删除
Git GUI:
Git Bash:git rm –cached
停止跟踪并删除文件
Git GUI:
Git Bash:git rm
撤消尚未提交的修改(未跟踪文件不受影响,未被跟踪即不在VCS管理之列)
Git GUI:“未缓存的改动”列表里选中需要撤销更改的文件 | 提交 | 撤销修改
Git Bash:git reset –hard HEAD
#撤消所有跟踪文件的未提交修改
git checkout HEAD #撤消指定跟踪文件的未提交修改
提交(未跟踪文件不受影响,未被跟踪即不在VCS管理之列,)
Git GUI:提交按钮
Git Bash:git commit -m “”
#提交跟踪文件中的所有更新
文件改名
Git GUI:
Git Bash:git mv
查看日志,也就是文件和文件内容的变更历史
Git GUI:版本库 | 图示所有分支的历史
Git Bash:git log
#查看提交历史
git log -p #查看指定文件的提交历史
git blame #以列表方式查看指定文件的提交历史
获取
Git GUI:菜单 | 远程 | 从…获取(fetch)
Git Bash:git fetch
[]
#从远程库获取代码,但不自动合并,remote默认为origin,branch默认为master
合并
Git GUI:菜单 | 合并 | 本地合并
Git Bash:git merge
#合并指定分支到当前分支
获取并合并
Git GUI:
Git Bash:git pull #获取并快速合并
上传分支
Git GUI:上传按钮
Git Bash:git push
#上传并合并,remote是url别名,branch是分支名,把branch本地分支的commit内容上传到远程同名分支
git push
: #上传并合并,本地分支名和远程分支名可以不同,如果相同,则等价于上一句
分支
git branch #创建新分支
git branch #显示所有本地分支
git branch -d #删除本地分支
git push : #删除远程分支或标签
git checkout #切换到指定分支或标签
可能会用到的常见指令
git push –tags #上传所有标签
git tag #列出所有本地标签
git tag #基于最新提交创建标签
git tag -d #删除标签
git rebase #衍合指定分支到当前分支
git remote -v #查看远程版本库信息(别名和版本库URL)
git remote show #查看指定远程版本库信息
git commit –amend #修改最后一次提交
git revert #撤消指定的提交
一个项目指定的两个版本间的差异
一个文件指定的两个版本间的差异