`

理解Git工作流

git 
阅读更多

如果你不了解Git背后的设计初衷,那么你正处在危险境地,当然有很多参数可以强迫Git按照你的意愿行事,但这并不是Git被设计的工作方式,这就好比你可以把改锥当锤子使用,并且它也可以完成工作,但这对改锥没什么好处。

下面就让我们来看一个最常见的Git工作流是如何变得没法收拾的。

首先从Master创建一个新分支,在这个分支上完成你的工作,然后将它合并回Master分支。

大多数情况下这不会有什么问题,你都会得到你预期的结果,这是因为在你创建新分支之后,Master的代码已经发生了变化。但是有一天,你合并了一个新特性到Master,不过这次Master的代码并没有发生变化,所以同以往不同,这次Git直接将Master指向了你的特性分支上的最后一个Commit,也就是“fast forwards”(见图),而不是创建一个合并commit。

不幸的是,你的新特性分支可能会包含一些checkpoint commits,这些小的commit保证了你的工作不会意外丢失,但是也让你的代码进入了相对不稳定的状态,现在你已经无法从Master的稳定commit中区分这些不稳定的commit了,一旦需要回滚,你很容易就会陷入灾难之中。

当然你可以添加一条规则:“只要是合并新特性时,都必须使用-no-ff来强制生成一个新的commit。”这样问题就解决了,于是你继续往下走。

直到有一天你在Production发现了一个严重的bug,你需要追踪这个bug是何时被引入的,于是你试图通过bisect来找出答案,但却总是找到那些checkpoint commit,于是你放弃了,并开始手动检查。

最终你将Bug定位到了某个单独的文件上,你想通过blame来查看过去48小时这个文件发生的变化,但是你发现这是不可能的,因为blame报告这个文件已经有几个星期没人碰过了,事实证明blame报告的是你最初的commit,而不是合并时的,你的第一个checkpoint commit在几周之前改变了这个文件,但是这个改变直到今天才被合并进来。

-no-ff标识就这样神奇的破坏了bisect和blame,就像你将改锥当做锤子一样。

重新考虑版本控制

版本控制系统的出现是为了解决2个问题

第一个问题就是帮助你更好的编写代码,你需要同你的团队成员同步代码,并且备份你的工作,通过Email发送压缩文件明显不是个靠谱的办法。

第二个问题就是配置管理,这主要是针对并行开发的管理,比如你需要在开发下一个大版本的同时,继续修复当前production版本存在的bug,配置管理也可以用来查找变更,但是这对于诊断Bug用处不是很大。

通常来说,这两个目的是矛盾的。

当你为一个新特性开发原型时,你应该不断的添加checkpoint commit,尽管如此,这些commit通常会破坏测试。

在一个理想的世界中,你的版本历史中的每次变更都应该是简明并且稳定的,不应该有checkpoint commit这种东西来制造噪音,也不应该有巨无霸,比如10,000行代码的commit,干净的提交历史让你可以很容易的撤销变更,或是在分支之间使用cherry-pick,干净的提交历史也让后期的代码检查和分析变得更简单。尽管如此,维护一个干净的提交历史记录却意味着你需要等待一切都变得完美之后再进行提交。

那么我们应该选择哪种策略呢?经常性的提交,还是保证提交历史干净整洁?

如果你是在一个产品还未发布的2人创业公司工作,干净的提交历史对你带来的好处非常有限,你可以把所有的commit都扔到Master,并在任何你需要的时候进行部署。

然后随着变更的增加,以及团队规模或是你的用户基数的增长,你需要工具和技术来确保所有事情都是经过检查的,这通常包括自动化测试,代码检查,以及干净的提交历史。

特性分支看起来是个不错的选择,它们解决了最基本的并行开发问题,但是在你写代码的时候,你迟早会开始考虑最后的集成问题。

当你的项目变得足够大时,简单的分支/提交/合并策略就变得不再奏效了,作坊式的开发时代已经结束了,你需要一个干净的提交历史。

Git的革命性就在于它很好的同时解决了这2个问题,让你在分支上开发新特性时,可以随时提交你的任何变更,并且在随后合并时,你依然可以得到一个干净的提交历史,如果这是你想要的,那么你就应该遵从Git的默认设置。

Git工作流

考虑下这两种类型的分支:公共和私有

公共分支保存着这个项目的权威历史,在公共分支上,每个提交都应该是简明,原子的,并且提交信息应该准确表达变更,同事应该尽可能的保证提交是线性的,并且是永久的,公开的分支包含Master以及Release分支。

而私有分支是属于你自己的,它就相当于你解决问题时候用到的草纸。

将私有分支存在本地是最安全的,如果你需要在你的工作电话和家庭电脑之间同步,最好告诉你的同事你推送的是一个私有分支,以防止他们在这个分支上进行开发。

永远不要把你的私有分支直接合并到任何公共分支上,而应该先使用reset,rebase,squash merges或者commit amending这样的工具清理你的分支。

你可以把自己想象成一个作家,并且将每个commit看做是一本书的章节,作家不会发布第一版手稿,Michael Crichton说过,“好书不是写出来的——而是改出来的”。

如果你使用的是其它系统,你可能会觉得修改历史是不可能的,所有提交就像刻在了石头上一样,是不可改变的,按照这个逻辑,那我们就应该在文本编辑器中禁用撤销功能。

实用主义者一般会直到事情变得不可收拾之时才会注意到问题的存在,对于配置管理来说,我们关心的是全局的变更,checkpoint commit仅仅只是为了方便撤销而保存的缓冲而已。

如果你认为你的公共历史是干净的,那么fast-forward合并不仅很安全,而且很可取,他们保证版本历史是线性的并且非常容易追踪。

而-no-ff参数唯一的作用就是“文档”,有人或许会使用merge commit的消息来表示最后一次合并到production代码中的版本信息,但是这是不对的,你应该使用tag。

根据我修改的代码量,以及修改的时间跨度,还有这个分支偏离Master的程度,我设定了3中基本的工作流。

短期开发

大多数情况都是这样,我通过squash merge来完成清理工作。

假设我创建了一个特性分支,并在接下来的一个小时做了许多checkpoint 提交。

git checkout -b private_feature_branch
touch file1.txt
git add file1.txt
git commit -am “WIP”

在我完成我的工作之后,我会运行下面的命令来完成合并:

git checkout master
git merge –squash private_feature_branch
git commit -v

然后花上一分钟详细的写上这次变更的注释。

大改动

有时一个特性可能需要几天才能够完成,并且包含许多小的提交。

这时我认为我的改动将会被打碎成许多更小的改动,所以squash在这种情况下就拍不上用场了(作为我的一条经验法则,我会问自己”这样有利于代码检查吗?“)

如果我的checkpoint commit包含逻辑上的递增,我可以使用rebase的互动模式。

互动模式非常强大,你可以使用它来编辑老的commit,分割它们,重新排序,在某些情况下,你还可以压缩(squash)它们。

我会在特性分支上执行:

git rebase –interactive master

它会打开一个编辑器,每一行包含一个commit,有SHA1以及commit的message,并且每个commit后面还会跟随一个可以执行的命令列表。

默认情况,每个commit都使用‘pick’,这不会改变commit。

pick ccd6e62 Work on back button
pick 1c83feb Bug fixes
pick f9d0c33 Start work on toolbar

我将这个操作改成了squash,这就会将第二个commit压缩到第一个commit中。

pick ccd6e62 Work on back button
squash 1c83feb Bug fixes
pick f9d0c33 Start work on toolbar

当我保存并关闭之后,会出现一个新的文本编辑器提示我为这些合并后的commit填写一个commit message,然后一切就绪。

废弃旧分支

如果我的特性分支已经存在了太久时间,并且我需要合并几个分支到我的特性分支以保证它是最新的,这样事情就变得错综复杂了,这时你可以很容易的获取原始的diff并创建一个干净的新分支。

git checkout master
git checkout -b cleaned_up_branch
git merge –squash private_feature_branch
git reset

现在我就有了一个新的分支,既有最近的Master上的commit,又有我上一个分支上的工作,现在我可以手动添加并提交我的变更了。

总结

如果你没有遵从Git的默认设置,那么你应该问问自己为什么?

你应该保证公共历史是永久的,原子的,并且易于追踪,而将私有分支看做是临时的,可丢弃的。

因此,理想的工作流应该是:

  1. 从一个公开分支创建一个似有分支。
  2. 经常新的在似有分支上提交你的工作
  3. 一旦你的代码已经完美了,那么清除它的历史
  4. 合并干净的分支到你的公共分支

特别感谢@joshaber以及@jbarnette提供反馈。

————–
本文翻译自”Understanding the Git Workflow”,作者:Benjamin Sandofsky,翻译:@yuanyiz

 转自:http://heikezhi.com/2011/08/04/understanding-the-git-workflow/

分享到:
评论

相关推荐

    最新版深入学习Git工作流

    为了更深入理解Git工作流,可以通过Git命令参考手册快速查找和记忆常用的命令及其参数。此手册分为不同的章节,每个章节涵盖了特定操作类型的命令,并提供了深入阅读的链接,如官方使用手册或《ProGit》书籍的相关...

    Git工作流指南

    Git是世界上最受欢迎的分布式版本控制系统,它为团队协作和代码管理提供了强大的支持。Git工作流是一种组织和协调团队成员在Git上共同开发项目的...理解并熟练运用这些Git工作流,将极大地提高软件开发的效率和质量。

    深入理解学习Git工作流.pdf

    通过深入理解这些Git工作流,开发团队可以更好地管理代码版本、提高工作效率以及更顺畅地处理团队协作。对于新接触的开发者来说,可以按照Git工作流指南逐步上手,并通过实际操作来加深理解和应用。 PullRequest...

    深入理解学习Git工作流(git-workflow-tutorial)

    工作流其实不是一个初级主题,背后的本质问题其实是有效的项目流程管理和高效的开发协同...关于Git工作流主题,网上体系的中文资料不多,主要是零散的操作说明,希望这篇文章能让你更深入理解并在工作中灵活有效地使用

    31Git协同工作流,你该怎样选1

    【Git协同工作流详解】 Git作为一种强大的分布式版本控制系统,因其高效、灵活的特性深受开发者喜爱。在实际开发中,为了确保代码的一致性和协同...重要的是理解每种工作流的优缺点,根据实际情况做出最适合的选择。

    GIT标准工作流1

    Git标准工作流是一种高效、有序的协作模式,旨在保持代码库的整洁和版本管理的清晰。以下是关于Git标准工作流的详细说明: 1. 主分支Master:Master分支被视为代码库的核心,只包含稳定且经过验证的代码。它代表了...

    git 教材 progit

    8. **Git工作流**:了解Git的不同工作流模型,如GitFlow、Forking Workflow等,可以帮助你更好地适应团队协作的场景。 9. **Git图形化工具**:除了命令行工具,还有许多图形化工具如SourceTree、GitKraken等,它们...

    git-workflow:Git 工作流的示例项目

    本项目“git-workflow:Git 工作流的示例项目”显然是一个用来展示如何实施Git工作流的实际应用。下面将详细阐述Git工作流的基本概念、常用工作流模型以及与JavaScript开发相关的实践。 1. Git基本概念: - **分支*...

    cjayb-kingjr_natmeg_arhus-archive-refs-heads-master.zip

    如果你打算对代码进行修改或扩展,理解Git工作流将非常有用,因为它可以帮助你追踪和管理变更。对于Git不熟悉的用户,学习基本的Git命令如`clone`, `checkout`, `commit`, `push`和`pull`将有助于协作和版本控制。

    完全学会GIT+GITHUB+GIT+SERVER的24堂课

    在实际项目中,常见的Git工作流有Git Flow、GitHub Flow和GitLab Flow等。Git Flow强调预发布分支(如develop和feature)和长期分支(如master和release),而GitHub Flow则简化为master一个分支,强调快速合并和...

    pro git 中英文

    8. **Git工作流**:Git支持多种工作流,如主干开发、特性分支、GitFlow、Forking等,根据项目需求选择合适的工作流可以提高团队协作效率。 9. **Git工具和图形界面**:除了命令行工具,还有TortoiseGit、SourceTree...

    git中文教程

    在Git的使用中,首先需要掌握的是Git工作流的概念。工作流简单来说就是团队成员之间协同工作的流程,它规定了源代码的组织、提交以及管理方式。根据团队的规模和项目的不同,工作流的模式也会有所不同。本教程介绍了...

    Git 钩子:定制工作流.zip

    Git钩子是Git版本控制系统中的一个强大特性,它允许用户在特定操作执行之前或之后运行自定义脚本,以此来实现对Git工作流的定制。本文将深入探讨Git钩子的工作原理、种类以及如何利用它们优化开发流程。 一、Git...

    Git版本控制管理 第2版.pdf.zip

    Git flow是一种常见的Git工作流模式,它定义了明确的分支策略,包括开发分支、特性分支、发布分支和热修复分支,以规范团队协作流程。 本书可能涵盖了以下关键知识点: 1. **Git基础**:安装与配置Git,创建和克隆...

    progit中文版.docx

    每一种工作流模型都有其特定的应用场景和优势,作者通过对这些工作流的分析,帮助团队选择最适合自身项目管理方式的Git工作流。 为了更好地帮助读者理解和吸收知识点,《ProGit中文版》在每个章节中都配有丰富的...

    progit.pdf--git学习教程

    这对于理解Git的分布式工作流非常关键,尤其是在多人协作的项目中。同时,本部分还介绍了如何处理远程分支和变基操作。 在“服务器上的Git”章节中,介绍了如何在服务器上搭建Git,包括使用不同的协议(如HTTP、SSH...

    git免安装版.zip

    通过Git GUI,初学者或者不习惯命令行操作的用户可以更轻松地理解Git的工作流程。在"Gitgui64_jb51"这个文件中,包含的就是适用于64位系统的Git GUI。它提供了类似于图形化的文件管理器的视图,用户可以方便地查看...

    Spring Cloud+Spring Boot+Git&GitHub;+Spring in action+SpringBoot

    本资源包涵盖了Spring Cloud、Spring Boot、版本控制工具Git及代码托管平台GitHub,以及Spring框架的经典书籍《Spring in Action》的相关内容,旨在帮助开发者深入理解和应用这些技术。 1. **Spring Boot**: Spring...

    git安装包git-2.34.0-64-bit.rar

    1. **基本概念**:理解Git的基本术语,如仓库(Repository)、提交(Commit)、分支(Branch)、合并(Merge)和克隆(Clone),是使用Git的第一步。 2. **初始化和配置**:在安装Git后,用户需要配置用户名和电子...

Global site tag (gtag.js) - Google Analytics