【Git原理与使用】-- 分支管理

news2024/11/15 15:47:57

目录

理解分支

创建分支

查看当前分支

创建本地分支

切换分支

合并分支

删除分支

合并冲突

分支管理策略

分支策略 

bug 分支

不建议的合并方式

建议的合并方式

第一步

第二步

删除临时分支


理解分支

        分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习 C++ 的时候,另⼀个你正在另⼀个平行宇宙里努力学习 JAVA。如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并了,结果:你既学会了 C++ 又学会了 JAVA!

回顾:在讲解工作区、暂存区、版本库的概念的时候有所提到,在版本库中是有一个HEAD指针,其是指向了一个 master 分支。 

[qcr@ecs-205826 project]$ cat .git/HEAD 
ref: refs/heads/master

[qcr@ecs-205826 project]$ cat .git/refs/heads/master 
dccd2a4405215cffcf40a12308449e27b1e58ea0

        master里面存储的就是我们的最新的一次提交,而最新的一次提交对应的就是commit id,对应的就是对象库中的一个对象的索引,我们可以适应 log 命令进行查看。

[qcr@ecs-205826 project]$ git log --pretty=oneline
dccd2a4405215cffcf40a12308449e27b1e58ea0 删除test3
1bba34a04f231d8ad49f3ce5079879144cf6f4db 临时空文件
8f2b55aca176fb578cf39952f776c3da9aa50009 新增一行
e797df72c0669a2b81339ff4854328126d2e6c8e 一行你好,用于学习git
[qcr@ecs-205826 project]$ 
        在版本回退里,每次提交,Git都把它们串成⼀条时间线,这条时间线就可以理解为是一个分⽀。截止到目前,只有⼀条时间线,在Git里,这个分⽀叫主分⽀,即 master 分⽀。 再来理解⼀下HEAD,HEAD 严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD 指向的就是当前分支。

        每次提交,master分支都会向前移动一步,这样随着我们不断提交,master分支的线也越来越长,而HEAD只要⼀直指向master分支即可指向当前分支。

创建分支

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

查看当前分支

        查看当前本地所有分支 branch。

[qcr@ecs-205826 project]$ git branch
* master

        其实在我们创建本地仓库的时候,git会为我们自动创建出来一个master主分支,所以此处只有一个master分支,而前面有一个*号,就是因为master前面存在一个HEAD指针。HEAD是不止可以指向master分支,还可以指向其他的任意分支的,而被HEAD指向的分支其实才是当前的工作分支。所以master前面有一个*号,其实是因为当前我们正在master上工作。

创建本地分支

        创建本地分支 dev。

[qcr@ecs-205826 project]$ git branch dev
[qcr@ecs-205826 project]$ git branch
  dev
* master

        通过*号我们可以知道,HEAD 指针还是指向 master 分支的,可以通过查看验证:

[qcr@ecs-205826 project]$ cat .git/HEAD
ref: refs/heads/master

        这个时候通过 tree 命令查看 .git 可以发现:
 

         以前只有一个 master ,而这一次多了一个 dev ,通过查看 dev 内的内容可以发现:

[qcr@ecs-205826 project]$ cat .git/refs/heads/dev 
dccd2a4405215cffcf40a12308449e27b1e58ea0
[qcr@ecs-205826 project]$ cat .git/refs/heads/master
dccd2a4405215cffcf40a12308449e27b1e58ea0

        其里面也是一个 commit id ,并且其里面放的内容与 master 里面放的内容是一摸一样的,指向的是最新的一次提交。

         原因就是因为:我们创建 dev 分支的时候,是基于最新的一次的提交创建出来的,即我们在git branch dev 的时候是站在当前最新的一个版本上去创建的。

切换分支

        如果想在对应的分支下进行操作,即切换到 dev 分支下进行开发,使用 git checkout 命令即可完成切换。

[qcr@ecs-205826 project]$ git checkout dev
Switched to branch 'dev'
[qcr@ecs-205826 project]$ git branch
* dev
  master

        我们发现 HEAD 已经指向了 dev,就表示我们已经成功的切换到了 dev 上了。接下来,在 dev 分支 下修改 ReadMe 文件,新增一行内容,并进行一次提交操作。
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
on dev branch

        然后进行提交。

