5

关于Git分支工作流的一些笔记

 2 years ago
source link: https://liruilongs.github.io/2022/08/02/rhca/DO447/%E5%85%B3%E4%BA%8EGit%E5%88%86%E6%94%AF%E5%B7%A5%E4%BD%9C%E6%B5%81%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AC%94%E8%AE%B0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

关于Git分支工作流的一些笔记

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。——–王小波


  • 今天和小伙伴们分享一些Git分支工作流的笔记
  • 学习的原因,希望通过学习了解大型项目的如何使用Git管理
  • 博文为《Pro Git》读书笔记整理
  • 感谢开源这本书的作者和把这本书翻译为中文的大佬们
  • 理解不足小伙伴帮忙指正,书很不错,感兴趣小伙伴可以去拜读

傍晚时分,你坐在屋檐下,看着天慢慢地黑下去,心里寂寞而凄凉,感到自己的生命被剥夺了。当时我是个年轻人,但我害怕这样生活下去,衰老下去。在我看来,这是比死亡更可怕的事。——–王小波


分支开发工作流

大多数的时候,使用Git的开发者都喜欢只在master分支上保留完全稳定的代码,一般为已经发布即将发布的代码。

还有一些名为develop或者next平行分支,被用来做后续开发或者测试稳定性,这些分支不必保持绝对稳定,但是一旦达到稳定状态,它们就可以被合并入master分支了。

类似下的样子,当然这里的分支周期很短

在这里插入图片描述

在这里插入图片描述

这样,在确保这些已完成的主题分支(短期分支)能够通过所有测试,并且不会引入更多bug之后,就可以合并入主干分支中,等待下一次的发布。

事实上我们刚才讨论的,是随着你的提交而不断右移的指针。稳定分支的指针总是在提交历史中落后一大截,而前沿分支的指针往往比较靠前。

在这里插入图片描述

在这里插入图片描述

通常把他们想象成流水线(work silos)可能更好理解一点,那些经过测试考验的提交会被遴选到更加稳定的流水线上去。

在这里插入图片描述

在这里插入图片描述

可以用这种方法维护不同层次的稳定性。一些大型项目还有一个proposed(建议)pu:proposed updates(建议更新)分支,它可能因包含一些不成熟的内容而不能进入next或者master分支。这么做的目的是使你的分支具有不同级别的稳定性

当它们具有一定程度的稳定性后,再把它们合并入具有更高级别稳定性的分支中。通过分支实现的工作流不是必须,但是对于复杂的项目往往很有帮助

在master分支上工作到C1,这时为了解决一个问题而新建iss91分支,在iss91分支上工作到C4,然而对于那个问题你又有了新的想法,于是你再新建一个iss91v2分支试图用另一种方法解决那个问题,接着你回到master分支工作了一会儿,你又冒出了一个不太确定的想法,你便在C10的时候新建一个dumbidea分支,并在上面做些实验。你的提交历史看起来像下面这个样子:

在这里插入图片描述

在这里插入图片描述

现在,我们假设两件事情:你决定使用第二个方案来解决那个问题,即使用在iss91v2分支中方案

另外,你将dumbidea分支拿给你的同事看过之后,结果发现这是个惊人之举。这时你可以抛弃iss91分支(即丢弃C5和C6提交),然后把另外两个分支合并入主干分支。最终你的提交历史看起来像下面这个样子:

在这里插入图片描述

在这里插入图片描述

$ git checkout master
$ git merge dumbidea
$ git merge dumbidea

当然这么多操作的时候,这些分支全部都存于本地。 当你新建和合并分支的时候,所有这一切都只发生在你本地的 Git 版本库中,没有与服务器发生交互。

远程引用是对远程仓库的引用(指针),你可以通过git 1s-remote<remote>来显式地获得远程引用的完整列表,或者通过git remote show <remote>获得远程分支的更多信息。然而,一个更常见的做法是利用远程跟踪分支

在这里插入图片描述

在这里插入图片描述

远程跟踪分支是远程分支状态的引用。通俗的讲,希望在本地可以看到远程分支的状态,它们是你无法移动的本地引用。一旦你进行了网络通信,Git就会为你移动它们以精确反映远程仓库的状态

远程跟踪分支以<remote>/<branch> 的形式命名。例如,如果你想要看你最后一次与远程仓库origin 通信时master分支的状态,你可以查看origin/master分支。

当你在Github或者Gitlab,Gitee上克隆一个项目,Git的clone命令会为你自动将其命名为origin,拉取它的所有数据,创建一个指向它的master分支的指针,并且在本地将其命名为origin/master。Git也会给你一个与origin的master分支在指向同一个地方的本地master分支,这样你就有工作的基础。

下图上面为远程厂库的分支情况,下面为克隆到本地的情况。

