简介
- 2005年由Linus Torvalds为管理Linux Kernel代码而开发
- 随着GitHub等开源社区网站的推动,Git已经统治代码管理工具市场
- 基于Git衍生出了众多高效的工作流程与研发管理平台
特点
离线
- 分布式代码库,每个本地库都是远程仓库的克隆(clone)
- 提交到暂存区,查看历史版本记录,创建项目分支等都不需要联网
- 进行所有代码库操作,开发者拥有极大自由
存储方式
- 内容按元数据方式存储
- 资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里,体积很小
并行
- 一个任务一个本地分支,开发新功能不耽误加入紧急bug修复的任务
- 大家都可以有自己的分支,改完推到服务器合并,不必受一条主干的约束
数据完整性
- 使用 SHA-1 算法计算数据的校验和,通过对文件的内容或目录的结构计算出一个 SHA-1 哈希值,作为指纹字符串。
- 所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。
快
- 分支、切换、合并,查看历史,diff均为毫秒级响应
- 直接记录快照,而非差异比较。若文件没有变化,Git 不会再次保存。
重要操作和心得
本地分支/远程分支/跟踪分支/远程仓库
- 远程分支:对远程仓库的引用(指针),如果不与远程仓库通信,不会更新。
- 远程仓库:远程服务器
- 本地分支:在本地自己创建的分支,我们在本地分支上工作。
- 跟踪分支:本地分支与远程分支之间,建立的一种追踪关系。比如,在git clone的时候,所有本地分支默认与远程主机的同名分支,建立追踪关系,也就是说,本地的master分支自动”追踪”origin/master分支。
git branch -vv
git branch --set-upstream
- HEAD指针:指向正在工作的本地分支,即指向最新的提交。进行checkout切换分支,其实就是修改的HEAD指针的指向而已。
git fetch/git pull
git fetch
从远程获取最新版本,也就是更新远程分支,与远程仓库同步。git pull
从远程获取最新版本并merge到本地。git pull = git fetch + git merge
- 对代码不是很了解时不是太建议直接使用
git pull
- 如果当前分支只有一个追踪分支,后面的参数可省略。
git merge/git rebase
merge和rebase都是用来合并分支的,但原理稍有不同
- 使用merge命令合并分支,解决完冲突,执行
git add
和git commit -m'fix conflict'
这个时候会产生一个commit。 - 使用rebase命令合并分支,解决完冲突,执行
git add
和git rebase --continue
,不会产生额外的commit。这样的好处是‘干净’,分支上不会有无意义的解决分支的commit。 - 采用merge和rebase后,git log的区别,merge命令不会保留merge的分支的commit
合并前:
D---E master
/
A---B---C---F origin/master
使用 merge 合并后:
D--------E
/ \
A---B---C---F----G master, origin/master
如果是 rebase 的方式,就不会有 G 合并点:
A---B---C---F---D'---E' master, origin/master
- rebase会把”master”分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到”.git/rebase”目录中),然后把”master”分支更新 为最新的”origin/master”分支,最后把保存的这些补丁应用到”master”分支上。
- 注意到,其中 D’, E’ 的 commit SHA 序号跟本來 D, E 是不同的,应为算是砍掉重新 commit 了。而且commit的时间先后顺序也不同。
git stash
- 当你正在做一项复杂的工作时, 发现了一个和当前工作不相关但是又很讨厌的bug. 你这时想先修复bug再做手头的工作, 那么就可以用 git stash 来保存当前的工作状态, 等你修复完bug后,执行’反储藏'(git pop/git stash apply)操作就可以回到之前的工作里。
- 不需要先commit手头工作之后再去修复bug,从而减少不必要的commit记录。
git cheery pick
- 可以选择某一个分支中的一个或几个commit来进行操作
- 用法:
git cherry-pick commitID
- 通过git log查看文档,找出要使用的commitID
- 若出现冲突,就跟普通的冲突一样,手工解决
同名但不同意义
git checkout -- file
撤销对工作区修改git reset HEAD -- file
清空add命令向暂存区提交的关于file文件的修改(Ustage)git reset --hard
回退到之前的commit(版本回退)
冲突
不管是svn还是git都要处理好冲突。
git pull
git merge
git rebase
git pop
git stash apply
等操作都可能产生冲突。处理冲突的方法都是一样的。
举个栗子:
如果系统中有一些配置文件在服务器上做了配置修改,然后后续开发又新添加一些配置项的时候,
在发布这个配置文件的时候,会发生代码冲突:
error: Your local changes to the following files would be overwritten by merge:
protected/config/main.php
Please, commit your changes or stash them before you can merge.
1.修复实名认证需求个人中心页面渲染和订阅邮箱bug
2.完成工单系统最大字数限制优化的需求
如果希望保留生产服务器上所做的改动,仅仅并入新配置项, 处理方法如下:
git stash
git pull
git stash pop
然后可以使用Git diff -w +文件名 来确认代码自动合并的情况.
此时提示产生冲突的话
git status
查看
冲突产生后,文件系统中冲突了的文件里面的内容会显示为类似下面这样:
a123
<<<<<<< HEAD
b789
=======
b45678910
>>>>>>> 6853e5ff961e684d3a6c02d4d06183b5ff330dcc
其中:冲突标记<<<<<<< (7个<)与=======之间的内容是我的修改,=======与>>>>>>>之间的内容是别人的修改。
之后再
git add
,
git commit
git 自定义命令
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.st status
git revert/git reset
git revert
是生成一个新的提交来撤销某次提交,此次提交之前的commit都会被保留。HEAD指针继续前进git reset
是回到某次提交,提交及之前的commit都会被保留,但是此次之后的修改都会被退回到暂存区。HEAD指针向后移动git reset –soft
回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可git reset –hard
彻底回退到某个版本,本地的源码也会变为上一个版本
git clean
- 用来从你的工作目录中删除所有没有tracked过的文件
- 经常和
git reset –hard
一起结合使用。reset只影响被track过的文件, 所以需要clean来删除没有track过的文件。 结合使用这两个命令能让你的工作目录完全回到一个指定的状态