返回介绍

分支的意义与管理

发布于 2024-12-09 12:49:34 字数 6236 浏览 0 评论 0 收藏 0

创建分支可以避免提交代码后对主分支的影响,同时也使我们有了相对独立的开发环境,分支在日常开发中具有很重要的意义。

# 新建一个分支,但依然停留在当前分支
git branch [branch-name]

# 新建一个分支,指向指定 commit
git branch [branch] [commit]

# 切换到指定分支,并更新工作区
git checkout [branch-name]

# 切换到上一个分支
git checkout -

# 新建一个分支,与指定的远程分支建立追踪关系
git branch --track [branch] [remote-branch]

# 建立追踪关系,在现有分支与指定的远程分支之间
git branch --set-upstream [branch] [remote-branch]

# 合并指定分支到当前分支,如果有冲突需要手动合并冲突,然后 add、commit 再提交
git merge [branch]

# 选择一个 commit,合并到当前分支
git cherry-pick [commit]

# 删除分支
git branch -d [branch-name]

# 强制删除分支
git branch -D [branch-name]

# 删除远程分支
git push origin --delete [branch-name]
git branch -dr [remote/branch]

# 在需要删除的分支前面加一个冒号就可以了,push 上去之后,服务器上的分支自然就被删除了
git push origin :branch_name

创建并切换到新建的分支:

git checkout -b 分支名

查看本地分支,即查看本地创建了哪些分支:

git branch

# 列出所有远程分支
git branch -r

查看本地+远程分支

git branch -va
# 列出所有本地分支和远程分支
git branch -a
  • 切换到远程分支
git checkout remotes/origin/branch_name
// 新建并切换到该分支
git checkout -b branch_name
# -b 的意思是 base,就是以当前分支为 base,新建一个分支

# 或者直接执行
git checkout -t origin/branch_name

变基-rebase

在 Git 中整合来自不同分支的修改主要有两种方法: merge 和 rebase 。步骤:

# 1. 假设当前在 dev 分支上,将 master 分支上的更新同步到当前分支
git rebase master

# 2. 切换回 master 分支
git checkout master

# 3. 最后把 dev 分支的最新代码 merge 到 master 分支上
git merge dev

第三步是最重要的,git 此时会自动 merge master 分支和当前分支 dev 。如果自动 merge 成功,就不需要再管了;如果自动 merge 失败,此时 git status 查看哪个文件 merge 失败,打开该文件,手动修改文件中冲突的地方,执行 git add . 命令去更新相应内容的索引,然后,不需要执行 git commit 命令,只要执行 git rebase --continue ,git 会继续应用(apply) 余下的补丁。

需要注意的是:可以在任何时候,使用 git rebase --abort 命令来终止 rebase 的行动,并且当前分支会回到 rebase 开始前的状态。

变基的基本操作

从上图可以看出,开发任务分叉到两个不同分支,又各自提交了更新。

我们知道,整合分支最容易的方法是 git merge 命令,该命令会把两个分支的最新快照(C3 和 C4) 以及两者最近的共同祖先(C2) 进行三方合并,合并的结果是生成一个新的快照(C5) 并提交。如上图所示:通过合并操作来整合分叉了的历史。

除了 git merge 之外,整合分支还有一种方法:我们可以提取在 C4 中引入的补丁和修改,然后在 C3 的基础上再应用一次。在 Git 中,这种操作就叫做变基。我们可以使用 rebase 命令将提交到某一分支上的所有修改都移至另一个分支上,就好像"重新播放"一样。

git checkout experiment
git rebase master

这一操作的原理是:首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master) 的最近共同祖先 C2,然后 对比当前分支 experiment 相对于该祖先的历次提交 ,提取相应的修改并存为临时文件,然后将当前分支指向目标基底 C3,最后将之前另存为临时文件的修改依序应用。如上图所示:将 C4 中的修改变基到 C3 上。

# 现在切换会 master 分支,进行一次快进合并
git checkout master
git merge experiment

这时候, C4' 指向的快照就和上面使用 git merge 命令的例子中 C5 指向的快照一模一样了。这两种整合方法的最终结果没有任何区别,但是变基使得提交历史更加整洁。我们在查看一个经过变基础的分支的历史记录时会发现,尽管实际的开发工作是并行的,但是它们看上去就像是先后串行的一样,提交历史是一条直线没有分叉。

特别注意: 无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。变基是将一系列提交按照 原有次序 依次应用到另一分支上,而合并是把最终结果合在一起。

rebase demo

在和远程分支同步后,对 demo.js 这个文件做了两次提交。用 git log 命令查看:

git log --graph --pretty=oneline --abbrev-commit

结果如下:

如上图所示:Git 用( HEAD -> master ) 和( origin/master ) 分别标识出当前分支的 HEAD 和远程 origin 的位置分别是 1e23035 test modify 23c696d0 test ,本地分支比远程分支快了两个提交。


现在我们尝试推送本地分支,很不幸,失败了,这说明有人先于我们推送了远程分支,我们需要先 git pull 一下。再用 git status 看看状态,加上刚才合并的提交,现在我们本地分支比远程分支超前 3 个提交。

git log 看看当前的提交历史:发现提交历史分叉了。

使用 git rebase 命令解决提交历史分叉问题:

➜  git_learn git:(master) git rebase
First, rewinding head to replay your work on top of it...
Applying: test modify 1
Applying: test modify 2

重新使用 git log 命令查看:

git log --graph --pretty=oneline --abbrev-commit

原本分叉的提交现在变成一条直线了!这种神奇的操作是怎么实现的?其实原理非常简单。我们注意观察,发现 Git 把我们本地的提交'挪动'了位置,放到了 fe1a412 (origin/master, origin/HEAD) Update README.md 之后,这样,整个提交历史就成了一条直线。rebase 操作前后,最终的提交内容是一致的,但是,我们本地的 commit 修改内容已经变化了,它们的修改不再基于 3c696d0 test ,而是基于 fe1a412 (origin/master, origin/HEAD) Update README.md ,但最后的提交 6ab73f9 (HEAD -> master) test modify 2 内容是一致的。

rebase 操作的特点:把分叉的提交历史'整理'成一条直线,看上去更直观。缺点是:本地的分叉提交已经被修改过了(之前本地提交的 commitId 发生了变化,但是内容不变)。

最后,通过 push 操作把本地分支推送到远程:

重新使用 git log 命令查看,远程分支的提交历史也是一条直线:

git pull 和 git pull --rebase 的区别使用

两者的区别可以用如下的等式来做解释:

git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文