可以说,任何一个真实的项目的源代码管理,都会用到“分支”这个概念。我们可以把分支理解成是并行的时间线,在这些时间线上,有它们各自的行为,彼此不互相影响。为了演示这个概念,我新建了一个Vapor项目git-learning,完成后,Vapor会自动为我们创建一个git repository。

在图中可以看到,git在创建仓库的时候,就默认创建了一个分支,叫做master。通常,这个分支上的代码都是经过严格测试,准备对外发布的。我们很少直接在这个分支上开发新功能以及修改Bug。

为什么需要一个分支呢?

为什么呢?

来看个例子。假设只有一个master分支,在routes.swift中,我们用demo来模拟一个正在开发中的功能:

public func routes(_ router: Router) throws {
    router.get("hello") { req in
        return "Hello, world!"
    }

    router.post("deom") { req in
        return "Some complicated features"
    }
}

完成后,我们就执行git add .git commit -m "Finish the demo"把它提交到了master上。并且,谁也没有发现上面代码中的这个typo。

然后,我们很快就开始投入新的工作了,再添加一个新的路由:

public func routes(_ router: Router) throws {
    // Basic "Hello, world!" example
    router.get("hello") { req in
        return "Hello, world!"
    }

    router.post("deom") { req in
        return "Some complicated features."
    }

    router.get("about") { req in
        return "About us"
    }
}

这时,有人反馈说demo这个API遇到无法访问啊,需要立即修复,该怎么办呢?如果about还没有完成,显然我们不应该提交和它相关的任何代码。但我们修复了bug之后执行git add的时候,这些代码是肯定会包含进来的,这样就很尴尬了。除非我们把手头正在开发的代码全部剪切出来存在别的地方,但这只是一个理论上可行的方案罢了,对于一个真实的项目来说,你不可能会做这样的事情。

而这,就是需要分支的理由。我们需要一个并行于master分支的新分支。所有的开发工作都在这个新分支上进行。

使用分支来解Bug和开发需求

对于我们上面说到的这种情况,先执行下git status就会看到下面的提示:

我们可以执行:

git checkout -- Sources/App/routes.swift

撤销掉master分支上,在最后一次提交之后的所有修改。当然,这也是没办法的事情,谁让我们之前做错了事情呢 :)

创建分支

接下来,为了创建一个分支来开发我们的about API,我们可以执行:

git branch feature-about
git checkout feature-about

其中:

  • git branch用于创建一个新的分支。分支的名称,通常都应该反应这个分支的用途。例如,我们在开发功能,因此叫做feature-about。如果是修改Bug,则应该是类似bug-id,如果是Github上的issue,则应该是issue-id等;
  • git checkout feature-about则是从master分支切换到feature-about分支。这时,从Shell提示符就会看到我们已经切换了当前分支:

实际上,之前创建并切换分支我们也可以执行git checkout -b feature-about

在这个分支里的所有操作,就不会影响master了。现在,我们把之前的about代码再添加进来:

public func routes(_ router: Router) throws {
    /// ...

    router.get("about") { req in
        return "About us"
    }
}

然后执行:

git add .
git commit -m "Finish about api"

about的实现就被提交到了feature-about这个分支上。执行git log,就会看到下面这样的结果:

也就是说,在feature-about这条时间线上,比master领先了一个提交。接下来,执行git checkout master,回到master分支,我们该处理之前的BUG了。理论上说,我们也应该创建一个分支来修改BUG。不过,对于typo这种无害的BUG,这里简单起见,我们就在master上修改就好了。还是之前那句话,规则固然应该遵守,但也不是绝对不能打破,重要的是,你要知道自己在干什么就好了。

完成修改之后,执行下面的命令更新master分支:

git add .
git commit -m "Fix typo"

现在,执行一下git log看下提交日志,就会发现,这里只有关于demo的记录,而没有任何about功能的信息:

这正是我们期望的结果,现在master和feature-about是两个平行的时间线。

合并分支

现在,假设feature-about上的代码已经通过测试准备发布了,我们自然要把它合并进master分支上。为此:

  • 我们要先确保自己在master分支上,这一步这很重要;
  • 其次,执行git merge feature-about。这时,git就会打开默认编辑器,让我们对这次合并做一个说明。默认的说明就是Merge branch branch_name。通常,我们也不会修改它,直接保存退出,合并就完成了;

这时,重新执行下git log,就会发现之前这两条时间线上的行为,以发生时间为序合并在了一起:

删除分支

现在,feature-about分支也就没有存在的意义了。我们可以执行git branch -d feature-about把它删掉就好了。

What's next?

以上,就是和分支有关的基本工作流。掌握了分支的用法之后,下一节我们讨论一个场景,现实工作中,当然不会总是像我们刚介绍的这样一帆风顺。如果不同分支里存在对同一个文件的同一个位置进行的修改,我们merge的时候,到底该听谁的呢?

所有订阅均支持 12 期免息分期

¥ 59

按月订阅

一个月,观看并下载所有视频内容。初来泊学,这可能是个最好的开始。

开始订阅

¥ 512

按年订阅

一年的时间,让我们一起疯狂地狩猎知识吧。比按月订阅优惠 28%

开始订阅

¥ 1280

泊学终身会员

永久观看和下载所有泊学网站视频,并赠送 100 元商店优惠券。

我要加入
如需帮助,欢迎通过以下方式联系我们