git
1. git简介
以前写毕业论文肯定会有如下经历:
提交给导师review之后,试着修改某些段落,又怕将来还会修改回来怎么办?于是就另存为一个新的word文档,再接着改,改到一个程度,再另存为另一个新文件,这样一直该下去,最终你的word文档变成了这样:
最要命的是,有些部分需要你的同学帮忙完成,于是把最新的版本拷贝给他。三天后,同学再把word文件传给你,此时,你必须想想发给他之后到收到这份文件期间,得把你的改动和他的部分进行合并,灰常困难。
于是乎,版本控制服务应运而生。当然这里必须说明一下word格式是二进制格式,git其实搞不了,这边只是作为一个栗子说明一下。
2. git的诞生
- 1991年Linus创建了开源的Linux,各地大牛提交代码都是使用diff的方式发给Linus。因为Linus坚决反对CVS和SVN。
- 2002年BitKeeper出于人道主义精神,授权Linux社区免费使用旗下版本控制产品。
- 2005年由于Linux社区中大批牛人试着破解BitKeeper的协议 ,于是其公司被彻底惹怒,收回了免费使用权。
- 被逼无奈,Linus花了两周的时间自己用c写了一个分布式版本控制系统,这就是Git!
3. git的好处
- 可以在不联网的情况下进行使用。包括提交代码和代码恢复等操作。
- 其他的好处暂且不理,也没看懂。
4. 创建版本库
-
通过
git init
命令把这个目录变成git可以管理的仓库。 -
编写一个readme.txt文件,该文件放在根目录下
this is a git test repository. git is free.
-
通过
git add
多次添加文件,git commit -m "add readme.txt"
将改动提交到本地仓库。
5. 修改提交
-
继续鼓捣readme.txt文件。
This is a git test repository. Git is free.
-
git status
查看仓库当前的状态。 -
git diff
查看文本变化点。 -
通过
git add
多次添加文件,git commit -m "readme.txt 行首大写"
将改动提交到本地仓库。
6. 版本回退
-
git log
查看提交日志。commit 21b433229c04ed5264ebba8968527fd3546d685d (HEAD -> master) Date: Mon Jul 9 11:03:04 2018 +0800 readme.txt 行首大写 commit f401109770227fe6dd231369afda5cb017912ba4 Date: Mon Jul 9 10:53:45 2018 +0800 add test readme.txt
-
如果嫌弃输出信息太多,看的眼花缭乱,可以试试加上
--pretty=oneline
参数。21b433229c04ed5264ebba8968527fd3546d685d (HEAD -> master) readme.txt 行首大写 f401109770227fe6dd231369afda5cb017912ba4 add test readme.txt
-
现在我想回退版本,在GIT中,用
HEAD
标识当前版本,也就是最新的提交21b433229c04ed5264ebba8968527fd3546d685d
,上一个版本是HEAD^
,上上个版本就是HEAD^^
,往上100个版本就是HEAD~100
。 -
OK,我现在要恢复到上个版本,
git reset --hard HEAD^
。HEAD 现在位于 f401109 add test readme.txt
-
我擦嘞,回退错了,想再搞回去咋整。办法还是有的,只要你的shell还没关闭,找一下刚才最新的commit id就可以了。
git reset --hard 21b433229c04ed5264ebba8968527fd3546d685d
。厉害! -
嗯,领导说还是不要大写开头,还是回退吧。好嘞,
git reset --hard HEAD^
搞定。 -
今天任务完成了,可以关机回家睡觉了。
-
第二天,领导又说想了一晚上,还是要大写开头,MD,咋整,有commit id的shell已经没有了。
git reflog
可以查看每一次操作的日志,牛逼了。如下可以找到了。git reset --hard 21b433229c04ed5264ebba8968527fd3546d685d
。f401109 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^ 21b4332 HEAD@{2}: reset: moving to 21b433229c04ed5264ebba8968527fd3546d685d f401109 (HEAD -> master) HEAD@{3}: reset: moving to HEAD^ 21b4332 HEAD@{4}: commit: readme.txt 行首大写 f401109 (HEAD -> master) HEAD@{5}: commit (initial): add test readme.txt
小结一下
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
。- 穿梭前,用
git log
可以查看提交历史,以便确定要回退到哪个版本。 - 要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
7. 工作区和暂存区
-
工作区
- 就是我们在电脑上能看到的目录。
-
版本库(repository)
-
工作去中有一个
.git
,这个不算工作区,而是git的版本库。 -
git的版本库里存了好多东西,其中最重要的就是称为stage的暂存区,还有git为我们自动创建的第一个分支
master
,以及指向master
的一个指针叫HEAD
。
- 我们之前用的
git add
其实就是把文件添加到暂存区stage。
-
git commit
其实就是把暂存区的所有内容提交到当前分支。
-
-
撤销修改
- 场景1:修改项未
git add
之前的撤销。git checkout -- readme.txt
是将readme.txt恢复到HEAD中的版本。
- 场景2:修改项1已经
git add
,但是对同一文件的修改项2并未git add
。git checkout -- readme.txt
是将readme.txt恢复到暂存区的版本,即只有修改项1的readme.txt.
- 场景3:将修改项
git add
到暂存区之后的撤销。git reset HEAD readme.txt
先将readme.txt从暂存区中回退到工作区,再做其他的操作。
- 场景1:修改项未
8. 远程仓库
git是一个分布式版本控制系统,同一个git仓库,可以分布在不同的机器上。为了大家可以协同开发,可以把一台机器充当服务器,大家以这个机器的版本为基准。这个服务器可以自己搭建,也可以使用现成的github或者gitee。
这些仓库的使用很简单,直接跳过。
9. 分支管理
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
其他版本控制系统如SVN等都有分支管理,但是用过之后你会发现,这些版本控制系统创建和切换分支比蜗牛还慢,简直让人无法忍受,结果分支功能成了摆设,大家都不去用。
1) 创建与合并分支
-
创建dev分支,并切换到新分支。
git checkout -b dev
上边的这条命令相当于以下的两条命令:
git branch dev git checkout dev
-
使用
git branch
查看当前所有的分支。 -
使用
git add
和git commit
将修改提交到dev分支。 -
将dev分支合并到master分支。
git checkout master
git merge dev
git branch -d dev
总结一下:
- 查看分支:
git branch
- 创建分支:
git branch <name>
- 切换分支:
git checkout <name>
- 创建+切换分支:
git checkout -b <name>
- 合并某分支到当前分支:
git merge <name>
- 删除分支:
git branch -d <name>
2) 解决冲突
这种情况下,是无法合并合并的,存在冲突。
-
使用git diff查看分支冲突的详情。
-
只能是手动修改冲突再合入。
-
使用git log --graph查看分支合并日志。
chuqq@chuqq-hp:~/xxx/git/test$ git log --graph --pretty=oneline * 2d5aa7919ff4baf7875e2967c8e6878f9c17b199 (HEAD -> master) 修改冲突 | | * f29e1b82d41bf8433b7daaa8ce998d9b5a740aff (test) test branch add line * | bb29bec3f082fe57a0f380f44094d47673e8386c master branck add line |/ * 5a79619f8a5489dbea6e0d4ca91194dea90e0558 test add other branch * 21b433229c04ed5264ebba8968527fd3546d685d readme.txt 行首大写 * f401109770227fe6dd231369afda5cb017912ba4 add test readme.txt
3) bug分支
存在场景:正在dev分支做一个大需求,接到一个紧急任务修复代号为101的bug修复任务。
git status
: 查看当前dev的状态,因为尚未验证,不能合入主干。git stash
: 进行代码暂存。git checkout master
: 切到主干版本。git checkout -b bug101
: 创建101新分支修复bug。git add readme.txt
git commit =m "fix 101 bug"
- 修复验证完成
git checkout master
git merge bug101
: 将bug101分支合入mastergit checkout dev
git stash list
git stash pop
: 恢复dev现场,进行继续开发。