Git分支管理

分支管理

    • 创建分⽀
      • git branch
    • 切换分⽀
      • git checkout
    • 合并分⽀
      • git merge
    • 删除分⽀
      • git branch -d
    • 合并冲突
    • 合并模式
    • 分⽀策略
    • bug分⽀
      • git stash
      • git stash list
      • git stash pop
      • git stash apply 、git stash drop
    • 强制删除临时分⽀
      • git branch -D

创建分⽀

git branch

Git⽀持我们查看或创建其他分⽀,在这⾥我们来创建第⼀个⾃⼰的分⽀dev ,对应的命令为:

#查看当前本地所有分⽀
[root@VM-16-15-centos gitcode]# git branch
* master
#新建分⽀dev
[root@VM-16-15-centos gitcode]# git branch dev
[root@VM-16-15-centos gitcode]# git branch
  dev
* master

当我们创建新的分⽀后,Git新建了⼀个指针叫dev, *表⽰当前 HEAD 指向的分⽀是 master 分
⽀。另外,可以通过⽬录结构发现新的 dev 分⽀。

[root@VM-16-15-centos ~]# ls .git/refs/heads
dev  master

切换分⽀

git checkout

那如何切换到dev分⽀下进⾏开发呢?使⽤ git checkout 命令即可完成切换,⽰例如下:

[root@VM-16-15-centos ~]# git checkout dev
Switched to branch 'dev'
[root@VM-16-15-centos ~]# git branch
* dev
  master
[root@VM-16-15-centos ~]# cat .git/HEAD
ref: refs/heads/dev
[root@VM-16-15-centos ~]# 

我们发现HEAD已经指向了dev,就表⽰我们已经成功的切换到了dev上!

接下来,在 dev 分⽀下修改ReadMe⽂件,新增⼀⾏内容,并进⾏⼀次提交操作:

[root@VM-16-15-centos gitcode]# vim readme 
[root@VM-16-15-centos gitcode]# cat readme 
hello world
alter readme 1

alter readme version1
alter readme version2
alter readme version3

write test for new branch

[root@VM-16-15-centos gitcode]# git add .
[root@VM-16-15-centos gitcode]# git commit -m "new branch"
[dev 58b2bfc] new branch
 1 file changed, 2 insertions(+)

现在,dev分⽀的⼯作完成,我们就可以切换回master分⽀,切换回master分⽀后,发现ReadMe⽂件中新增的内容不⻅了。

因为我们是在dev分⽀上提交的,⽽master分⽀此刻的提交点并没有变,此时的状态如图如下所⽰

Git分支管理_第1张图片

当切换到master分⽀之时,HEAD就指向了master,当然看不到提交了!

合并分⽀

git merge

为了在master主分⽀上能看到新的提交,就需要将 dev 分⽀合并到 master 分⽀,⽰例如下

git checkout master # 切换到 master 上进⾏合并

git merge dev # 合并 dev 分⽀

git merge 命令⽤于合并指定分⽀到当前分⽀。合并后,master就能看到dev分⽀提交的内容了。此时的状态如图如下所⽰:

Git分支管理_第2张图片

删除分⽀

git branch -d

合并完成后,dev分⽀对于我们来说就没⽤了,那么dev分⽀就可以被删除掉,注意如果当前正处于该分⽀下,就不能删除当前分⽀,如:

[root@VM-16-15-centos ~]# git checkout dev
Switched to branch 'dev'
[root@VM-16-15-centos ~]# git branch 
* dev
  master
[root@VM-16-15-centos ~]# git branch -d dev
error: Cannot delete the branch 'dev' which you are currently on.

⽽可以在其他分⽀下删除当前分⽀,如:

[root@VM-16-15-centos ~]# git checkout master
Switched to branch 'master'
[root@VM-16-15-centos ~]# git branch -d dev
Deleted branch dev (was 36d40bc).
[root@VM-16-15-centos ~]# git branch 
* master

此时的状态如图如下所⽰:
Git分支管理_第3张图片

因为创建、合并和删除分⽀⾮常快,所以Git⿎励你使⽤分⽀完成某个任务,合并后再删掉分⽀,这和直接在master分⽀上⼯作效果是⼀样的,但过程更安全。

合并冲突

可是,在实际分⽀合并的时候,并不是想合并就能合并成功的,有时候可能会遇到代码冲突的问题。为了演⽰这问题,创建⼀个新的分⽀ dev1 ,并切换⾄⽬标分⽀,我们可以使⽤ git checkout -b dev1 ⼀步完成创建并切换的动作,⽰例如下:

[root@VM-16-15-centos ~]# git checkout -b dev1
Switched to a new branch 'dev1'
[root@VM-16-15-centos ~]# git branch
* dev1
  master

在 dev1 分⽀下修改 ReadMe ⽂件,并进⾏⼀次提交。