[qcr@ecs-205826 project]$ git add test.txt 
[qcr@ecs-205826 project]$ git commit -m "新增一行"
[dev d9412c1] 新增一行
 1 file changed, 1 insertion(+)

        这个时候再切回 master 分支,进行查看我们在 dev 分支下进行修改并提交的 test.txt 文件。

[qcr@ecs-205826 project]$ git checkout master
Switched to branch 'master'
[qcr@ecs-205826 project]$ git branch
  dev
* master
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello

        可以发现在 dev 上的修改并没有在 master 上体现出来。并且这个时候我们再打印 dev 里面的内容,可以发现发生了改变。

[qcr@ecs-205826 project]$ cat .git/refs/heads/dev 
d9412c152d40b391d55c01a75e60d99f78ef45cf

        也就是说 dev 分支其实也是每一次提交,对应进行一次的更新的,我们可以查看此处 dev 中更新的 commit id parent 是什么。

[qcr@ecs-205826 project]$ git cat-file -p d9412c152d40b391d55c01a75e60d99f78ef45cf
tree c7375ebb32b60c3e84d5b0f78b2cb6817060de54
parent dccd2a4405215cffcf40a12308449e27b1e58ea0
author qcr <2390139574@qq.com> 1688126065 +0800
committer qcr <2390139574@qq.com> 1688126065 +0800

新增一行

         可以发现,是创建完 dev 分支的时候里面保存的内容。也就是说我们在 dev 分支上,实现了一次的提交,实际上是进行了:

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

合并分支

        为了在 master 主分⽀上能看到新的提交,就需要将 dev 分⽀合并到 master 分⽀,合并后,master 就能看到 dev 分支提交的内容了,首先如果是想让 master 分支来合并 dev 分支,必须要先切到 master 分支上。

[qcr@ecs-205826 project]$ git branch
  dev
* master
[qcr@ecs-205826 project]$ git merge dev
Updating dccd2a4..d9412c1
Fast-forward
 test.txt | 1 +
 1 file changed, 1 insertion(+)

        这个时候我们再查看 test.txt 文件,可以发现 master 分支下的文件确实发生了改变。

[qcr@ecs-205826 project]$ git branch
  dev
* master
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
on dev branch

        并且 master 中存的 commit id 也变为了 dev 中的最新提交。

[qcr@ecs-205826 project]$ cat .git/refs/heads/master 
d9412c152d40b391d55c01a75e60d99f78ef45cf
[qcr@ecs-205826 project]$ cat .git/refs/heads/dev 
d9412c152d40b391d55c01a75e60d99f78ef45cf

        这个时候再回头看一看在 master 分支中合并 dev 分支的命令。

        Fast-forward 代表 “ 快进模式 ” ,也就是直接把 master 指向 dev 的当前提交,所以合并速度非常快。

Note:当然,也不是每次合并都能 Fast-forward,我们后⾯会讲其他方式的合并。

删除分支

        合并完成后,dev 分支对于我们来说就没用了,因为 dev 分支所需要达到的目标已经做到了,并且已经将结果交付给了 master 主分支,那么 dev 分支就需要被删除掉(荒废的分支会占用一定的资源,并且不利于管理)。

Note:如果当前正处于某分支下,就不能删除当前分⽀。

[qcr@ecs-205826 project]$ git branch
* dev
  master
[qcr@ecs-205826 project]$ git branch -d dev
error: Cannot delete the branch 'dev' which you are currently on.
[qcr@ecs-205826 project]$ git branch
  dev
* master
[qcr@ecs-205826 project]$ git branch -d dev
Deleted branch dev (was d9412c1).
[qcr@ecs-205826 project]$ git branch
* master

        此时的状态如图如下所示。 

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

合并冲突

        可是,在实际分支合并的时候,并不是想合并就能合并成功的,有时候可能会遇到代码冲突的问题。为了演示这问题,创建⼀个新的分支 dev ,并切换至目标分支。

Note:我们可以使用 git checkout -b dev ⼀步完成创建并切换的动作。

        大致操作流程:

[qcr@ecs-205826 project]$ git checkout -b dev
Switched to a new branch 'dev'
[qcr@ecs-205826 project]$ vim test.txt 
[qcr@ecs-205826 project]$ git add test.txt 
[qcr@ecs-205826 project]$ git commit -m "最后一行添加5个a"
[dev 0bd9eb1] 最后一行添加5个a
 1 file changed, 1 insertion(+), 1 deletion(-)