在这里插入图片描述

在这里插入图片描述

master 是当你运行git init时默认的起始分支名字,原因仅仅是它的广泛使用,origin是当你运行git clone时默认的远程仓库名字。如果你运行git clone -o booyah,那么你默认的远程分支名字将会是booyah/master

如果你在本地的master分支做了一些工作,在同一段时间内有其他人推送提交到 git.ourcompany.com 并且更新了它的master分支,这就是说你们的提交历史已走向不同的方向。即便这样,只要你保持不与origin 服务器连接(并拉取数据),你的origin/master 指针就不会移动。

在这里插入图片描述

在这里插入图片描述

**如果要与给定的远程仓库同步数据**,运行git fetch <remote>命令(在本例中为git fetch origin)。这个命令查找“origin”是哪一个服务器(在本例中,它是git.ourcompany.com),从中抓取本地没有的数据,并且更新本地数据库,移动origin/master指针到更新之后的位置。

在这里插入图片描述

在这里插入图片描述

添加远程仓库到当前Git版本库

为了演示有多个远程仓库与远程分支的情况,我们假定你有另一个内部Git服务器,仅服务于你的某个敏捷开发团队。这个服务器位于git.teaml.ourcompany.com。你可以运行git remote add命令添加一个新的远程仓库引用到当前的项目,将这个远程仓库命名为teamone

在这里插入图片描述

在这里插入图片描述

现在,可以运行git fetch teamone来抓取远程仓库teamone有而本地没有的数据。因为那台服务器上现有的数据是origin服务器上的一个子集,所以Git并不会抓取数据而是会设置远程跟踪分支teamone/master 指向teamone的master分支

在这里插入图片描述

在这里插入图片描述

推送本地分支到远程

当你想要公开分享一个分支时,需要将其推送到有写入权限的远程仓库上。如果你在本地新建的分支并做了commit,服务端会有一个申请合并的消息,在我日常的开发中,大都也是以这种方式来提交代码,

本地的分支并不会自动与远程仓库同步—-你必须显式地推送想要分享的分支。这样,你就可以把不愿意分享的内容放到私人分支上,而将需要和别人协作的内容推送到公开分支。

如果希望和别人一起在名为serverfix的分支上工作,你可以像推送第一个分支那样推送它。运行git push<remote><branch>

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
* [new branch] serverfix -> serverfix

也可以运行git push origin serverfix:serverfix,推送本地的 serverfix分支,将其作为远程仓库的serverfix分支

如果并不想让远程仓库上的分支叫做 serverfix,可以运行git push origin serverfix:awesomebranch 来将本地的serverfix分支推送到远程仓库上的awesomebranch分支

使用推送的远程分支

下一次其他协作者从服务器上抓取数据时 git fetch origin,他们会在本地生成一个远程分支 origin/serverfix,指向服务器的serverfix分支的引用:

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
* [new branch] serverfix -> origin/serverfix

要特别注意的一点是当抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本(拷贝)。换一句话说,这种情况下,不会有一个新的serverfix分支——只有一个不可以修改的origin/serverfix指针。

可以运行git merge origin/serverfix将这些工作合并到当前所在的分支

如果想要在自己的serverfix分支上工作可以新建分支在远程跟踪分支之上

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

这会给你一个用于工作的本地分支serverfix,并且起点位于 origin/serverfix

从一个远程跟踪分支检出一个本地分支会自动创建所谓的“跟踪分支”(它跟踪的分支叫做“上游分支”)。跟踪分支是与远程分支有直接关系的本地分支。如果在一个跟踪分支上输入git pu11,Git能自动地识别去哪91个服务器上抓取、合并到哪个分支。

当克隆一个仓库时,它通常会自动地创建一个跟踪origin/mastermaster分支。然而,如果你愿意的话可以设置其他的跟踪分支,或是一个在其他远程仓库上的跟踪分支,又或者不跟踪master分支。最简单的实例就是像之前看到的那样,运行git checkout-b <branch><remote>/<branch>

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

这是一个十分常用的操作所以Git 提供了--track快捷方式,该捷径本身还有一个捷径,如果你尝试检处的分支不存在且刚好有一个远程分支与之对应,那么Git就会为你创建一个远跟踪分支。

$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

设置已有的本地分支跟踪一个刚刚拉取下来的远程分支,或者想要修改正在跟踪的上游分支,你可以在任意时间使用-u或--set-upstream-to选项运行git branch来显式地设置。

$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.

拉取 fetch和pull的区别

git fetch命令从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容。它只会获取数据然后让你自己合并

git pull在大多数情况下它的含义是一个git fetch紧接着一个git merge命令

由于git pull的魔法经常令人困惑所以通常单独显式地使用fetch与merge命令会更好一些。

删除远程分支