[root@VM-16-15-centos ~]#cat readme
hello bit
hello git
hello world
hello version1
hello version2
hello version3
write bbb for new branch # 将 aaa 该为 bbb
[root@VM-16-15-centos ~]# git add .
[root@VM-16-15-centos ~]# git commit -m"modify ReadMe"

然后切换⾄ master 分⽀,此时在master分⽀上,我们对ReadMe⽂件再进⾏⼀次修改,并进⾏提交。

[root@VM-16-15-centos ~]# git checkout master
Switched to branch 'master'
[root@VM-16-15-centos ~]#cat readme
hello bit
hello git
hello world
hello version1
hello version2
hello version3
write ccc for new branch 
[root@VM-16-15-centos ~]# git add .
[root@VM-16-15-centos ~]# git commit -m"modify ReadMe"

现在, master 分⽀和 dev1 分⽀各⾃都分别有新的提交(master是bbb,dev1是ccc),变成了这样:

Git分支管理_第4张图片
这种情况下,Git只能试图把各⾃的修改合并起来,但这种合并就可能会有冲突(master是bbb,dev1是ccc)

此时我们必须要⼿动调整冲突代码,使其原本冲突的地方代码一致,并需要再次提交修正后的结果!!(再次提交很重要,切勿忘记)

到这⾥冲突就解决完成,此时的状态变成了:

Git分支管理_第5张图片

最后,不要忘记dev1分⽀使⽤完毕后就可以删除了。

合并模式

通常合并分⽀时,如果可能,Git会采⽤ Fast forward 模式。
Git分支管理_第6张图片
我们看到,合并时采用的就是 Fast forward 模式。

在这种 Fast forward 模式下,删除分⽀后,查看分⽀历史时,会丢掉分⽀信息,看不出来最新提交的到底是merge进来的还是正常提交的

但在合并冲突部分,我们也看到通过解决冲突问题,会再进⾏⼀次新的提交,得到的最终状态为:
Git分支管理_第7张图片
那么这就不是 Fast forward 模式了,他会保留分支历史信息,这样的好处是,从分⽀历史上就可以看出分⽀信息。例如我们现在已经删除了在合并冲突部分创建的 dev分⽀,但依旧能看到master其实是由其他分⽀合并得到。

Git⽀持我们强制禁⽤ Fast forward 模式,那么就会在merge时⽣成⼀个新的 commit ,这样,从分⽀历史上就可以看出分⽀信息。


下⾯我们实战⼀下 --no-ff ⽅式的 git merge :

  • ⾸先,创建新的分⽀ dev2 ,并切换⾄新的分⽀;
  • 修改 ReadMe ⽂件,并提交⼀个新的 commit;
  • 切回 master 分⽀,开始合并;

Git分支管理_第8张图片

请注意 --no-ff 参数,表⽰禁⽤ Fast forward 模式。禁⽤ Fast forward 模式后合并会创建⼀个新的 commit ,所以加上 -m 参数,把描述写进去。

合并后,查看分⽀历史:

Git分支管理_第9张图片

从图上我们可以看出来此时的master其实是由其他分⽀(dev2)合并得到的。

所以在合并分⽀时,加上 --no-ff 参数就可以⽤普通模式合并,能看出来曾
经做过合并,⽽ fast forward 合并就看不出来曾经做过合并。


分⽀策略

Git分支管理_第10张图片

在实际开发中,我们应该按照⼏个基本原则进⾏分⽀管理:

⾸先,master分⽀应该是⾮常稳定的,也就是仅⽤来发布新版本,平时不能在上⾯⼲活(线上环境是用户能看到的,如果你线上环境出现bug或不稳定情况是会直接你公司营收效益的);

那在哪⼲活呢?⼲活都在dev分⽀上,也就是说,dev分⽀是不稳定的,到某个时候,⽐如1.0版本发布时,再把dev分⽀合并到master上,在master分⽀发布1.0版本;

你和你的⼩伙伴们每个⼈都在dev分⽀上⼲活,每个⼈都有⾃⼰的分⽀,时不时地往dev分⽀上合并就可以了。

所以,团队合作的分⽀看起来就像这样:
Git分支管理_第11张图片

bug分⽀

假如我们现在正在 dev2分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有bug,需要解决。

Git分支管理_第12张图片

在Git中,每个bug都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀删除。

可现在 dev2 的代码在⼯作区中开发了⼀半,还⽆法提交,怎么办?

例如:
Git分支管理_第13张图片

解释:
我们在dev2分支进行开发,此时假设master出现了bug,那么我们就需要先创建新分支用来解决master的bug,然后继续回到dev2进行开发,直到开发完成将dev2合并到master。

但是我们在mastr上创建新分支用于解决bug之前,会看到开发到一半的dev2分支的内容已经在master的工作区可以看到了,很显然,这是我们不想看到的。

git stash

Git提供了 git stash 命令,可以将当前的⼯作区信息进⾏储藏,被储藏的内容可以在将来某个时间恢复出来。

