欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > 【git#4】分支管理 -- 知识补充

【git#4】分支管理 -- 知识补充

2025/4/26 15:12:01 来源:https://blog.csdn.net/island1314/article/details/147500767  浏览:    关键词:【git#4】分支管理 -- 知识补充

一、bug 分支

假如我们现在正在 dev2 分支上进行开发,开发到一半,突然发现 master 分支上面有 bug,需要解决。

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

可现在 dev2 的代码在工作区中开发了一半,还无法提交,怎么办?例如:

lighthouse@VM-8-10-ubuntu:gitcode$ git branch
* dev2masterlighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
Hello World
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d
I am coding...lighthouse@VM-8-10-ubuntu: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:   bookno changes added to commit (use "git add" and/or "git commit -a")

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

lighthouse@VM-8-10-ubuntu:gitcode$ git stash
Saved working directory and index state WIP on dev2: 2bd7b8b modify Readme
lighthouse@VM-8-10-ubuntu:gitcode$ git status
On branch dev2
nothing to commit, working tree clean

git status 查看工作区,就是干净的(除非有没有被 Git 管理的文件),因此可以放心地创建分支来修复bug。

储藏 dev2 工作区之后,由于我们要基于 master 分支修复 bug,所以需要切回 master 分支,再新建临时分支来修复 bug,示例如下:

lighthouse@VM-8-10-ubuntu:gitcode$ git checkout -b fix_bg # 新建并切换
Switched to a new branch 'fix_bg'
lighthouse@VM-8-10-ubuntu:gitcode$ vim book
lighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
Hello World
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d,e
lighthouse@VM-8-10-ubuntu:gitcode$ git add book
lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "fix bug"
[fix_bg c0637e0] fix bug1 file changed, 1 insertion(+), 1 deletion(-)

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

lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
Switched to branch 'master'
lighthouse@VM-8-10-ubuntu:gitcode$ git merge --no-ff -m "merge fix_bug branch" fix_bg
Merge made by the 'ort' strategy.book | 2 +-1 file changed, 1 insertion(+), 1 deletion(-)

至此,bug的修复工作已经做完了,我们还要继续回到 dev2 分支进行开发。切换回 dev2 分支:

lighthouse@VM-8-10-ubuntu:gitcode$ git checkout dev2
Switched to branch 'dev2'
lighthouse@VM-8-10-ubuntu:gitcode$ git status
On branch dev2
nothing to commit, working tree clean

工作区是干净的,刚才的工作现场存到哪去了?用 git stash list 命令看看:

lighthouse@VM-8-10-ubuntu:gitcode$ git stash list
stash@{0}: WIP on dev2: 2bd7b8b modify Readme

工作现场还在,Git 把 stash 内容存在某个地方了,但是需要恢复一下,如何恢复现场呢?我们可以使用 git stash pop 命令,恢复的同时会把 stash 也删了,示例如下:

lighthouse@VM-8-10-ubuntu:gitcode$ git stash pop
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:   bookno changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (e2dfd6d0312e2454d1a7a4a3eb65cf3e28f333af)

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

lighthouse@VM-8-10-ubuntu:gitcode$ git stash list
lighthouse@VM-8-10-ubuntu:gitcode$ 

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

  • 当然也可以多次 stash,恢复的时候,先用 git stash list 查看,然后恢复指定的 stash,用命令git stash apply stash@{o}

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

lighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
Hello World
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d
I am coding... Done
lighthouse@VM-8-10-ubuntu:gitcode$ git add .
lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "modify book"
[dev2 ccb0f97] modify book1 file changed, 1 insertion(+)

但我们注意到了,修复 bug的内容,并没有在 dev2 上显示。此时的状态图为:

image-20250408222829805

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

  • 我们的最终目的是要让 master 合并 dev2 分支的,那么正常情况下我们切回 master 分支直接合并即可,但这样其实是有一定风险的

原因:在合并分支时可能会有冲突,而代码冲突需要我们手动解决(在 master上解决)

  • 我们无法保证对于冲突问题可以正确地一次性解决掉,因为在实际的项目中,代码冲突不只一两行那么简单,有可能几十上百行,甚至更多,解决的过程中难免手误出错,导致错误的代码被合并到 master 上。

此时的状态为:

image-20250408223022215

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

此时的状态为:

