【Git#4】分支管理 -- 知识增补 [复制链接]
发表于 2025-9-21 22:19:34 | 显示全部楼层 |阅读模式
一、bug 分支

假如我们如今正在 dev2 分支上举行开辟,开辟到一半,突然发现 master 分支上面有 bug,须要办理。

  • 在Git中,每个 bug 都可以通过一个新的暂时分支来修复,修复后,归并分支,然后将暂时分支删除。
可如今 dev2 的代码在工作区中开辟了一半,还无法提交,怎么办?例如:
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git branch
  2. * dev2
  3.   master
  4. lighthouse@VM-8-10-ubuntu:gitcode$ cat book
  5. Hello Island1314
  6. Hello World
  7. hello version1
  8. hello version2
  9. hello version3
  10. write bbb for new branch
  11. a,b,c,d
  12. I am coding...
  13. lighthouse@VM-8-10-ubuntu:gitcode$ git status
  14. On branch dev2
  15. Changes not staged for commit:
  16.   (use "git add <file>..." to update what will be committed)
  17.   (use "git restore <file>..." to discard changes in working directory)
  18.         modified:   book
  19. no changes added to commit (use "git add" and/or "git commit -a")
复制代码
Git 提供了 git stash 下令,可以将当前的工作区信息举行蕴藏,被蕴藏的内容可以在将来某个时间规复出来。
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git stash
  2. Saved working directory and index state WIP on dev2: 2bd7b8b modify Readme
  3. lighthouse@VM-8-10-ubuntu:gitcode$ git status
  4. On branch dev2
  5. nothing to commit, working tree clean
复制代码
用 git status 检察工作区,就是干净的(除非有没有被 Git 管理的文件),因此可以放心地创建分支来修复bug。
蕴藏 dev2 工作区之后,由于我们要基于 master 分支修复 bug,以是须要切回 master 分支,再新建暂时分支来修复 bug,示例如下:
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout -b fix_bg # 新建并切换
  2. Switched to a new branch 'fix_bg'
  3. lighthouse@VM-8-10-ubuntu:gitcode$ vim book
  4. lighthouse@VM-8-10-ubuntu:gitcode$ cat book
  5. Hello Island1314
  6. Hello World
  7. hello version1
  8. hello version2
  9. hello version3
  10. write bbb for new branch
  11. a,b,c,d,e
  12. lighthouse@VM-8-10-ubuntu:gitcode$ git add book
  13. lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "fix bug"
  14. [fix_bg c0637e0] fix bug
  15. 1 file changed, 1 insertion(+), 1 deletion(-)
复制代码
修复完成后,切换到 master 分支,并完成归并,末了删除 fix_bg 分支
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
  2. Switched to branch 'master'
  3. lighthouse@VM-8-10-ubuntu:gitcode$ git merge --no-ff -m "merge fix_bug branch" fix_bg
  4. Merge made by the 'ort' strategy.
  5. book | 2 +-
  6. 1 file changed, 1 insertion(+), 1 deletion(-)
复制代码
至此,bug的修复工作已经做完了,我们还要继续回到 dev2 分支举行开辟。切换回 dev2 分支:
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout dev2
  2. Switched to branch 'dev2'
  3. lighthouse@VM-8-10-ubuntu:gitcode$ git status
  4. On branch dev2
  5. nothing to commit, working tree clean
复制代码
工作区是干净的,刚才的工作现场存到哪去了?用 git stash list 下令看看:
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git stash list
  2. stash@{0}: WIP on dev2: 2bd7b8b modify Readme
复制代码
工作现场还在,Git 把 stash 内容存在某个地方了,但是须要规复一下,怎样规复现场呢?我们可以使用 git stash pop 下令,规复的同时会把 stash 也删了,示例如下:
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git stash pop
  2. On branch dev2
  3. Changes not staged for commit:
  4.   (use "git add <file>..." to update what will be committed)
  5.   (use "git restore <file>..." to discard changes in working directory)
  6.         modified:   book
  7. no changes added to commit (use "git add" and/or "git commit -a")
  8. Dropped refs/stash@{0} (e2dfd6d0312e2454d1a7a4a3eb65cf3e28f333af)