[qcr@ecs-205826 project]$ git checkout master
Switched to branch 'master'
[qcr@ecs-205826 project]$ vim test.txt 
[qcr@ecs-205826 project]$ git add test.txt 
[qcr@ecs-205826 project]$ git commit -m "最后一行添加5个b"
[master 88dbe15] 最后一行添加5个b
 1 file changed, 1 insertion(+), 1 deletion(-)

        于是我就得到了如下关系的两个分支。

        这个时候本地的仓库就如下图类似:

         这种情况下, Git 只能试图把各自的修改合并起来,但这种合并就可能会有冲突。
[qcr@ecs-205826 project]$ git branch
  dev
* master
[qcr@ecs-205826 project]$ git merge dev
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
        发现 test.txt 文件有冲突后,可以直接查看⽂件内容,要说的是 Git 会⽤ <<<<<<<、=======、>>>>>>> 来标记出不同分⽀的冲突内容,如下所示:
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
<<<<<<< HEAD
bbbbb on dev branch
=======
aaaaa on dev branch
>>>>>>> dev

        此时我们必须要手动调整冲突代码,并需要再次提交修正后的结果! (再次提交很重要,切勿忘记)
        我们需要自行的编写,来决定代码的保留。

        冲突修复完整之后就是对应的,一定需要进行的提交的操作。 

[qcr@ecs-205826 project]$ git add .
[qcr@ecs-205826 project]$ git commit -m "使用dev分支的变动"
[master 937bd7e] 使用dev分支的变动
         到这里冲突就解决完成,此时的状态变成了如下图所示:

        因为我们就是再之前的基础上,进行了又一次的提交。这个时候 master 就指向了最新的一次的提交了,但是 dev 还是执行的它的提交。

[qcr@ecs-205826 project]$ cat .git/refs/heads/master 
937bd7e54a78557ff84d4d0ab095f635b9b30596

[qcr@ecs-205826 project]$ cat .git/refs/heads/dev 
0bd9eb10a93857eb66698c86d21571715da0477d

[qcr@ecs-205826 project]$ git log --pretty=oneline
937bd7e54a78557ff84d4d0ab095f635b9b30596 使用dev分支的变动
88dbe15a8c877e05e17a1cbc8a0904ac1510a9d5 最后一行添加5个b
0bd9eb10a93857eb66698c86d21571715da0477d 最后一行添加5个a
d9412c152d40b391d55c01a75e60d99f78ef45cf 新增一行
dccd2a4405215cffcf40a12308449e27b1e58ea0 删除test3
1bba34a04f231d8ad49f3ce5079879144cf6f4db 临时空文件
8f2b55aca176fb578cf39952f776c3da9aa50009 新增一行
e797df72c0669a2b81339ff4854328126d2e6c8e 一行你好,用于学习git
        ⽤带参数的 git log 也可以看到分支的合并情况:
[qcr@ecs-205826 project]$ git log --graph --abbrev-commit
*   commit 937bd7e
|\  Merge: 88dbe15 0bd9eb1
| | Author: qcr <2390139574@qq.com>
| | Date:   Fri Jun 30 23:09:03 2023 +0800
| | 
| |     使用dev分支的变动
| |   
| * commit 0bd9eb1
| | Author: qcr <2390139574@qq.com>
| | Date:   Fri Jun 30 22:17:49 2023 +0800
| | 
| |     最后一行添加5个a
| |   
* | commit 88dbe15
|/  Author: qcr <2390139574@qq.com>
|   Date:   Fri Jun 30 22:18:45 2023 +0800
|   
|       最后一行添加5个b
|  
* commit d9412c1
| Author: qcr <2390139574@qq.com>
| Date:   Fri Jun 30 19:54:25 2023 +0800
| 
|     新增一行
|  
* commit dccd2a4
| Author: qcr <2390139574@qq.com>
| Date:   Sun Jun 18 20:48:38 2023 +0800
| 
:

        可以发现其左侧就与我们之前画的图一样。

        觉得太杂、太乱,可以再加一个选项,让其一行漂亮干净的显示。

[qcr@ecs-205826 project]$ git log --graph --abbrev-commit --pretty=oneline
*   937bd7e 使用dev分支的变动
|\  
| * 0bd9eb1 最后一行添加5个a
* | 88dbe15 最后一行添加5个b
|/  
* d9412c1 新增一行
* dccd2a4 删除test3
* 1bba34a 临时空文件
* 8f2b55a 新增一行
* e797df7 一行你好,用于学习git
        最后,不要忘记 dev 分支使用完毕后就可以删除了。