image-20250408223401563

image-20250408223405993

对应的实操演示如下,要说明的是,以下演示的merge操作,没有使用 --no-ff ,但上述的图示是禁用 Fast forward 了模式后得出的,主要是为了方便解释问题。

# dev 合并 master
lighthouse@VM-8-10-ubuntu:gitcode$ git branch
* dev2master
lighthouse@VM-8-10-ubuntu:gitcode$ git merge master
Auto-merging book
CONFLICT (content): Merge conflict in book
Automatic merge failed; fix conflicts and then commit the result.# 发送冲突
lighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
Hello World
hello version1
hello version2
hello version3
write bbb for new branch
<<<<<<< HEAD
a,b,c,d
I am coding... Done
=======
a,b,c,d,e
>>>>>>> master# 解决冲突并重新提交
lighthouse@VM-8-10-ubuntu:gitcode$ vim book
lighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
Hello World
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d,e
I am coding... Done
lighthouse@VM-8-10-ubuntu:gitcode$ git add .
lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "merge master"
[dev2 9e77002] merge master
lighthouse@VM-8-10-ubuntu:gitcode$ git status
On branch dev2
nothing to commit, working tree clean# 切回 master
lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
Switched to branch 'master'# master 合并 dev2  -- 无需解决冲突
lighthouse@VM-8-10-ubuntu:gitcode$ git merge dev2
Updating adbb267..9e77002
Fast-forwardbook | 1 +1 file changed, 1 insertion(+)
lighthouse@VM-8-10-ubuntu:gitcode$ git status
On branch master
nothing to commit, working tree clean# 删除 dev2 分支
lighthouse@VM-8-10-ubuntu:gitcode$ git branch -d dev2
Deleted branch dev2 (was 9e77002).
lighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
Hello World
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d,e
I am coding... Done

二、强制删除分支

软件开发中,总有无穷无尽的新的功能要不断添加进来

  • 添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个分支,我们可以将其称之为 feature 分支,在上面开发,完成后,合并,最后,删除该 feature 分支。
  • 可是,如果我们今天正在某个 feature 分支上开发了一半,被产品经理突然叫停,说是要停止新功能的开发。虽然白干了,但是这个 feature 分支还是必须就地销毁,留着无用了。
  • 这时使用传统的 git branch -d 命令删除分支的方法是不行的。

演示如下:

# 新增并切换到 dev3 分支
lighthouse@VM-8-10-ubuntu:gitcode$ git checkout -b dev3
Switched to a new branch 'dev3'
lighthouse@VM-8-10-ubuntu:gitcode$ clear# 开始开发新功能并提交
lighthouse@VM-8-10-ubuntu:gitcode$ vim book
lighthouse@VM-8-10-ubuntu:gitcode$ cat book
Hello Island1314
Hello World
hello version1
hello version2
hello version3
write bbb for new branch
a,b,c,d,e
I am coding... Done
I am writing new features ...
lighthouse@VM-8-10-ubuntu:gitcode$ git add .
lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "modify book for new features"
[dev3 fb6a737] modify book for new features1 file changed, 1 insertion(+)# 此时新功能叫停, 切回 master 准备删除 dev3
lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
Switched to branch 'master'

对 dev3 进行删除,如下:

# 常规删除 dev3 分支时失败
lighthouse@VM-8-10-ubuntu:gitcode$ git branch -d dev3
error: The branch 'dev3' is not fully merged.
If you are sure you want to delete it, run 'git branch -D dev3'.
# 按照提示进行删除
lighthouse@VM-8-10-ubuntu:gitcode$ git branch -D dev3
Deleted branch dev3 (was fb6a737).

三、分支的作用

🌊 分支在实际中有什么用呢?

  • 假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。
  • 如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
  • 现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

而且 Git 无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件

四、细节补充