复制代码
再次检察的时间,我们已经发现已经没有现场可以规复了
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git stash list
  2. lighthouse@VM-8-10-ubuntu:gitcode$
复制代码
别的,规复现场也可以接纳 git stash apply 规复,但是规复后,stash内容并不删除,你须要用 git stash drop 来删除;

  • 固然也可以多次 stash,规复的时间,先用 git stash list 检察,然后规复指定的 stash,用下令git stash apply stash@{o}
规复完代码之后我们便可以继续完成开辟,开辟完成后便可以举行提交,例如
  1. lighthouse@VM-8-10-ubuntu:gitcode$ cat book
  2. Hello Island1314
  3. Hello World
  4. hello version1
  5. hello version2
  6. hello version3
  7. write bbb for new branch
  8. a,b,c,d
  9. I am coding... Done
  10. lighthouse@VM-8-10-ubuntu:gitcode$ git add .
  11. lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "modify book"
  12. [dev2 ccb0f97] modify book
  13. 1 file changed, 1 insertion(+)
复制代码
但我们注意到了,修复 bug的内容,并没有在 dev2 上表现。此时的状态图为:

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

  • 我们的终极目的是要让 master 归并 dev2 分支的,那么正常环境下我们切回 master 分支直接归并即可,但如许其实是有肯定风险的
缘故原由:在归并分支时大概会有辩论,而代码辩论须要我们手动办理(在 master上办理)

  • 我们无法包管对于辩论问题可以精确地一次性办理掉,因为在现实的项目中,代码辩论不但一两行那么简朴,有大概几十上百行,以致更多,办理的过程中不免手误堕落,导致错误的代码被归并到 master 上。
此时的状态为:

办理这个问题的一个好的发起就是:最幸亏自己的分支上归并下 master ,再让 master 去归并dev ,如许做的目的是有辩论可以在当地分支办理并举行测试,而不影响 master
此时的状态为:


对应的实操演示如下,要分析的是,以下演示的merge利用,没有使用 --no-ff ,但上述的图示是禁用 Fast forward 了模式后得出的,重要是为了方便表明问题。
  1. # dev 合并 master
  2. lighthouse@VM-8-10-ubuntu:gitcode$ git branch
  3. * dev2
  4.   master
  5. lighthouse@VM-8-10-ubuntu:gitcode$ git merge master
  6. Auto-merging book
  7. CONFLICT (content): Merge conflict in book
  8. Automatic merge failed; fix conflicts and then commit the result.
  9. # 发送冲突
  10. lighthouse@VM-8-10-ubuntu:gitcode$ cat book
  11. Hello Island1314
  12. Hello World
  13. hello version1
  14. hello version2
  15. hello version3
  16. write bbb for new branch
  17. <<<<<<< HEAD
  18. a,b,c,d
  19. I am coding... Done
  20. =======
  21. a,b,c,d,e
  22. >>>>>>> master
  23. # 解决冲突并重新提交
  24. lighthouse@VM-8-10-ubuntu:gitcode$ vim book
  25. lighthouse@VM-8-10-ubuntu:gitcode$ cat book
  26. Hello Island1314
  27. Hello World
  28. hello version1
  29. hello version2
  30. hello version3
  31. write bbb for new branch
  32. a,b,c,d,e
  33. I am coding... Done
  34. lighthouse@VM-8-10-ubuntu:gitcode$ git add .
  35. lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "merge master"
  36. [dev2 9e77002] merge master
  37. lighthouse@VM-8-10-ubuntu:gitcode$ git status
  38. On branch dev2
  39. nothing to commit, working tree clean
  40. # 切回 master
  41. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
  42. Switched to branch 'master'
  43. # master 合并 dev2  -- 无需解决冲突
  44. lighthouse@VM-8-10-ubuntu:gitcode$ git merge dev2
  45. Updating adbb267..9e77002
  46. Fast-forward
  47. book | 1 +
  48. 1 file changed, 1 insertion(+)
  49. lighthouse@VM-8-10-ubuntu:gitcode$ git status
  50. On branch master
  51. nothing to commit, working tree clean
  52. # 删除 dev2 分支
  53. lighthouse@VM-8-10-ubuntu:gitcode$ git branch -d dev2
  54. Deleted branch dev2 (was 9e77002).
  55. lighthouse@VM-8-10-ubuntu:gitcode$ cat book
  56. Hello Island1314
  57. Hello World
  58. hello version1
  59. hello version2
  60. hello version3
  61. write bbb for new branch
  62. a,b,c,d,e
  63. I am coding... Done
