当我们进行程序开发的过程中,有时会产生一个新的想法,然后就想马上试验,那我们怎么办? 如果我们继续在现有的基础上进行开发,但最后想法不成功,我们还要进行版本回退?如果我们的新想法,需要很长时间才能实现呢?我们其它的功能还要不要进行开发?最后就是如果有bug,我们修复bug,这有时也需要较长时间,我们还是在现有基础进行开发,如果修改不成功或引入的新的bug 怎么样? 这时就要引入分支的概念,当我们进行新功能开发或者修复bug的时候,在新的分支上进行开发, 它不会影响现有的代码。
分支,可以按照现实中的分支进行理解,树木在成长的过程中,它先生长树干,等到树干长到一定的高度,它就会进行分支。还有一个例子,就是道路。当我们驾车在道路上行驶的时候,你会发现,时不时的会有一条支路从道路上分出来。对于我们的程序开发说,前期的开发就相当于形成树木的主干或道路的主路,这通常是master分支,因为git在初始化仓库的时候,会默认生成一个master 分支。到了后期的开发,我们也要像树木一样进行分支。分支开发还是有好处的,就像树木一样,只要某个分支有问题,我们可以直接把它砍掉,不影响主干,但如果主干有问题,那树木可能就真挂了。程序也是一样,当我们分支开发出问题时,直接把这个分支删除就可以了,但如果我们一直在主干上开发时,主干有问题,我们整个项目就完了。
说了这么多分支,我们怎么才能在分支上进行开发呢?因为程序可不像树木一样会自动长出分支,那就 先用git branch 分支名 命令来创建分支,git branch new_feature,就创建了新的分支new_feature. 我们可以使用 git branch 命令来查看git 仓库中所有分支。
你会注意到有两个分支,master和new_feature 分支,并且master 分支前面有一个*号,*表示我们当前处于哪一个分支上,* 在master 前面就表示,我们当前在master 分支上。怎样才能切换到新的分支上进行开发呢? git checkout 分支名,就可以进行切换。git checkout new_feature, 就切换到了new_feature 分支上。这时再调用git branch 可以发现 * 在new_feature 上表明切换成功了,这时,命令行后面也换成了new_feature, 它也表明我们在new_feature 上。
通常来说,我们创建了分支,就会立即使用,能不能把创建分支和切换分支开支变成一步操作。可以,git checkout -b new_feature. 创建并切换到new_feature 分支。
现在我们就可以在new_feature 分支上进行开发了,创建分支,就是相当于把代码拷贝了一份到分支上,各分支之间的代码相互独立,互不影响。我们在master分支上开发时创建了new_feature 分支,所以它就相当于把master分支上(创建new_feature 分*一刹那的)内容完全拷贝了new_feature 分支上,这时,我们就拥有了一个和master 分支一模一样的私人分支,可以放心进行开发。增加一个新utils.js 文件,
里面放一个sum 求和函数,
const add = (a, b) => a + b;
然后git add 和 git commit提交到仓库
这时我们再切换到master 分支(git checkout master),你会发现在工作区uitils.js 文件不见了, 因为master 分支下没有这个文件,这也表示这两个分支是相互独立。整个git 仓库的状态,如下所示
现在我们在master 分支上main.js 写一个减法函数。
const subtract = (a, b) => a - b;
然后git add 和 git commit 到仓库, 整个仓库的状态如下:
这时我们打印一下提交记录,可以发现,它只有一个master 分支上的提交,其它分支上的提交并没有,这时可以使用下列命令显示仓库中的所有分支。
git log --graph --decorate --pretty=oneline --all --abbrev-commit
可以看到显示分支了。但这条命令有点长,要不要使用图形界面查看一下,gitk 就可以了,但还是只看到了master 分支的内容。 找到view 菜单,选择new view
然后弹出一个提示框,选择 all(Local) branches
点击弹窗底部的Apply 或按F5,就可以看到分支了,且更为直观。
现在我们再来看一下,使用分支来修改bug. 修改bug 和新增功能有一点不同,因为bug是在以前的代码中引进的,我们要找到出现bug的文件,然后在此基础上进行修改,就是在此基础上创建分支。假设在修改index.html文件的时候引入bug,如文字写错了,就要以此创建分支。git branch 在分支名后面 可以接受一个commit id参数,就是以commit id 这次提交为基础作为提交,commit id 就是引起包含引起bug的文件的那次提交。 我们用git log --oneline 找到修改index.html 提交的commit id, 如下图,在我这里是a69243e
git branch fix_bug001 a69243e, 就创建了以a69243e为基础的分支fix_bug001 ,然后就是git checkout fix_bug001 切换分支。这次不这么做了,因为我们可以使用快捷方式,git checkout -b 创建的同时切换分支。git checkout -b fix_bug001 a69243e
现在 git branch 看一下状态
有三个分支,我们在fix_bug001上, 同时工作区了发生了变化,只有index.html了,修改bug, 我们这里只是演示,所以就随便改动了一个,
现在再切换到master 分支,
原来是我们修改index.html之后并没有保存,然后就切换分支了。如果进行切换,我们所有的修改就会失效,所以git 要求我们进行提交修改。但是有时我们修改代码时,没有修改完整就切换分支了,还不想提交代码,这时可以用git stash 暂时保存一下。
这时,你再切换到其它分支,就没有问题了。
在master 分支,开发完成后,我们要回到fix_bug001 分支再次开发,这时需要把暂存的文件取出来。用git stash pop
在分支上新功能开发完了,或bug 修复成功了,我们就要把它合并到master 分支上,好对外进行发布, 这就要用到git merge 命令,我们想要把其它分支合并到哪个分支,就要先切换到哪个分支,比如我们要把其它分支合并到master 分支,那就要切换到master 分支,使它成为当前分支 , git checkout master, 然后git merge 其它 要合并的分支名,如git merge new_feature, 这时就把new_feature 合并到了master 分支。不过在合并之前,我们最好先看一下两个分支的不同,还是使用git diff 命令,不过,参数有不同 git diff master...new_feature, 要合并的到分支, 加上三个点,再到被合并的分支。这里要注意顺序, 要合并到的分支永远在前面
可以看new_feature分支utils.js 多了一行代码,如果只是看看两个分支哪个文件发生变化,可以再加上修饰符 --name-status
utils.js 文件发生了变化,并且前面一个A, 表示新增的意思 add 。这时候,我们的都知道了改变了什么,也能预估到合并到将会发生什么。调用git merge new_feature 进行分支合并。这时会弹出一个vim 界面,输入提交信息,它有一个默认信息,merge branch new_feature, 你可以输入修改,
输入 信息后,按esc 键退出输入状态,然后再输入:wq 退出。退出后,git 自动做了一次提交。但有时候合并没有这么顺利,会发生冲突。因为 我们在这个分支开发,然后提交,其它人也会在分支上进行开发,然后提交,如果两个人同时修改了同一个文件的同一个地方,那就会有冲突。现在我们在master分支上修改index.html文件,在index.html 中增加一个div,内容为 main 分支修改
然后再git add 和git commit 提交到master 分支。 执行 git merge bug_fix001, 可以发现有冲突了。
在index.html 中起了冲突,因为我们在两个分支上修改了同一件文件index.html, 并且是同一个地方,都是index.html的第11 行,所以就起冲突了。git 没有办法合并,我们要手动解决冲突。打开index.html 页面,可以看到如下代码
git 把有冲突的地方给我们标注好出来了,以====== 为分隔线,上面的部分就是master 分支上的内容, 因为>>>>>> HEAD, HEAD 就是指向的当前分支,下面的部分就是把bug_fix001的分支,因为>>>>>> bug_fix001. 我们要想保留哪一部分,就把另一部分删掉,从而解决冲突。想一想,还是保留bug_fix001的内容,那就把多余的内容删除
然后保存文件,再 git add 和 git commit 提交代码。
可以看到代码合并了提交了。
把分支合并到master, 我们的分支实际上就没有什么作用了,可以把它删除掉了。这时 git branch 一下
仍然有三个分支,这时可以把bug_fix001 和 new_feature 分支删除掉了。 使用命令git branch -d 分支名
git branch -d bug_fix001 把bug_fix001 分支删掉了。删除分支要注意,不能在当前分支上删除当前分支,要在其它分支上删除某个分支, 我们不能在new_feature 上删除new_feature 分支
可以看到报错了, 不能删除分支。还有就是,如果我们创建了分支,而又没有使用和合并,而想删除,那就要把 小d 换成 大D, 强制删除。 git branch -D new_feature