[qcr@ecs-205826 project]$ git branch
  dev
* master
[qcr@ecs-205826 project]$ git branch -d dev
Deleted branch dev (was 0bd9eb1).

分支管理策略

        通常合并分支时,如果可能 Git 会采⽤ Fast forward 模式。如果我们采用 Fast forward 模式之后,形成的合并结果如下图。

        在这种 Fast forward 模式下,删除分支后,查看分支历史时,会丢掉分支信息,看不出来最新提交到底是 merge 进来的还是正常提交的。
        举个例子: 接下来再创建一个分支 dev1 用于实现  Fast forward 模式:
[qcr@ecs-205826 project]$ git checkout -b dev1
Switched to a new branch 'dev1'
[qcr@ecs-205826 project]$ vim test.txt 
[qcr@ecs-205826 project]$ git add .
[qcr@ecs-205826 project]$ git commit -m "dev1分支下新增一行"
[dev1 93e5bb2] dev1分支下新增一行
 1 file changed, 1 insertion(+)
[qcr@ecs-205826 project]$ git checkout master
Switched to branch 'master'
[qcr@ecs-205826 project]$ git merge dev1
Updating 937bd7e..93e5bb2
Fast-forward
 test.txt | 1 +
 1 file changed, 1 insertion(+)

        接下来再让我们看一看 git log 下的情况(由于此处主要是看线路,所以查看简洁版)

[qcr@ecs-205826 project]$ git log --graph --abbrev-commit --pretty=oneline
* 93e5bb2 dev1分支下新增一行
*   937bd7e 使用dev分支的变动
|\  
| * 0bd9eb1 最后一行添加5个a
* | 88dbe15 最后一行添加5个b
|/  
* d9412c1 新增一行
* dccd2a4 删除test3
* 1bba34a 临时空文件
* 8f2b55a 新增一行
* e797df7 一行你好,用于学习git

        可以很明显的看出来:Fast forward 模式下,删除分支后,查看分支历史时,会丢掉分支信息,看不出来最新提交到底是 merge 进来的还是正常提交的。

        就算是详细显示也是一个样,但在合并冲突部分,我们也看到通过解决冲突问题,会再进行⼀次新的提交,得到的最终状态为:

        那么这就不是 Fast forward 模式了,这样的好处是,从分支历史上就可以看出分支信息。例如:我们现在已经删除了在合并冲突部分创建的 dev  分支 ,但依旧能看到 master 其实是由其他分支合并得到。
        其实 Git 支持我们强制禁用  Fast forward 模式,那么就会在 merge 时⽣成⼀个新的 commit ,这样从分⽀历史上就可以看出分⽀信息。
         举个例子: 接下来再创建一个分支 dev2 用于实现 强制禁用  Fast forward 模式:
[qcr@ecs-205826 project]$ git checkout -b dev2 
Switched to a new branch 'dev2'
[qcr@ecs-205826 project]$ vim test.txt 
[qcr@ecs-205826 project]$ git add .
[qcr@ecs-205826 project]$ git commit -m "在dev2分支下新增一行"
[dev2 803a10f] 在dev2分支下新增一行
 1 file changed, 1 insertion(+)
[qcr@ecs-205826 project]$ git checkout master
Switched to branch 'master'
        开始合并。 请注意 --no-ff 参数,表示禁用  Fast forward 模式。禁用  Fast forward 模式后合并会创建⼀个新的 commit ,所以加上 -m 参数,把描述写进去。
[qcr@ecs-205826 project]$ git merge --no-ff -m "merge dev2" dev2
Merge made by the 'recursive' strategy.
 test.txt | 1 +
 1 file changed, 1 insertion(+)
[qcr@ecs-205826 project]$ cat test.txt
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch

        现在再使用 git log 查看可以发现:

[qcr@ecs-205826 project]$ git log --graph --abbrev-commit --pretty=oneline
*   bb787c5 merge dev2
|\  
| * 803a10f 在dev2分支下新增一行
|/  
* 93e5bb2 dev1分支下新增一行
*   937bd7e 使用dev分支的变动
|\  
| * 0bd9eb1 最后一行添加5个a
* | 88dbe15 最后一行添加5个b
|/  
* d9412c1 新增一行
* dccd2a4 删除test3
* 1bba34a 临时空文件
* 8f2b55a 新增一行
* e797df7 一行你好,用于学习git