复制代码
二、逼迫删除分支

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

  • 添加一个新功能时,你肯定不渴望因为一些实验性子的代码,把主分支搞乱了,以是,每添加一个新功能,最好新建一个分支,我们可以将其称之为 feature 分支,在上面开辟,完成后,归并,末了,删除该 feature 分支。
  • 但是,假如我们本日正在某个 feature 分支上开辟了一半,被产物司理突然叫停,说是要制止新功能的开辟。固然白干了,但是这个 feature 分支照旧必须就地销毁,留着无用了。
  • 这时使用传统的 git branch -d 下令删除分支的方法是不可的。
演示如下:
  1. # 新增并切换到 dev3 分支
  2. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout -b dev3
  3. Switched to a new branch 'dev3'
  4. lighthouse@VM-8-10-ubuntu:gitcode$ clear
  5. # 开始开发新功能并提交
  6. lighthouse@VM-8-10-ubuntu:gitcode$ vim book
  7. lighthouse@VM-8-10-ubuntu:gitcode$ cat book
  8. Hello Island1314
  9. Hello World
  10. hello version1
  11. hello version2
  12. hello version3
  13. write bbb for new branch
  14. a,b,c,d,e
  15. I am coding... Done
  16. I am writing new features ...
  17. lighthouse@VM-8-10-ubuntu:gitcode$ git add .
  18. lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "modify book for new features"
  19. [dev3 fb6a737] modify book for new features
  20. 1 file changed, 1 insertion(+)
  21. # 此时新功能叫停, 切回 master 准备删除 dev3
  22. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
  23. Switched to branch 'master'
复制代码
对 dev3 举行删除,如下:
  1. # 常规删除 dev3 分支时失败
  2. lighthouse@VM-8-10-ubuntu:gitcode$ git branch -d dev3
  3. error: The branch 'dev3' is not fully merged.
  4. If you are sure you want to delete it, run 'git branch -D dev3'.
  5. # 按照提示进行删除
  6. lighthouse@VM-8-10-ubuntu:gitcode$ git branch -D dev3
  7. Deleted branch dev3 (was fb6a737).
复制代码
三、分支的作用

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

  • 假设你预备开辟一个新功能,但是须要两周才气完成,第一周你写了50%的代码,假如立刻提交,由于代码还没写完,不完备的代码库会导致别人不能干活了。
  • 假如等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
  • 如今有了分支,就不消怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开辟完毕后,再一次性归并到原来的分支上,如许,既安全,又不影响别人工作。
而且 Git 无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件照旧1万个文件
四、细节增补

1. 未提交修改时(未commit)

当我们在 dev 分支下修改文件之后,master 照旧可以看到的(没有 add 的环境下),如下:
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout dev
  2. Switched to branch 'dev'
  3. lighthouse@VM-8-10-ubuntu:gitcode$ vim file
  4. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
  5. Switched to branch 'master'
  6. lighthouse@VM-8-10-ubuntu:gitcode$ cat file
  7. i miss you # master 分支
  8. I Miss You # dev 分支
  9. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout dev
  10. Switched to branch 'dev'
  11. lighthouse@VM-8-10-ubuntu:gitcode$ git add file
  12. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
  13. A        file
  14. Switched to branch 'master'
  15. lighthouse@VM-8-10-ubuntu:gitcode$ cat file
  16. i miss you # master 分支
  17. I Miss You # dev 分支
复制代码

  • 工作目次是共享的:全部未提交的改动(包罗未 add 的修改和已 add 但未 commit 的暂存)都存在于工作目次中,不会被 Git 自动隔离到特定分支
  • 切换分支时的举动

    • 假如目的分支(如 master)和当前分支(如 dev)对同一文件的修改不辩论,Git 答应直接切换,并生存工作目次的改动。
    • 因此,在未提交的环境下,无论切换到哪个分支,看到的都是工作目次中的当前内容(即未提交的修改)

