###1,建立与合并分支git
1,原理:每次提交,git把版本串成一条时间线这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来讲不是指向提交,而是指向master,master才是指向提交的,因此,HEAD指向的就是当前分支。github
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能肯定当前分支,以及当前分支的提交点:shell
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也愈来愈长:数据库
当咱们建立新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:vim
你看,Git建立一个分支很快,由于除了增长一个dev指针,改改HEAD的指向,工做区的文件都没有任何变化!安全
不过,从如今开始,对工做区的修改和提交就是针对dev分支了,好比新提交一次后,dev指针往前移动一步,而master指针不变:app
假如咱们在dev上的工做完成了,就能够把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:编辑器
因此Git合并分支也很快!就改改指针,工做区内容也不变!fetch
合并完分支后,甚至能够删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,咱们就剩下了一条master分支:ui
2,实战:
首先,咱们建立dev分支,而后切换到dev分支:
$ git checkout -b dev Switched to a new branch 'dev'
git checkout命令加上-b参数表示建立并切换,至关于如下两条命令:
$ git branch dev $ git checkout dev Switched to branch 'dev'
而后,用git branch命令查看当前分支:
$ git branch * dev master
git branch命令会列出全部分支,当前分支前面会标一个*号。
而后,咱们就能够在dev分支上正常提交,好比对readme.txt作个修改,加上一行:
Creating a new branch is quick.
而后提交:
$ git add readme.txt $ git commit -m "branch test" [dev fec145a] branch test 1 file changed, 1 insertion(+)
如今,dev分支的工做完成,咱们就能够切换回master分支:
$ git checkout master Switched to branch 'master'
切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!由于那个提交是在dev分支上,而master分支此刻的提交点并无变:
如今,咱们把dev分支的工做成果合并到master分支上:
$ git merge dev Updating d17efd8..fec145a Fast-forward readme.txt | 1 + 1 file changed, 1 insertion(+)
git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就能够看到,和dev分支的最新提交是彻底同样的。
注意到上面的Fast-forward信息,Git告诉咱们,此次合并是“快进模式”,也就是直接把master指向dev的当前提交,因此合并速度很是快。
固然,也不是每次合并都能Fast-forward,咱们后面会讲其余方式的合并。
合并完成后,就能够放心地删除dev分支了:
$ git branch -d dev Deleted branch dev (was fec145a).
删除后,查看branch,就只剩下master分支了:
$ git branch * master
由于建立、合并和删除分支很是快,因此Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工做效果是同样的,但过程更安全。
###2,解决冲突
人生不如意之事十之八九,合并分支每每也不是一路顺风的。
准备新的feature1分支,继续咱们的新分支开发:
$ git checkout -b feature1 Switched to a new branch 'feature1'
修改readme.txt最后一行,改成:
Creating a new branch is quick AND simple.
在feature1分支上提交:
$ git add readme.txt $ git commit -m "AND simple" [feature1 75a857c] AND simple 1 file changed, 1 insertion(+), 1 deletion(-)
切换到master分支:
$ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 1 commit.
Git还会自动提示咱们当前master分支比远程的master分支要超前1个提交。
在master分支上把readme.txt文件的最后一行改成:
Creating a new branch is quick & simple. 提交:
$ git add readme.txt $ git commit -m "& simple" [master 400b400] & simple 1 file changed, 1 insertion(+), 1 deletion(-)
如今,master分支和feature1分支各自都分别有新的提交,变成了这样:
这种状况下,Git没法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突,咱们试试看:
$ git merge feature1 Auto-merging readme.txt CONFLICT (content): Merge conflict in readme.txt Automatic merge failed; fix conflicts and then commit the result.
果真冲突了!Git告诉咱们,readme.txt文件存在冲突,必须手动解决冲突后再提交。git status也能够告诉咱们冲突的文件:
$ git status # On branch master # Your branch is ahead of 'origin/master' by 2 commits. # # Unmerged paths: # (use "git add/rm <file>..." as appropriate to mark resolution) # # both modified: readme.txt # no changes added to commit (use "git add" and/or "git commit -a")
咱们能够直接查看readme.txt的内容:
Git is a distributed version control system. Git is free software distributed under the GPL. Git has a mutable index called stage. Git tracks changes of files. <<<<<<< HEAD Creating a new branch is quick & simple. ======= Creating a new branch is quick AND simple. >>>>>>> feature1 Git用<<<<<<<,=======,>>>>>>>标记出不一样分支的内容,咱们修改以下后保存: Creating a new branch is quick and simple.
再提交:
$ git add readme.txt $ git commit -m "conflict fixed" [master 59bc1cb] conflict fixed
如今,master分支和feature1分支变成了下图所示:
用带参数的git log也能够看到分支的合并状况:
$ git log --graph --pretty=oneline --abbrev-commit * 59bc1cb conflict fixed |\ | * 75a857c AND simple * | 400b400 & simple |/ * fec145a branch test ...
最后,删除feature1分支:
$ git branch -d feature1 Deleted branch feature1 (was 75a857c).
工做完成。
###多人协做
当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,而且,远程仓库的默认名称是origin。
要查看远程库的信息,用git remote:
$ git remote origin
或者,用git remote -v显示更详细的信息:
$ git remote -v origin git@github.com:michaelliao/learngit.git (fetch) origin git@github.com:michaelliao/learngit.git (push)
上面显示了能够抓取和推送的origin的地址。若是没有推送权限,就看不到push的地址。
###3,推送分支
推送分支,就是把该分支上的全部本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:
$ git push origin master
若是要推送其余分支,好比dev,就改为:
$ git push origin dev
可是,并非必定要把本地分支往远程推送,那么,哪些分支须要推送,哪些不须要呢?
master分支是主分支,所以要时刻与远程同步;
dev分支是开发分支,团队全部成员都须要在上面工做,因此也须要与远程同步;
bug分支只用于在本地修复bug,就不必推到远程了,除非老板要看看你每周到底修复了几个bug;
feature分支是否推到远程,取决于你是否和你的小伙伴合做在上面开发。
总之,就是在Git中,分支彻底能够在本地本身藏着玩,是否推送,视你的心情而定!
###4,忽略特殊文件
有些时候,你必须把某些文件放到Git工做目录中,但又不能提交它们,好比保存了数据库密码的配置文件啦,等等,每次git status都会显示Untracked files ...,有强迫症的童鞋内心确定不爽。
好在Git考虑到了你们的感觉,这个问题解决起来也很简单,在Git工做区的根目录下建立一个特殊的.gitignore文件,而后把要忽略的文件名填进去,Git就会自动忽略这些文件。
不须要从头写.gitignore文件,GitHub已经为咱们准备了各类配置文件,只须要组合一下就可使用了。全部配置文件能够直接在线浏览:https://github.com/github/gitignore
忽略文件的原则是:
忽略操做系统自动生成的文件,好比缩略图等; 忽略编译生成的中间文件、可执行文件等,也就是若是一个文件是经过另外一个文件自动生成的,那自动生成的文件就不必放进版本库,好比Java编译产生的.class文件; 忽略你本身的带有敏感信息的配置文件,好比存放口令的配置文件。 举个例子:
假设你在Windows下进行Python开发,Windows会自动在有图片的目录下生成隐藏的缩略图文件,若是有自定义目录,目录下就会有Desktop.ini文件,所以你须要忽略Windows自动生成的垃圾文件:
# Windows: Thumbs.db ehthumbs.db Desktop.ini
而后,继续忽略Python编译产生的.pyc、.pyo、dist等文件或目录:
# Python: *.py[cod] *.so *.egg *.egg-info dist build
加上你本身定义的文件,最终获得一个完整的.gitignore文件,内容以下:
# Windows: Thumbs.db ehthumbs.db Desktop.ini # Python: *.py[cod] *.so *.egg *.egg-info dist build # My configurations: db.ini deploy_key_rsa
最后一步就是把.gitignore也提交到Git,就完成了!固然检验.gitignore的标准是git status命令是否是说working directory clean。
使用Windows的童鞋注意了,若是你在资源管理器里新建一个.gitignore文件,它会很是弱智地提示你必须输入文件名,可是在文本编辑器里“保存”或者“另存为”就能够把文件保存为.gitignore了。
有些时候,你想添加一个文件到Git,但发现添加不了,缘由是这个文件被.gitignore忽略了:
$ git add App.class The following paths are ignored by one of your .gitignore files: App.class Use -f if you really want to add them.
若是你确实想添加该文件,能够用-f强制添加到Git:
$ git add -f App.class
或者你发现,多是.gitignore写得有问题,须要找出来到底哪一个规则写错了,能够用git check-ignore命令检查:
$ git check-ignore -v App.class .gitignore:3:*.class App.class
Git会告诉咱们,.gitignore的第3行规则忽略了该文件,因而咱们就能够知道应该修订哪一个规则。
小结
忽略某些文件时,须要编写.gitignore;
.gitignore文件自己要放到版本库里,而且能够对.gitignore作版本管理!
###5,vim简单操做
####正常模式 正常模式通常用于浏览文件,也包括一些复制、粘贴、删除等操做。这时击键时, 通常的键/键组合会被当成功能键,而不会键入对应的字符。
在这个模式下,咱们可能经过键盘在文本中跳来跳去,跳动的范围从小到大是字符、 单词、行、句子、段落和屏幕。
启动vim后默认位于正常模式。不论位于什么模式,按下<Esc>键(有时须要按两下) 都会进入正常模式。
####插入模式 在正常模式中按下i, I, a, A等键(后面系列文章会详细介绍),会进入插入模式。 如今只用记住按i键会进行插入模式。插入模式中,击键时会写入相应的字符。
命令模式 在正常模式中,按下:(冒号)键,会进入命令模式。在命令模式中能够执行 一些输入并执行一些vim或插件提供的指令,就像在shell里同样。这些指令包括 设置环境、文件操做、调用某个功能等等。
可视模式 在正常模式按下v, V, <Ctrl>+v,能够进入可视模式。可视模式中的 操做有点像拿鼠标进行操做,选择文本的时候有一种鼠标选择的即视感,有时候 会很方便。
####命令模式下的简单命令
:w 将编辑的内容写入原始文件,用来保存编辑的中间结果 :wq 将编辑的内容写入原始文件并退出编辑程序(至关于 ZZ 命令) :w file 将编辑的内容写入 file 文件,保持原有文件的内容不变 :a,bw file 将第 a 行至第 b 行的内容写入 file 文件 :r file 读取 file 文件的内容,插入当前光标所在行的后面 :e file 编辑新文件 file 代替原有内容 :f file 将当前文件重命名为 file :f 打印当前文件名称和状态,如文件的行数、光标所在的行号等
###6,一个小问题:Git warning:LF will be replaced by CRLF in readme.txt的缘由与解决方案
首先问题出在不一样操做系统所使用的换行符是不同的,下面罗列一下三大主流操做系统的换行符:
Uinx/Linux采用换行符LF表示下一行(LF:LineFeed,中文意思是换行);
Dos和Windows采用回车+换行CRLF表示下一行 (CRLF:CarriageReturn LineFeed,中文意思是回车换行);
Mac OS采用回车CR表示下一行(CR:CarriageReturn,中文意思是回车)。
在Git中,能够经过如下命令来显示当前你的Git中采起哪一种对待换行符的方式
$ git config core.autocrlf
此命令会有三个输出,“true”,“false”或者“input”
为true时,Git会将你add的全部文件视为文本问价你,将结尾的CRLF转换为LF,而checkout时会再将文件的LF格式转为CRLF格式。
为false时,line endings不作任何改变,文本文件保持其原来的样子。
为input时,add时Git会把CRLF转换为LF,而check时仍旧为LF,因此Windows操做系统不建议设置此值。
解决办法: 将core.autocrlf设为false便可解决这个问题
$ git config --global core.autocrlf false