Note:所以在合并分支时,加上 --no-ff 参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而 fast forward 合并就看不出来曾经做过合并。

分支策略 

        在实际开发中,我们应该按照几个基本原则进行分支管理: 首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活,干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本。

        我们和我们的团队每个人都在 dev 分支上干活,每个人都有自己的分⽀,时不时地往dev分支上合并就可以了。 所以,团队合作的分支看起来就像这样:

bug 分支

        假如我们现在正在 dev 分支上进行开发,开发到⼀半,突然发现 master 分支上面有 bug,需要解决。在Git中,每个 bug 都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分支删除。

[qcr@ecs-205826 project]$ git checkout -b dev
Switched to a new branch 'dev'
[qcr@ecs-205826 project]$ vim test.txt 
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch
I am coding ……

        这个时候突然遇到了 bug ,我们就需要新建一个分支来进行 bug 的修复,虽然 dev 分支可以用来修复 bug ,但是这违背了开辟 dev 分支的初衷,其是用来开发部分的新需求的,而不是用来解决 bug 的。这个时候就需要切到 master 分支上,然后基于 master 分支进行创建一个新的分支用于解决 bug。

[qcr@ecs-205826 project]$ git checkout master
M	test.txt
Switched to branch 'master'

        这个时候我么可以看到,除了打印切换成功的一行提示之外,还多打印了一行。而大写的M就代表修改(modify),这个时候再让我们查看 master 分支上的 test.txt 会发现其也发生了更改(dev 的内容跑到了 master 上了)。

[qcr@ecs-205826 project]$ git checkout master
M	test.txt
Switched to branch 'master'
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch
I am coding ……

        这个时候查看当前状态。

[qcr@ecs-205826 project]$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   test.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

        可以发现 test.txt 文件只是再工作区中被修改了。虽然没有对我们的仓库进行影响,但是我们并不想在 master 上看到 dev 上的内容。Git 提供了 git stash 命令,可以将当前的工作区信息进行储藏,被储藏的内容可以在将来某个时间恢复出来。

Note:首先要在其对应的分支下。

[qcr@ecs-205826 project]$ git checkout dev
M	test.txt
Switched to branch 'dev'
[qcr@ecs-205826 project]$ git stash
Saved working directory and index state WIP on dev: 920acfc 有bug
HEAD is now at 920acfc 有bug

        通过查看 .git 中对应的文件,可以发现,refs 中多了一个对应的 stash 文件。这个文件里就是临时抱保存的工作区中的代码数据。

        这个时候在查看当前仓库状态,就可以发现工作区是干净的。

[qcr@ecs-205826 project]$ git status
# On branch dev
nothing to commit, working directory clean
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch

        而 stash 里面存的其实是已经被 Git 追踪、管理的一些文件,而如果是 touch 一个文件,然后其只是在工作区中新建了,并没有进行 add、commit 操作,其是不属于 Git 追踪、管理的文件。这个时候就是不可以被 git stash 命令,进行储藏:

[qcr@ecs-205826 project]$ touch tmp.txt
[qcr@ecs-205826 project]$ git stash
No local changes to save

        提示为:没有一些变动需要存储。

        当存储起来之后,就可以发现 test.txt 文件里面新增的内容也就没有了。储藏 dev 工作区之后,由于我们要基于 master 分支修复 bug,所以需要切回 master 分支,再新建临时分支来修复 bug。

[qcr@ecs-205826 project]$ git checkout -b fit_bug
Switched to a new branch 'fit_bug'
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch
[qcr@ecs-205826 project]$ vim test.txt 
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
aaaaa on dev1 branch
aaaaa on dev2 branch
[qcr@ecs-205826 project]$ git add . 
[qcr@ecs-205826 project]$ git commit -m "修复内容不完整的bug"
[fit_bug 171cefc] 修复内容不完整的bug
 1 file changed, 2 insertions(+), 2 deletions(-)

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

[qcr@ecs-205826 project]$ git checkout master
Switched to branch 'master'
[qcr@ecs-205826 project]$ git merge --no-ff -m "merge fit_bug" fit_bug
Merge made by the 'recursive' strategy.
 test.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