2. 已提交修改后

而当我们在 切换到 dev 分支举行 commit 之后,然后再切换到 master 分支检察,然后 如下:
  1. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout dev
  2. A        file
  3. Switched to branch 'dev'
  4. lighthouse@VM-8-10-ubuntu:gitcode$ git commit file
  5. Aborting commit due to empty commit message.
  6. lighthouse@VM-8-10-ubuntu:gitcode$ git commit -m "改变" file
  7. [dev 1a1993f] 改变
  8. 1 file changed, 2 insertions(+)
  9. create mode 100644 file
复制代码

  • 提交 (commit) 的作用:将暂存区的内容永世记载到当前分支的历史中,此时修改正式归属于 dev 分支。
  • 切换分支时的举动

    • Git 会严酷根据目的分支(如 master)的最新提交重建工作目次
    • 假如 master 分支从未包罗 file 文件(即该文件只在 dev 分支提交过,下面等下会细说这个问题),切换到 master 时,Git 会删除工作目次中的 file 文件,因为 master 分支的历史中不存在它

总结

  • 提交后,数据已生存在 dev 分支的历史中,不会丢失。
  • master 分支的工作区被重建为它自己的最新提交状态,因此看不到 dev 分支的改动。
这里要说一下,由于我们在 master 分支下没有 commit 过文件,因此当我们在 dev下初次 commit,那么 master 分支下的 file 文件就会消散,如下:
  1. lighthouse@VM-8-10-ubuntu:gitcode$ cat file
  2. i miss you # master 分支
  3. I Miss You # dev 分支
  4. lighthouse@VM-8-10-ubuntu:gitcode$ git checkout master
  5. Switched to branch 'master'
  6. lighthouse@VM-8-10-ubuntu:gitcode$ cat file
  7. cat: file: No such file or directory
  8. lighthouse@VM-8-10-ubuntu:gitcode$ ll
  9. total 20
  10. drwxrwxr-x 4 lighthouse lighthouse 4096 Apr 18 19:52 ./
  11. drwxrwxr-x 7 lighthouse lighthouse 4096 Apr 15 21:47 ../
  12. -rw-rw-r-- 1 lighthouse lighthouse  129 Apr  8 23:05 book
  13. drwxrwxr-x 8 lighthouse lighthouse 4096 Apr 18 19:52 .git/
  14. 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 add 和 commit 明确添加到分支历史中。


  • 未提交的修改:属于工作目次,切换分支时大概生存(除非辩论)。
  • 已提交的修改:属于特定分支的历史,切换分支时 Git 会严酷重建工作目次以匹配目的分支
这就是为什么在提交后切换到 master 时文件“消散”的缘故原由——Git 严酷依照分支的历史记载管理文件
4.  重新明白 工作区、暂存区、版本


  • 工作区(Working Directory)

    • 全部门支共享同一个物理工作目次,未提交的修改(无论是否 add)都存在于工作区中,不直接绑定到任何分支
    • 工作区的内容会根据当前分支的最新提交动态厘革

  • 暂存区(Staging Area):同样全局共享,git add 后的内容属于暂存区,与分支无关。
  • 版本库(Repository)

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

但是看到这里,也许各人也会有点问题,就是当 commit 之后,那么产生的文件在两个分支下不就内容不一样了吗,此时它两也能算得上全局共享嘛???
表明如下
假设有一个文件 file.txt,初始状态如下:
步调 1:在 master 分支创建文件并提交
  1. git checkout master
  2. echo "Hello from master" > file.txt
  3. git add file.txt
  4. git commit -m "Add file in master"
复制代码
此时:

  • master 分支的提交历史包罗 file.txt。
  • 工作区中的 file.txt 内容是 Hello from master。
步调 2:创建 dev 分支并修改文件
  1. git checkout -b dev
  2. echo "Hello from dev" > file.txt
  3. git add file.txt
  4. git commit -m "Update file in dev"
复制代码
此时:

  • dev 分支的提交历史包罗修改后的 file.txt(内容是 Hello from dev)。
  • master 分支的提交历史仍为旧版本(内容是 Hello from master)。
步调 3:切换回 master 分支检察文件
  1. git checkout master
  2. cat file.txt
  3. Hello from master
复制代码
关键征象表明


  • 为什么切换分支后文件内容变了?

    • Git 会根据目的分支的最新提交重建工作区
    • master 分支的最新提交是原始版本,而 dev 分支的最新提交是修改后的版本。

  • 工作区是“共享”的吗?

    • 物理上共享:全部门支利用同一块磁盘区域。
    • 逻辑上隔离:切换分支时,Git 会覆盖工作区内容,使其匹配目的分支的提交。
    • 你可以明白为:工作区是“共享的舞台”,但每次切换分支时,Git 会更换舞台上的“背景”

  • 提交后的文件到底属于谁?

    • 提交后的内容属于分支的历史记载,不直接绑定到工作区。
    • dev 分支的提交历史中有一个新版本的 file.txt,而 master 分支的提交历史中照旧旧版本。


全局共享 vs 分支独立

区域是否全局共享?是否受分支切换影响?工作区✅ 是(全部门支共享同一物理目次)✅ 是(切换分支时内容会被覆盖)暂存区✅ 是✅ 是(切换分支时大概被覆盖)版本库(提交)❌ 否(每个分支有独立提交历史)❌ 否(提交历史永世绑定到分支)
疑问办理


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

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


总结


  • 工作区共享:全部门支利用同一块磁盘区域,但内容由当前分支的提交历史决定。
  • 提交隔离:差别分支的提交历史独立,切换分支时 Git 会严酷按目的分支的历史重建工作区。
  • 看似抵牾的征象:工作区是共享的,但提交后的文件在差别分支下内容差别,这正是 Git 分支机制的核心筹划——通过动态覆盖工作区内容,实现高效的多分支协作
五、git rebase(交互式变基)

🔧 表明:对整个 Git 项目的历史提交(从最开始的第一个提交)举行 交互式变基(interactive rebase)
  1. git rebase -i --root
复制代码
📌 各部门寄义:
下令片段寄义分析git rebase变基利用:把一些提交“重新应用”到另一个提交之上,常用于整理提交历史。-i或--interactive进入交互模式,会弹出编辑器让你选择要对这些提交做什么(比如修改、归并、删除等)。--root从项目的第一个提交开始变基,而不是从某个中心点开始。通常rebase -i是不能选根提交的,这个参数逼迫让它可以包罗最早的那个提交。✅ 使用场景举例:
你想对整个 Git 提交历史做一次大整理,例如:

  • 删除某些错误的早期提交;
  • 归并多个早期提交为一个;
  • 修改最早的提交信息;
  • 重新排序提交次序;
  • 以致完全重写整个提交历史。
⚠️ 注意事项:

  • 非常伤害的利用!

    • 因为它会影响整个项目的提交历史。
    • 假如你已经将代码推送到远程堆栈,而且别人基于你的提交做过开辟,如许做会引起杂乱。

  • 使用前请务必备份分支或 commit hash ,以防误利用后能规复。
  • 实行之后,当地的提交历史会被改写,假如要推送到远程须要加 -f 逼迫推送:
    1. git push -f origin main
    复制代码
💡 示例流程
  1. git rebase -i --root
复制代码
实行后会打开编辑器,表现全部提交记载(从最早的一个开始),像如许:
  1. pick abc1234 First commit message
  2. pick def5678 Second commit message
  3. ...
复制代码
你可以将 pick 改成:

  • edit(e):进入提交后停息,可以修改提交内容;
  • squash(s):归并到上一个提交;
  • drop(d):删除该提交;
  • reword(r):修改提交信息;
  • 等等…
生存退出后 Git 会逐个处理处罚这些利用。
🔄 小结
利用目的git rebase -i --root

重新开始整理整个 Git 提交历史安全性⚠️ 高风险利用,慎用保举用途整理历史、讲授演示、重构项目


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表