理解分支
分⽀就是科幻电影里面的平行宇宙,当你正在电脑前努力学习C++的时候,另⼀个你正在另⼀个平行宇宙里努力学习JAVA。如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并 了,结果,你既学会了C++也学会了JAVA。
在版本回退里,每次提交,Git都把它们串成⼀条时间线,这条时间线就可以理解为是⼀个分⽀。截止到目前,只有⼀条时间线,在Git里面,这个分支叫主分支,即master分支。
再来理解⼀下HEAD,HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
同样的,我们可以创建出分支,最后合并分支到主分支上。
创建分支
HEAD可以执行其它分支,不一定是只指向master分支,而被HEAD指向的分支便是当前的工作分支。当前的HEAD指向的是master分支。
使用**git branch [name]**来创建分支。
使用git branch查看到当前的分支。
创建处理的分支,是站在当前最新的提交记录上的,因此,新建出来的分支,与master分支的最新提交记录的一模一样的。
可以使用cat .git/refs/heads/master查看
创建好新分支后,想要在新分支上工作,则将HEAD指向该新分支。
切换分支
使用git checkout dev 进行切换分支。注意与撤销修改命令git checkout -- file区别开
此时,对工作区中的文件进行修改,使用这个分支!
接着,为了验证,切换回master分支,来看看,这个修改记录存在不:
此时,master和dev两个分支的提交记录已经不一样了:
此时的状态是这样的:
当切换到master分支之时,HEAD就指向了master,当然看不到提交了。
创建分支有两种方式:
除了上面介绍的:①git branch dev。②git checkout dev。通过两步来创建并切换分支。还有一步到位,创建并切换的:git checkout -b dev
合并分支
为了在master上也能看到最新记录,就就需要将dev分支合并到master分支上。
git merge 命令用于合并指定分支到当前分支。合并后,master就能看到dev分支提交的内容
了。此时的状态如图如下所示:
合并的步骤是:
①切换到需要合并的分支上,也就是master分支。
②使用git merge dev。将dev分支合并到master分支上。
Fast-forward代表"快进模式",也就是直接把master指向dev的当前提交 ,所以合并速度非常快。
当然,也不是每次合并都能Fast-forward 。
此时可以看到,合并了:
接着,查看master提交记录,发现,它更新了,变成了dev的提交记录,也就是最新的提交记录了。
删除分支
合并完成后,dev分支对于我们来说就没用了,那么dev分支就可以被删除掉,注意如果当前正处于某分支下,就不能删除当前分支。
使用 **git branch -d [name]**将分支删掉。
合并冲突
出现的问题
当在master分支在对文件内容进行修改的同时,在dev也对文件内容的同一行同一个位置进行修改,两个分支修改的内容均不同。比如文件ReadMe第三行原本的内容是aaa,masert分支将其改成bbb,dev分支将其改成ccc,接着在对master和dev进行合并时,git将保存谁呢?这就是合并冲突问题。
切换到master分支,进行合并:发现合并冲突,提醒需要修改文件内容并重新提交
打开ReadMe文件,发现出现了两个分支的最新提交的内容。
解决合并冲突问题
在合并后,git会在文件上显示两个分支提交的内容,此时我们可以自己手动选择要保留的内容,保存后。重新add和commit便可。
此时的状态是:
此时,master指向的是最新提交,dev指向的是自己的最新的提交。
可以通过git log查看合并情况:
合并模式
在合并分支后,git会采用Fast forward模式,在这个模式下,删除分支后,查看分支历史时,会丢掉分支信息,看不出来最新提交到底是merge进来的还是正常提交的。
而在合并冲突后,发现Fast forward模式不在了,这样的好处是,从分支历史上就可以看出分支信息。例如我们现在已经删除了在合并冲突部分创建的 dev1 分支,但依旧能看到master其实是由其他分支合并得到。
如果想要正常合并也能看到分支信息,可以在合并时,在merge后加上--no-ff ,表示禁止是否fast forward模式;
git merge --no-ff -m "merge with no-ff" dev2
请注意 --no-ff 参数,表示禁用 Fast forward 模式。禁用 Fast forward 模式后合并会创建⼀个新的 commit ,所以加上 -m 参数,把描述写进去。
bug分支
场景:如果在dev2分支的开发的过程中,发现之前提交给master分支的代码出现了bug,需要去解决。但是dev2是作为开发分支的,那么此时需要额外多创建一个临时的分支,专门用于修复bug。
可是,在dev2中正在开发的代码在工作区中,并没有提交,如果此时切换到master分支,创新新的分支去修复bug,那么在dev2工作区的代码也会显示出来。
cpp
[wjmhlh@VM-12-9-centos gitcode]$ git branch
* dev2
master
[wjmhlh@VM-12-9-centos gitcode]$ cat ReadMe
hello bit
hello git
hello world
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d
i am coding ...
[wjmhlh@VM-12-9-centos gitcode]$ git status
On branch dev2
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: ReadMe
no changes added to commit (use "git add" and/or "git commit -a")
此时需要用到git stash命令。
git stash命令可以将可以将当前的⼯作区信息进⾏储藏,被储藏的内容可以在将来某个时间恢复出来。这样,就可以放心地去创建一个临时的分支去修改bug了。
储藏 dev2 工作区之后,由于我们要基于master分支修复bug,所以需要切回 master 分支,再新
建临时分支来修复bug,实例如下:
cpp
[wjmhlh@VM-12-9-centos gitcode]$ git checkout master # 切回master
Switched to branch 'master'
[wjmhlh@VM-12-9-centos gitcode]$ git checkout -b fix_bug # 新建并切换到 fix_bug 分⽀
Switched to a new branch 'fix_bug'
[wjmhlh@VM-12-9-centos gitcode]$ vim ReadMe
[wjmhlh@VM-12-9-centos gitcode]$ cat ReadMe
hello bit
hello git
hello world
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d,e # 修复bug--忘记写e
[wjmhlh@VM-12-9-centos gitcode]$ git add ReadMe # 重新add,commit
[wjmhlh@VM-12-9-centos gitcode]$ git commit -m"fix bug"
[fix_bug 4bbc0c4] fix bug
1 file changed, 1 insertion(+), 1 deletion(-)
修复完成后,切换到 master 分支,并完成合并,最后删除 fix_bug 分支。到此,bug修复完毕,重新回到dev2上进行工作。在工作前,将原本正在开发的代码从存储区中拿回来:
使用 git stash pop 命令,恢复的同时会把stash也删掉。当然,在拿回来前,可以查看存储区有没有可以恢复的内容现场:⽤ git stash list 命令看看。
除此之外:恢复现场也可以采用 git stash apply 恢复,但是恢复后,stash内容并不删除,你需要
用 git stash drop 来删除;你可以多次stash ,恢复的时候,先用 git stash list 查看,然后恢复指定的stash,⽤命令git stash apply stash@{0}
代码开发完成后,可以提交了。但是,必须记得,在上面修复好的bug,并没有在dev2中修复,如果此时直接合并到master中,会导致合并冲突,要在master分支中人工去改,这很可能会导致新bug的出现。
因此,在合并前,最后在dev2分支上,将master合并进来,然后修复bug。修复后,进入master分支,将dev2合并到master上。
总结步骤就是:
①发现之前提交给master的代码出现了bug。
②使用stash,将工作区的代码存储起来。
③进入master分支,创新临时分支去修复bug。
④修复后, 合并到master分支上。
⑤回到dev2分支,将存储起来的代码拿回来,继续开发。
⑥开发完毕,将master合并过来,修复bug。
⑦修复完成,将最终的dev2合并到master中。
强制删除分支
如果在某个分支上进行开发,并且已经提交了一部分的代码了,但是此时由于某些原因,这个分支的代码不要了,需要删除这个分支。在git看来,如果这个分支已经commit提交了代码,说明是有用的,不能随意被删除,也就是不能使用git branch -d [name]删除。此时,可以将d改成D,表示强制删除。