可以运行带有--delete选项的git push命令来删除一个远程分支。 如果想要从服务器上删除 serverfix 分支,运行下面的命令:

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
- [deleted] serverfix

基本上这个命令做的只是从服务器上移除这个指针。 Git 服务器通常会保留数据一段时间直到垃圾回收运行,所以如果不小心删除掉了,通常是很容易恢复的。

这一章中,你将会学习如何作为贡献者或整合者,在一个分布式协作的环境中使用Git。你会学习为一个项目成功地贡献代码,并接触一些最佳实践方式,让你和项目的维护者能轻松地完成这个过程。另外,你也会学到如何管理有很多开发者提交贡献的项目。

分布式工作流程

与传统的集中式版本控制系统(CVCS)相反,Git的分布式特性使得开发者间的协作变得更加灵活多样。

在集中式系统中,每个开发者就像是连接在集线器上的节点,彼此的工作方式大体相像。而在分布式Git中,每个开发者同时扮演着节点和集线器的角色,也就是说,每个开发者既可以将自己的代码贡献到其他的仓库中,同时也能维护自己的公开仓库,让其他人可以在其基础上工作并贡献代码。

Git的分布式协作可以为项目和团队衍生出种种不同的工作流程,一起来学习下

集中式工作流

集中式系统中通常使用的是单点协作模型——集中式工作流。一个中心集线器,或者说仓库,可以接受代码,所有人将自己的工作与之同步。若干个开发者则作为节点,即作为中心仓库的消费者与中心仓库同步。

在这里插入图片描述

在这里插入图片描述

例如John和Jessica同时开始工作。John完成了他的修改并推送到服务器。接着Jessica尝试提交她自己的修改,却遭到服务器拒绝。她被告知她的修改正通过非快进式(non-fast-forward)的方式推送,只有将数据抓取下来并且合并后方能推送。这种模式的工作流程的使用非常广泛,因为大多数人对其很熟悉也很习惯。

当然这并不局限于小团队。利用Git的分支模型,通过同时在多个分支上工作的方式,即使是上百人的开发团队也可以很好地在单个项目上协作。

集成管理者工作流

Git允许多个远程仓库存在,使得这样一种工作流成为可能:

每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。这种情形下通常会有个代表“官方”项目的权威的仓库

要为这个项目做贡献,你需要从该项目克隆出一个自己的公开仓库,然后将自己的修改推送上去。接着你可以请求官方仓库的维护者拉取更新合并到主项目。

维护者可以将你的仓库作为远程仓库添加进来,在本地测试你的变更,将其合并入他们的分支并推送回官方仓库。这一流程的工作方式如下所示

在这里插入图片描述

在这里插入图片描述

  1. 项目维护者推送到主仓库。
  2. 贡献者克隆此仓库,做出修改。
  3. 贡献者将数据推送到自己的公开仓库。
  4. 贡献者给维护者发送邮件,请求拉取自己的更新。
  5. 维护者在自己本地的仓库中,将贡献者的仓库加为远程仓库并合并修改
  6. 维护者将合并后的修改推送到主仓库。

这也是GitHub和GitLab等集线器式(hub-based)工具最常用的工作流程。

人们可以容易地将某个项目派生成为自己的公开仓库,向这个仓库推送自己的修改,并为每个人所见。这么做最主要的优点之一是你可以持续地工作,而主仓库的维护者可以随时拉取你的修改。贡献者不必等待维护者处理完提交的更新——每一方都可以按照自己的节奏工作。

主管与副主管工作流

这其实是多仓库工作流程的变种。一般拥有数百位协作开发者的超大型项目才会用到这样的工作方式,例如著名的Linux内核项目。被称为副主管(lieutenant)的各个集成管理者分别负责集成项目中的特定部分。所有这些副主管头上还有一位称为主管(dictator)的总集成管理者负责统筹。主管维护的仓库作为参考仓库,为所有协作者提供他们需要拉取的项目代码。整个流程看起来是这样的(见主管与副主管工作流。):

在这里插入图片描述

在这里插入图片描述

  1. 普通开发者在自己的主题分支上工作,并根据master分支进行变基。这里是主管推送的参考仓库的master分支。
  2. 副主管将普通开发者的主题分支合并到自己的master分支中。
  3. 主管将所有副主管的master分支并入自己的master分支中。
  4. 最后,主管将集成后的master分支推送到参考仓库中,以便所有其他开发者以此为基础进行变基

这种工作流程并不常用,只有当项目极为庞杂,或者需要多级别管理时,才会体现出优势。利用这种方式,项目总负责人(即主管)可以把大量分散的集成工作委托给不同的小组负责人分别处理,然后在不同时刻将大块的代码子集统筹起来,用于之后的整合。


《Pro Git》


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK