Git 中的分支


你正在开发 weather-app 的过程中,想尝试添加一个五天天气预报功能。可能需要多个提交才能完善它,在完成之前,你不希望半成品代码与那个已经可用的应用混在一起。分支就是 Git 解决这个问题的方式:一条独立的工作线,实验代码在这里进行,而 main 则保持原来的状态。
分支实际上是什么
这是它的实际运用:
$ git branch forecast
$ git switch forecast
Switched to branch 'forecast'两个命令:第一个创建了一个叫 forecast 的新分支,第二个将你移到这个分支上。从此以后,你在 forecast 上的每一个提交都会在这个分支上,而 main 始终保持原样。
一个**分支**是指向一个提交的可移动标签。现在,main 和 forecast 都指向同一个提交,即你运行 git branch forecast 时所在的那个提交。当你在 forecast 上再次提交时,这个标签会移向新提交。main 会保持原位,直到你切换到它并在那里提交。
你可以用 git branch 看到两个标签:
$ git branch
forecast
* main星号标记的是你当前所在的分支。一个分支只是指向一个提交的名称。这就是整个机制。本章其他内容都是围绕如何移动这些标签展开的。
git branch forecast 创建一个新标签指向你的当前提交,git switch forecast 将你移到它上面。直到你真正在那里提交,你的文件不会有任何变化。我喜欢把分支想象成贴在提交上的便签:便宜到可以随意添加,便宜到可以随意移动,便宜到完成后可以随意撕掉。 创建和切换分支
单独使用 git branch forecast 会创建标签,但不会将你移到那里。大多数时候你想同时做这两件事,所以 git switch 有一个快捷方式:
$ git switch -c forecast
Switched to a new branch 'forecast'-c 代表"create"(创建)。git switch -c 既创建分支又将你移到那里。这个单一命令是你几乎每次开始新工作时都会用到的。
切换分支会改变你的文件所显示的快照。试试看:下面的 echo 行是创建一个新文件 src/forecast.js 的一步方法,其中只有一行,其他的都是你已经知道的命令:
$ git switch forecast
$ echo "// five-day forecast logic" > src/forecast.js
$ git add src/forecast.js
$ git commit -m "Start forecast module"
$ ls src
forecast.js index.js
$ git switch main
Switched to branch 'main'
$ ls src
index.js这个文件并没有消失。它存在于 forecast 分支上,而 main 分支的快照从未包含过它。切换回 forecast,它会精确地按照你留下的样子重新出现。
git switch -c forecast 在一步中创建分支并将你移到它上面,这是你几乎每次都会用到的。切换分支会交换你看到的文件版本,所以在一个分支上添加的文件在另一个分支上是不存在的,直到你切换回来。没有什么丢失,它只是停在另一个分支上。 HEAD 和分离的 HEAD
Git 用一个叫做 HEAD 的标记来跟踪你当前的位置。通常 HEAD 指向你的当前分支,而该分支指向一个提交,所以每次你切换或提交时 HEAD 会自动向前移动。如果你通过提交的哈希值检出一个具体的提交,或者检出一个标签(固定在一个提交上的标签,通常标记发布版本),而不是分支名称,HEAD 会直接附加到那个提交上,而不是附加到分支标签。这个状态叫做分离 HEAD。
你可以在那里自由地查看,甚至可以提交,但没有名称指向那些新提交。如果你没有先创建分支就切换到一个分支,它们会变得很难找到。
$ git switch a1b2c3d
HEAD is now at a1b2c3d Add password strength meter那条消息"HEAD is now at"告诉你已经离开了分支领地,并将 HEAD 附加到一个单一的提交。
这通向何处
你现在已经创建了分支,在它们之间移动,并看到了当你在其他地方进行实验时 main 如何保持不动。下一个问题是分支上的工作如何回到 main,这正是合并和冲突要涵盖的内容。如果你想在继续之前复习一下阅读提交历史,历史讲解了 git log、git show 和 git diff。

