Git 是用C写的一个分布式版本控制系统。
集中式 VS 分布式
集中式版本控制系统必须联网才能工作。
分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库。
多个人如何协作只需把各自的修改推送给对方,就可以互相看到对方的修改了。
和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多。Git的优势不单是不必联网还有极其强大的分支管理,把SVN等远远抛在了后面。
GIT 的组成部分:工作区、版本库、储藏区、暂存区;
版本回退
- HEAD指向的版本就是当前版本,使用命令切换不同版本git reset --hard commit_id。
- 用git log可以查看提交历史,以便确定要回退到哪个版本。
- 用git reflog查看命令历史,以便确定要回到较新的版本。
工作区和暂存区
把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用
git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用
git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
如果没有add ,commit 时是不会将变动提交到版本库的,需注意。
撤销修改
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令
git checkout -- file
。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令
git reset HEAD file
,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考
版本回退
,不过前提是没有推送到远程库。
删除文件
命令
git rm
用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失
最近一次提交后你修改的内容
。
远程仓库
要关联一个远程库,使用命令
git remote add origin git@server-name:path/repo-name.git
;
关联后,使用命令
git push -u origin master
第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令
git push origin master
推送最新修改;
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作
远程仓库克隆
要克隆一个仓库,首先必须知道仓库的地址,然后使用
git clone
命令克隆。
Git支持多种协议,包括
https
,但通过
ssh
支持的原生
git
协议速度最快。
创建与合并分支
Git鼓励大量使用分支:
查看分支:
git branch
创建分支:
git branch <name>
切换分支:
git checkout <name>
创建+切换分支:
git checkout -b <name>
合并某分支到当前分支:
git merge <name>
删除分支:
git branch -d <name>
合并分支
git merge dev
将dev 分支合并到当前分支
用带参数的
git log
也可以看到分支的合并情况:
git log --graph --pretty=oneline --abbrev-commit
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
用
git log --graph
命令可以看到分支合并图。
分支管理策略
合并分支时,如果可能,Git会用
Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用
Fast forward
模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
下面我们实战一下
--no-ff
方式的
git merge
:
准备合并
dev
分支,请注意
--no-ff
参数,表示禁用
Fast forward
:
$
git merge --no-ff -m
"merge with no-ff"
dev
把commit描述写进去。
合并后,我们用
git log
看看分支历史:
$ git log --graph --pretty=oneline --abbrev-commit*
7825
a50 merge
with
no-ff|\| *
6224937
add merge|/*
59
bc1cb conflict fixed...
可以看到,不使用
Fast forward
模式,merge后就像这样:
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,
master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在
dev
分支上,也就是说,
dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把
dev
分支合并到
master
上,在
master
分支发布1.0版本;
你和你的小伙伴们每个人都在
dev
分支上干活,每个人都有自己的分支,时不时地往
dev
分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
合并分支时,加上
--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而
fast forward
合并就看不出来曾经做过合并。
Bug分支
bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
当你接到一个修复bug的任务时,很自然地,你想创建一个分支来修复它,但是,当前正在
dev
上进行的工作还没有提交:
$
git status
怎么办?
Git还提供了一个
stash
功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
$
git stash
修复完成后,并完成合并,最后删除
issue-101
分支:
$
git checkout dev
Switched
to branch
'dev'
$
git status
用
git stash list
命令恢复储藏内容:
$
git stash liststash@{
0
}
:
WIP
on
dev:
6224937
add merge
需要恢复一下,有两个办法:
一是用
git stash apply
恢复,但是恢复后,stash内容并不删除,你需要用
git stash drop
来删除;
另一种方式是用
git stash pop
,恢复的同时把stash内容也删了:
$
git stash pop
再用
git stash list
查看,就看不到任何stash内容了:
$
git stash list
你可以多次stash,恢复的时候,先用
git stash list
查看,然后恢复指定的stash,用命令:
$
git stash apply stash@{
0
}
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场
git stash
一下,然后去修复bug,修复后,再
git stash pop
,回到工作现场。
Feature分支
开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过
git branch -D <name>
强行删除。
多人协作
- 查看远程库信息,使用git remote -v;
- 本地新建的分支如果不推送到远程,对其他人就是不可见的;
- 从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
- 在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
- 建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
- 从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
标签管理
- 命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id;
- git tag -a <tagname> -m "blablabla..."可以指定标签信息;
- git tag -s <tagname> -m "blablabla..."可以用PGP签名标签;
- 命令giit tag可以查看所有标签。
- 命令git push origin <tagname>可以推送一个本地标签;
- 命令git push origin --tags可以推送全部未推送过的本地标签;
- 命令git tag -d <tagname>可以删除一个本地标签;
- 命令git push origin :refs/tags/<tagname>可以删除一个远程标签。
使用GitHub
- 在GitHub上,可以任意Fork开源仓库;
- 自己拥有Fork后的仓库的读写权限;
- 可以推送pull request给官方仓库来贡献代码。
使用码云
使用GitHub时,国内的用户经常遇到的问题是访问速度太慢,有时候还会出现无法连接的情况(原因你懂的)。
和GitHub相比,码云也提供免费的Git仓库。此外,还集成了代码质量检测、项目演示等功能。对于团队协作开发,码云还提供了项目管理、代码托管、文档管理的服务,5人以下小团队免费。
本地库关联码云和github
本地库关联远程库时需要注意远程库名称 不能都叫 origin
用
git remote -v
查看远程库信息:
删除已有的远程库:
git remote rm origin
git本身是分布式版本控制系统,可以同步到另外一个远程库,当然也可以同步到另外两个远程库。
使用多个远程库时,我们要注意,git给远程库起的默认名称是
origin
,如果有多个远程库,我们需要用不同的名称来标识不同的远程库。
git remote add github git
@github
.
com:
michaelliao/learngit.git
注意,远程库的名称叫
github
,不叫
origin
了。
接着,再关联码云的远程库:
git remote add gitee git
@gitee
.
com:
360linker/360linker.git
同样注意,远程库的名称叫
gitee
,不叫
origin
。
现在,我们用
git remote -v
查看远程库信息,可以看到两个远程库:
git remote -vgitee git
@gitee
.
com:
360linker/learngit.git (fetch)gitee git
@gitee
.
com:
360linker/learngit.git (push)github git
@github
.
com:
360linker/learngit.git (fetch)github git
@github
.
com:
360linker/learngit.git (push)
如果要推送到GitHub,使用命令:
git push github master
如果要推送到码云,使用命令:
git push gitee master
这样一来,我们的本地库就可以同时与多个远程库互相同步:
忽略文件
- 忽略某些文件时,需要编写.gitignore;
- .gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理
、配置别名、搭建git 服务器等需要深入了解的小伙伴自行学习。
=================================END===========================
360linker是一个分享IT 圈内 市场、技术、产品、运营 等信息的技术社区。在技术更新换代如此之快的当前,达到高效的的技能的提升,欢迎更多的小伙伴加入。扫描下方二维码或者添加微信 li_360linker,备注IT。