通常,你想尝试一些新想法,或开发一些新功能,而不是干扰主分支。这就是主题分支的用武之地。你可以轻松地在分支之间来回切换,这样你就不需要通过一次大的“怪物”提交来贡献新功能。
如果你想尝试一些可能行不通的事情,并且你不想让任何人知道这种情况,你可以将主题分支保留在本地。
#创建主题分支
您可以从任意起点创建主题分支,如下所示:
$ git checkout -b new-branch branch-point
参数 branch-point 可以是任何提交或标签。如果你想从当前 HEAD 分支,则根本不需要提交参数:
$ git checkout -b topic1
注意:如果您想从远程(默认跟踪)分支启动新分支,此命令发送设置默认合并为来自该远程分支与该分支:
$ git checkout -b fake2 origin/fake2
...
$ git pull
分支分支 fake2 从 origin 拉入当前 (fake2) 分支。
分支间切换
要从当前分支切换到另一个分支,首先确保您已提交(或隐藏)所有内容,然后调用
$ git checkout 其他分支
这将切换到另一个分支(现在成为您的 HEAD),并更新工作目录。注意:只有跟踪的文件才会更新;未跟踪的文件将保持不变。
择优提交
如果您希望在当前分支中拥有另一个分支上的单个提交,请使用
$ gitcherry-pick 其他分支~2
在此示例中,引用了其他分支提示的倒数第三次提交(第二顺序祖先)。
如果您修复主题分支中的某些内容也需要在主分支中进行修复,那么择优挑选即可派上使用场:
# current branch: topic234
... fix bug ...
# git commit -s <file>
$ git checkout main
$ git cherry-pick topic234
$ git checkout topic234
在此示例中,修复错误并提交错误修复后,您切换到分支 main,选择分支 topic234 上的最新提交,然后切换回分支 topic234。
解决冲突
注意:当轮询提交时,可能会出现冲突。它们标记有冲突标记(“«<”…“===”…»»”)。
您必须编辑文件,选择想要的更改(第一部分是您当前分支中的版本,部分是预选的提交想要导入的内容)。有关如何解决合并冲突的第二详细信息,请参阅Git Conflicts。
编辑文件后,将它们暂存在以进行提交和提交,使用
$ git add <file>...
$ git commit
如果cherry-pick/rebase失败,这将为您带来合适的提交消息。
合并/变基主题分支
如果您完成了一个主题,并且想要更改分支分支 main,只需切换到该分支并合并主题分支:
$ git checkout main
$ git merge topic234
与cherry-pick一样,混音可能会造成冲突和失败。详情请参阅Resolving conflicts。
您可能不想合并,但是希望在当前主分支的基础上重新建立主题分支。要了解合并和变基之间的区别,请考虑以下历史记录(左边比右边更旧):
- A - B - C - D - main
\
E - F - G - topic234
合并后:
- A - B - C - D - main^ - main
\ /
E - F - G - topic234
变基后:
- A - B - C - D - 主要 - E’ - F’ - G’ - topic234
那么,topic234 中的所有提交都被重写,就要求它们在 main 分支的当前提示之上创建的一样。
如您所见,分支 topic234 被重写,并且与 topic234 分支的前一个提示没有共享任何有趣的历史记录。(您可以通过 topic234@{1} 访问前一个提示,请参阅Git_reflogs。)
因此,要通过变基将您的主题分支合并到 main 分支中,您需要执行以下操作:
# current branch is topic234
$ git rebase main
$ git checkout main
# this will fast-forward, i.e. not create a merge commit, but just move main's tip to topic234's tip.
$ git merge topic234
通常情况下,合并应该优先于变基,因为合并可以更好地显示历史记录:变基之后,分支的尖端基本上没有测试,因为您只在变基之前测试了提交。
然而,变基有时会非常方便,特别是如果您想重写提交历史记录,如下所述。
高级主题分支编辑(又名药物变基)
通常,主题分支会成为良好提交和修复提交的集合,也许还有一些需要的提交。在这种情况下,您可能需要稍微清理一下提交历史记录。这就是“交互式”变基的用武之地。
考虑一下这样的历史(第一个“单词”是缩写的提交名称):
0470894... Untrack generated files
e0acf90... Add Fake, a specialized yet simple substitute for 'make'
047ad28... Fake: implement up-to-date test and use it in make()
deadbee... fixup! Add Fake, a specialized yet simple substitute for 'make'
其中0470894是main分支的尖端,而deadbee修复了提交e0acf90中的一些严重问题,这些问题不应该按原样提交。
Note that the *fixup!* commit can be made easily by calling `git commit --fixup <commit-to-fixup>`.
To reorder the commits and merge the two commits (*squash* in Git terminology, as *merge* already means to merge branches), call
$ git rebase -i –autosquash main
这将启动一个编辑器,其中包含要在 main 之上应用的提交列表:
pick e0acf90 Add Fake, a specialized yet simple substitute for 'make'
fixup deadbee fixup! Add Fake, a specialized yet simple substitute for 'make'
pick 047ad28 Fake: implement up-to-date test and use it in make()
请注意,autosquash 模式解释了修复提交的特殊提交消息,移动了最后一行放置命令“pick”(如“cherry-pick”中的)替换为“fixup”。
保存并退出编辑器。将启动变基并使用修复提交修改第一个提交。
Note: If you want to default to the *autosquash* mode, you can tell Git so: `git config --global rebase.autosquash true` (you only need to do this once).
Note: as with cherry-picking and merging, conflicts can arise. You will [have to resolve them](/develop/git/conflicts), `git add` the resolved files, but you do not need to commit; calling
$ git rebase –继续
将接受更改,应用正确的提交作者和消息,并启动编辑器提供您验证内容。和以前一样,保存并退出,rebase 将继续。
中止交互式变基
Sometimes you realize by the sheer size of the list of commits that you made a mistake, and do not want to rebase after all. As with `git commit`, just delete the *complete* list, and the interactive rebase will be aborted.
Even at later stages, e.g. when you have a huge conflict and would prefer to go back and merge instead of rebase, you can abort the rebase. Just call
$ git rebase --abort
Git 将您带回到开始变基之前的位置。
Reflog 和 rebase
变基将在分离的 HEAD 上工作。既然,rebase 进行时,不会更新任何分支,而是会增长一个临时分支,只有当rebase 成功完成后,才会更新当前的分支。
这意味着您可以通过 branch-name@{1} 引用变基之前的状态(参见Git_reflogs)。
注意:对于 HEAD@{1} 来说情况并非如此:“HEAD”的引用日志遵循存储库中当前某个阶段的每个单独修订。