[qcr@ecs-205826 project]$ git branch -d fit_bug
Deleted branch fit_bug (was 171cefc).

        此时,bug 的修复工作已经做完了。

[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
aaaaa on dev1 branch
aaaaa on dev2 branch
        至此,我们还要继续回到 dev 分支进行开发。
[qcr@ecs-205826 project]$ git checkout dev
Switched to branch 'dev'
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch

        然而此时,工作区是干净的,刚才的工作现场存到哪去了?需要用 git stash list 命令进行查看。

[qcr@ecs-205826 project]$ git stash list
stash@{0}: WIP on dev: 920acfc 有bug
        工作现场还在,Git 把 stash 内容存在某个地方了,但是需要恢复⼀下,我们可以使用  git stash pop 命令,并且恢复的同时会把 stash 也删了。
[qcr@ecs-205826 project]$ git stash pop
# On branch dev
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#	modified:   test.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (ec2f9704d78aec920b0ef53a711241e3ce3c215b)
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch
I am coding ……

        这个时候可以看见,工作区中原有的内容是恢复过来了,但是原有的 "ont" bug是并未被修复的。原因就是因为,创建 dev 分支的时候,是基于 master 的 bug 提交所创建出来的,而 master 分支下的 bug 是已经被修复了的,所以并不会影响。

        此时,dev 中的新项目的开发完成了,并进行了提交。

[qcr@ecs-205826 project]$ vim test.txt 
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch
I am coding … done
[qcr@ecs-205826 project]$ git add .
[qcr@ecs-205826 project]$ git commit -m "新功能更新完成"
[dev bdea1fa] 新功能更新完成
 1 file changed, 1 insertion(+)

        master 分支目前最新的提交,是要领先于新建 dev 分支时基于的 master 分支的提交的,所以在 dev 中当然看不见修复 bug 的相关代码。

不建议的合并方式

        我们最终目的是要让 master 合并 dev 分支的,那么正常情况下我们切回 master 分支直接合并即可,但这样其实是有⼀定风险的。是因为在合并分支时可能会有冲突,而代码冲突需要我们手动解决(在 master 上解决)。我们无法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项目中,代码冲突不只⼀两行那么简单,有可能几十上百行甚至更多,解决的过程中难免手误出错,导致错误的代码被合并到 master 上。

建议的合并方式

        解决这个问题的⼀个好的建议就是:最好在自己的分支上合并下 master ,再让 master 去合并 dev ,这样做的目的是有冲突可以在本地分支解决并进行测试,而不影响 master

        接下来就是实操。

第一步

        首先我们需要将 dev 与 master 进行合并。

[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
ont dev1 branch
on dev2 branch
I am coding … done
[qcr@ecs-205826 project]$ git branch
* dev
  master
[qcr@ecs-205826 project]$ git merge --no-ff -m "merge master" master
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
<<<<<<< HEAD
ont dev1 branch
on dev2 branch
I am coding … done
=======
aaaaa on dev1 branch
aaaaa on dev2 branch
>>>>>>> master

        发现在 test.txt 中是有冲突的,但是这一次是无所谓的,因为这一次冲突是在本地分支上的,在本地分支上就可以随意的修改了。

[qcr@ecs-205826 project]$ vim test.txt 
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
aaaaa on dev1 branch
aaaaa on dev2 branch
I am coding … done
[qcr@ecs-205826 project]$ git add .
[qcr@ecs-205826 project]$ git commit -m "合并与master的冲突"
[dev c6eafd4] 合并与master的冲突

第二步

        然后就可以切换到 master 上,进行dev的没有冲突的合并了。

[qcr@ecs-205826 project]$ git checkout master
Switched to branch 'master'
[qcr@ecs-205826 project]$ git merge --no-ff -m "merge dev" dev
Merge made by the 'recursive' strategy.
 test.txt | 1 +
 1 file changed, 1 insertion(+)
[qcr@ecs-205826 project]$ cat test.txt 
你好
hello
aaaaa on dev branch
aaaaa on dev1 branch
aaaaa on dev2 branch
I am coding … done
[qcr@ecs-205826 project]$ git branch -d dev
Deleted branch dev (was c6eafd4).

删除临时分支​​​​​​​

        软件开发中,总有无穷无尽的新的功能要不断添加进来。
        添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个分支,我们可以将其称之为 feature 分支,在上面开发。完成后,合并,最后删除该 feature 分支。
        可是,如果我们今天正在某个 feature 分支上开发了一半,被产品经理突然叫停,说是要停止新功能的开发。虽然白干了,但是这个 feature 分支还是必须就地销毁,留着无用了。这时使用传统的 git branch -d 命令删除分支的方法是不行的。因为之前使用这个命令进行删除分支的时候,该分支都是已经进行了 merge 操作的,这样 Git 才支持我们删的。
        如果是一个我们还未进行 merge 操作的时候,并且还在该分支上,进行了一定的提交操作, Git 就会保护这个分支,因为 Git 认为只要我们创建出来的分支就是有用的!这个时候需要使用  git branch -d 命令强行删除分支。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/710451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java 全局、局部异常处理详解及result结果封装

1、引入spring-boot-starter-web依赖和new-swagger依赖 <dependency><groupId>com.jjw</groupId><artifactId>new-swagger</artifactId><version>1.0-SNAPSHOT</version> </dependency> <dependency><groupId>or…

Linux系统编程:进程的替换

目录 一. 进程替换的原理 二. 进程替换的方法 2.1 进程替换的相关函数 2.2 进程替换为其它的C/C程序或其它语言编写的程序 三. 自主实现简单地命令行解释器 四. 总结 一. 进程替换的原理 进程替换&#xff0c;就是对进程所执行的代码进行替换&#xff0c;让正在运行的一个…

华为OD机试真题 Python 实现【简单的自动曝光】【2023Q1 100分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、备注五、解题思路六、Python算法源码七、效果展示1、输入2、输出3、说明4、再输入5、输出6、说明 一、题目描述 一个图像有 n 个像素点&#xff0c;存储在一个长度为 n 的数组 img 里&#xff0c;每个像素点的取值范围[0,255]的…

HOT33-排序链表

leetcode原题链接&#xff1a;排序链表 题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4]示例 2&#xff1a; 输入&#xff1a;head [-1,5,3,4,0] 输出…

html内盒子长宽增加溢出但是外盒子不自动向下延

自动扩展 问题描述 外盒子设置固定px&#xff0c;导致内盒子如图片长宽增加后&#xff0c;溢出但是外盒子不自动扩展&#xff08;向下延申&#xff09; 图片高230时正常 设置250后超出 问题解决 /*height: 660px;*/ /*设死就不能自动扩展&#xff0c;内块块长宽超出&#x…

vuex-persistedstate —— 数据持久化

在之前的篇目当中对于 Vuex 中的相关内容都讲得差不多&#xff0c;但是在项目中去使用vuex&#xff0c;虽然数据状态得到管理了&#xff0c;但数据在每一次都需要去重新加载&#xff0c;那么对于数据的持久化vue是没有给解决的&#xff0c;而是通过第三方的工具去进行数据的持久…

代码随想录算法训练营第17期第4天(5休息) | 24. 两两交换链表中的节点、19. 删除链表的倒数第 N 个结点、面试题 02.07. 链表相交、​​​​​​142. 环形链表 II

目录 24. 两两交换链表中的节点 19. 删除链表的倒数第 N 个结点 面试题 02.07. 链表相交 ​​​​​​142. 环形链表 II 这题不是很难&#xff0c;目前除了从【.】变成了【->】之外&#xff0c;python和C也没啥区别 另外就是对虚拟头结点的掌握了 /*** Definition for …

爬虫小白入门在服务器上-部署爬虫或者开服务接口并供给他人访问

目录 一、准备工作-服务器1、先准备一个服务器&#xff08;以阿里云为例子&#xff09;2、开通服务端口号访问权限 二、准备工作-Xshell登录服务器1、xshell基本登录操作2、xftp基本操作 三、部署代码到服务器上1、部署一个python爬虫脚本在服务器上定时运行等2、部署一个pytho…

Java-API简析_占位符类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意&#xff0c;谢绝转载&#xff01;&#xff08;请尊重原创&#xff0c;博主保留追究权&#xff09; https://blog.csdn.net/m0_69908381/article/details/131504916 出自【进步*于辰的博客】 因为我发现目前&#xff0c;我对Java-API的学习意识比较薄弱…

区块链开发:JS/TS本地|项目环境搭建

区块链开发&#xff1a;JS/TS本地|项目环境搭建 本地环境搭建VSCode Solidity扩展全局安装Solc,corepackVSCode配置本地Solc安装Ganache搭建JS虚拟环境 项目测试安装依赖编写代码部署合约test_blockchain.ts 设置Script部署查看 报错说明1. Error&#xff1a;missing revert da…

【EasyX】使用C/C++实现 流星雨效果(配上详细注释解释)

&#x1f38a;专栏【​​​​​​​EasyX】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Love Story】 &#x1f970;大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 文章目录 &#x1f354;效果&#x…

RNN LSTM

参考资料&#xff1a; 《机器学习2022》李宏毅史上最详细循环神经网络讲解&#xff08;RNN/LSTM/GRU&#xff09; - 知乎 (zhihu.com) LSTM如何来避免梯度弥散和梯度爆炸&#xff1f; - 知乎 (zhihu.com) 1 RNN 的结构 首先考虑这样一个 slot filling 问题&#xff1a; 注意…

云解析DNS

云解析过程&#xff1a; DNS查询的结果通常会在本地域名服务器中进行缓存&#xff0c;如果本地域名服务器中有缓存的情况下&#xff0c;则会跳过如下DNS查询步骤&#xff0c;很快返回解析结果。下面的示例则概述了本地域名服务器没有缓存的情况下&#xff0c;DNS查询所需的8个步…

电路的组成和连接方式-通路、开路、短路

电路是电子设备中最基本的组成部分之一&#xff0c;它由各种电子元件组成&#xff0c;并通过连接方式构建成不同的电路结构。在电路设计和维护中&#xff0c;通路、开路和短路是常见的概念&#xff0c;它们分别代表了电路中不同的连接状态和故障情况。 工具认识&#xff1a; …

万能的微信小程序个人主页:商城系统个人主页、外卖系统个人主页、购票系统个人主页等等【全部源代码分享+页面效果展示+直接复制粘贴编译即可】

前言 以下给出来四个常见的小程序个人主页,分别是商城系统个人主页,外卖系统个人主页,挂号系统个人主页,电影购票系统个人主页。包括完整的页面布局代码,完整的样式代码。使用的时候,只需要将页面代码和样式代码复制到自己项目对应的页面即可。而且可以根据已有代码只需稍…

【机器学习】准确率、精确度、召回率和 F1 定义

一、说明 数据科学家选择目标变量后 - 例如他们希望预测电子表格中的“列”&#xff0c;并完成了转换数据和构建模型的先决条件&#xff0c;最后步骤之一是评估模型的性能。 二、混淆矩阵的模型 2.1 混淆矩阵 选择性能指标通常取决于要解决的业务问题。假设您的数据集中有 10…

电子时钟制作(瑞萨RA)(2)----使用串口进行程序烧写

概述 本篇文章主要介绍如何使用UART串口烧写程序到瑞萨芯片&#xff0c;并以实际项目进行演示。 硬件准备 首先需要准备一个开发板&#xff0c;这里我准备的是芯片型号R7FA2E1A72DFL的开发板&#xff1a; 视频教程 https://www.bilibili.com/video/BV1kX4y1v7tL/ 电子时钟制…

Symbol.for()

示例&#xff1a;Symbol() 和 Symbol.for(‘ ’)的区别 Symbol.for("foo"); // 创建一个 symbol 并放入 symbol 注册表中&#xff0c;键为 "foo" Symbol.for("foo"); // 从 symbol 注册表中读取键为"foo"的 symbolSymbol.for("b…

常见面试题之线程池

1. 说一下线程池的核心参数&#xff08;线程池的执行原理知道嘛&#xff09;&#xff1f; 线程池核心参数主要参考ThreadPoolExecutor这个类的7个参数的构造函数 corePoolSize 核心线程数目 maximumPoolSize 最大线程数目 (核心线程救急线程的最大数目) keepAliveTime 生存…

蘑菇车联用城市级落地讲述自动驾驶新故事

作者 | 魏启扬 来源 | 洞见新研社 “如果不能实现自动驾驶&#xff0c;特斯拉将一文不值”。 这是马斯克在接受媒体采访时的公开发言&#xff0c;这句话的语境是&#xff0c;特斯拉是自动驾驶坚实的拥护者&#xff0c;且一直在付诸行动。 可是特斯拉渐进式的单车智能路线&am…