1. 未提交修改时(未commit

当我们在 dev 分支下修改文件之后,master 还是可以看到的(没有 add 的情况下),如下:

lighthouse@VM-8-10-ubuntu:gitcode$ git checkout dev
Switched to branch 'dev'
lighthouse@VM-8-10-ubuntu:gitcode$ vim filelighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
Switched to branch 'master'
lighthouse@VM-8-10-ubuntu:gitcode$ cat file
i miss you # master 分支
I Miss You # dev 分支lighthouse@VM-8-10-ubuntu:gitcode$ git checkout dev
Switched to branch 'dev'
lighthouse@VM-8-10-ubuntu:gitcode$ git add file
lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
A	file
Switched to branch 'master'
lighthouse@VM-8-10-ubuntu:gitcode$ cat file
i miss you # master 分支
I Miss You # dev 分支
  • 工作目录是共享的:所有未提交的改动(包括未 add 的修改和已 add 但未 commit 的暂存)都存在于工作目录中,不会被 Git 自动隔离到特定分支
  • 切换分支时的行为
    • 如果目标分支(如 master)和当前分支(如 dev)对同一文件的修改不冲突,Git 允许直接切换,并保留工作目录的改动。
    • 因此,在未提交的情况下,无论切换到哪个分支,看到的都是工作目录中的当前内容(即未提交的修改)

2. 已提交修改后

而当我们在 切换到 dev 分支进行 commit 之后,然后再切换到 master 分支查看,然后 如下:

lighthouse@VM-8-10-ubuntu:gitcode$ git checkout dev
A	file
Switched to branch 'dev'
lighthouse@VM-8-10-ubuntu:gitcode$ git commit file
Aborting commit due to empty commit message.
lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "改变" file
[dev 1a1993f] 改变1 file changed, 2 insertions(+)create mode 100644 file
  • 提交 (commit) 的作用:将暂存区的内容永久记录到当前分支的历史中,此时修改正式归属于 dev 分支。
  • 切换分支时的行为
    • Git 会严格根据目标分支(如 master)的最新提交重建工作目录
    • 如果 master 分支从未包含 file 文件(即该文件只在 dev 分支提交过,下面等下会细说这个问题),切换到 master 时,Git 会删除工作目录中的 file 文件,因为 master 分支的历史中不存在它

总结

  • 提交后,数据已保存在 dev 分支的历史中,不会丢失。
  • master 分支的工作区被重建为它自己的最新提交状态,因此看不到 dev 分支的改动。

这里要说一下,由于我们在 master 分支下没有 commit 过文件,因此当我们在 dev下首次 commit,那么 master 分支下的 file 文件就会消失,如下:

lighthouse@VM-8-10-ubuntu:gitcode$ cat file
i miss you # master 分支
I Miss You # dev 分支lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
Switched to branch 'master'
lighthouse@VM-8-10-ubuntu:gitcode$ cat file
cat: file: No such file or directory
lighthouse@VM-8-10-ubuntu:gitcode$ ll
total 20
drwxrwxr-x 4 lighthouse lighthouse 4096 Apr 18 19:52 ./
drwxrwxr-x 7 lighthouse lighthouse 4096 Apr 15 21:47 ../
-rw-rw-r-- 1 lighthouse lighthouse  129 Apr  8 23:05 book
drwxrwxr-x 8 lighthouse lighthouse 4096 Apr 18 19:52 .git/
drwxrwxr-x 3 lighthouse lighthouse 4096 Apr 10 22:29 git_learning/

初始状态

  • master 分支未提交过 file 文件(或该文件未被跟踪)。
  • 你在 dev 分支修改并提交了 file,此时 file 成为 dev 分支的一部分。

切换回 master

  • master 分支没有 file 的记录,Git 会清理工作目录,删除 file 文件以匹配 master 分支的状态

因此分支交换的逻辑,可以这样理解,如下:

  • 未提交时
    • 如果修改未提交,Git 在切换分支时会尽量保留工作区内容(除非目标分支和当前修改冲突)。
    • 保留的原因:并非“怕数据丢失”,而是为了用户能自由切换分支并继续工作。例如,你在 dev 修改了文件,想临时切到 master 修复问题,Git 允许携带未提交的修改切换(只要不冲突)。
  • 提交后
    • 提交的修改会写入 dev 分支的历史记录,此时 dev 分支的最新提交包含该文件,而 master 分支的历史记录中没有该文件。
    • 切换回 master 时,Git 会根据 master 的最新提交重建工作区,因此文件会消失(因为 master 从未记录过它)。

3. 如何避免问题

  • 提交前检查分支状态:确保在正确的分支提交改动。
  • 使用 git stash:临时保存未提交的修改,切换分支后再恢复
    • 核心功能:临时保存工作区和暂存区的未提交修改,清空工作区,使其“干净”(与当前分支的最新提交一致)
    • 效果:切换分支时,未提交的修改不会被带到其他分支(避免意外覆盖或冲突)
  • 理解文件跟踪:新增文件需通过 git addcommit 明确添加到分支历史中。
  • 未提交的修改:属于工作目录,切换分支时可能保留(除非冲突)。
  • 已提交的修改:属于特定分支的历史,切换分支时 Git 会严格重建工作目录以匹配目标分支

这就是为什么在提交后切换到 master 时文件“消失”的原因——Git 严格遵循分支的历史记录管理文件

4. 重新理解 工作区、暂存区、版本库

  1. 工作区(Working Directory)

    • 所有分支共享同一个物理工作目录,未提交的修改(无论是否 add)都存在于工作区中,不直接绑定到任何分支
    • 工作区的内容会根据当前分支的最新提交动态变化
  2. 暂存区(Staging Area):同样全局共享,git add 后的内容属于暂存区,与分支无关。

  3. 版本库(Repository)

    • 提交(commit)后,修改会绑定到当前分支的历史记录中,不同分支的提交历史是独立的
    • 提交后的内容属于分支的历史记录,与工作区无关

但是看到这里,也许大家也会有点问题,就是当 commit 之后,那么产生的文件在两个分支下不就内容不一样了吗,此时它两也能算得上全局共享嘛???

解释如下

假设有一个文件 file.txt,初始状态如下:

步骤 1:在 master 分支创建文件并提交

git checkout master
echo "Hello from master" > file.txt
git add file.txt
git commit -m "Add file in master"

此时:

  • master 分支的提交历史包含 file.txt
  • 工作区中的 file.txt 内容是 Hello from master

步骤 2:创建 dev 分支并修改文件

git checkout -b dev
echo "Hello from dev" > file.txt
git add file.txt
git commit -m "Update file in dev"

此时:

  • dev 分支的提交历史包含修改后的 file.txt(内容是 Hello from dev)。
  • master 分支的提交历史仍为旧版本(内容是 Hello from master)。

步骤 3:切换回 master 分支查看文件

git checkout master
cat file.txt
Hello from master
关键现象解释
  1. 为什么切换分支后文件内容变了?
    • Git 会根据目标分支的最新提交重建工作区
    • master 分支的最新提交是原始版本,而 dev 分支的最新提交是修改后的版本。
  2. 工作区是“共享”的吗?
    • 物理上共享:所有分支操作同一块磁盘区域。
    • 逻辑上隔离:切换分支时,Git 会覆盖工作区内容,使其匹配目标分支的提交。
    • 你可以理解为:工作区是“共享的舞台”,但每次切换分支时,Git 会更换舞台上的“布景”
  3. 提交后的文件到底属于谁?
    • 提交后的内容属于分支的历史记录,不直接绑定到工作区。
    • dev 分支的提交历史中有一个新版本的 file.txt,而 master 分支的提交历史中仍是旧版本。

全局共享 vs 分支独立
区域是否全局共享?是否受分支切换影响?
工作区✅ 是(所有分支共享同一物理目录)✅ 是(切换分支时内容会被覆盖)
暂存区✅ 是✅ 是(切换分支时可能被覆盖)
版本库(提交)❌ 否(每个分支有独立提交历史)❌ 否(提交历史永久绑定到分支)

疑问解决
  • 你的问题

    “commit 之后,产生的文件在两个分支下内容不一样了,此时它们还能算全局共享吗?”

  • 答案

    • 工作区本身是共享的,但它的内容会根据当前分支的提交历史动态变化。
    • 提交后的差异是分支历史隔离的结果,而不是工作区本身的隔离。
    • 你可以想象工作区是一个“画布”,而不同分支是“不同的画作版本”。每次切换分支时,Git 会擦掉当前画布上的内容,重新绘制目标分支对应的画作。

总结
  • 工作区共享:所有分支操作同一块磁盘区域,但内容由当前分支的提交历史决定。
  • 提交隔离:不同分支的提交历史独立,切换分支时 Git 会严格按目标分支的历史重建工作区。
  • 看似矛盾的现象:工作区是共享的,但提交后的文件在不同分支下内容不同,这正是 Git 分支机制的核心设计——通过动态覆盖工作区内容,实现高效的多分支协作

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词