我们进入dev2分支,将其工作区内容进行保存。

在这里插入图片描述

那这些内容储藏到哪里了呢?

我们通过tree .git查看一下:

Git分支管理_第14张图片

我们看到此时这里有一个stash文件,这里面就是保存的dev2分支的内容。


注意点: git stash 命令只会将目前已经追踪管理到master的分支的内容进行储藏,也就是说,你如果当前分支只是在工作区进行了新建,没有 add 、commit ,那么你的内容是不能被储藏的。


接着,假设我们在新建分支fix_bug上进行了修复bug,然后重新add,commit。

# 切回master
git checkout master
# 新建并切换到 fix_bug 分⽀
git checkout -b fix_bug
# 修复bug
# 重新add,commit
 git add ReadMe # 重新add,commit
 git commit -m"fix bug"

修复完成后,切换到 master 分⽀,并完成合并,最后删除 fix_bug 分⽀:

git checkout master
git merge --no-ff -m"merge fix_bug branch" fix_bug
git branch -d fix_bug

⾄此,bug的修复⼯作已经做完了,我们还要继续回到 dev2 分⽀进⾏开发。切换回 dev2 分⽀:

hyb@139-159-150-152:~/gitcode$ git checkout dev2
Switched to branch 'dev2'
hyb@139-159-150-152:~/gitcode$ git status
On branch dev2
nothing to commit, working tree clean

git stash list

我们发现⼯作区是⼲净的,刚才的⼯作现场存到哪去了?⽤ git stash list 命令看看:

hyb@139-159-150-152:~/gitcode$ git stash list
stash@{0}: WIP on dev2: 41b082f modify ReadMe

⼯作现场还在,Git把stash内容存在某个地⽅了,但是需要恢复⼀下,如何恢复现场呢?

git stash pop

我们可以使⽤ git stash pop 命令,恢复的同时会把stash也删了,⽰例如下:

hyb@139-159-150-152:~/gitcode$ git stash pop
On branch dev2
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: ReadMe
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (4f873250b3503687b5efd26196776aee7e3724c2)

再次查看的时候,我们已经发现已经没有现场可以恢复了:

hyb@139-159-150-152:~/gitcode$ git stash list
hyb@139-159-150-152:~/gitcode$

git stash apply 、git stash drop

另外,恢复现场也可以采⽤ git stash apply 恢复,但是恢复后,stash内容并不删除,你需要⽤ git stash drop 来删除;

你可以多次stash,恢复的时候,先⽤ git stash list 查看,然后恢复指定的stash,⽤命令git stash apply stash@{0}


恢复完代码之后我们便可以继续完成开发,开发完成后便可以进⾏提交。

需要注意一点,恢复完dev2分支的内容后,我们会发现修复bug的内容,并没有在 dev2 上显⽰。此时的状态图为:

Git分支管理_第15张图片

Master 分⽀⽬前最新的提交,是要领先于新建 dev2 时基于的 master 分⽀的提交的,所以我们在 dev2 中当然看不⻅修复bug的相关代码。

我们的最终⽬的是要让 master 合并 dev2 分⽀的,那么正常情况下我们切回 master 分⽀直接合并即可,状态如下图。
Git分支管理_第16张图片

但这样其实是有⼀定⻛险的。

是因为在合并分⽀时可能会有冲突,⽽代码冲突需要我们⼿动解决(在 master 上解决)。我们⽆法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单,有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到 master 上。

解决这个问题的⼀个好的建议就是:最好在⾃⼰的分⽀dev上先合并下master ,再让 master 去合并dev ,这样做的⽬的是有冲突可以在本地分⽀解决并进⾏测试,⽽不影响 master 。

状态演示:

Git分支管理_第17张图片
Git分支管理_第18张图片


强制删除临时分⽀

软件开发中,总有⽆穷⽆尽的新的功能要不断添加进来。
添加⼀个新功能时,你肯定不希望因为⼀些实验性质的代码,把主分⽀搞乱了,所以,每添加⼀个新功能,最好新建⼀个分⽀,我们可以将其称之为 feature 分⽀,在上⾯开发,完成后,合并,最后,删除该 feature 分⽀。

可是,如果我们今天正在某个 feature 分⽀上开发了⼀半(该分支有提交未进行合并),被产品经理突然叫停,说是要停⽌新功能的开发。虽然⽩⼲了,但是这个 feature 分⽀还是必须就地销毁,留着⽆⽤了。这时使⽤传统的 git branch -d 命令删除分⽀的⽅法是不⾏的。需要用到 git branch -D 命令。

git branch -D

  • git branch -d :删除一个名字为branchName的分支。如果该分支有提交未进行合并,则会删除失败。
  • git branch -D :强制删除一个名字为branchName 的分支。如果该分支有提交未进行合并,也会删除成功。

the end!

你可能感兴趣的:(Git,git)