Mode of managing source code branch
ryougifujino 2021-08-09 16:35:00

From my blog ryougifujino.com.

Preface : Translation of this long article 、 Touch up 、 It took me close to... To correct the intermittent 3 months ( I feel like I haven't had the power to open a new pit for a long time ).Martin Fowler After reading this article, I have a feeling of being impressed ( His website martinfowler.com/ I feel like a treasure ). To be honest, I've also read a lot of articles on version control workflow , But I always feel that I have a taste of something or avoid talking about it , But this article tells you the advantages and disadvantages of various models one by one , Answered many questions in my heart , It can be said that after reading, it has a good enlightening effect on which scenarios and which modes should be used ( For business software , Of course, continuous integration is the best ).


Original author :Martin Fowler

Original address

Modern source control system provides a powerful tool , Makes it easy to create branches in the source code . But eventually these branches have to merge together , Many teams also spend a lot of time gluing these branches together . There are several patterns that allow teams to use branching effectively , And let the team focus on integrating the work of multiple developers and organizing to production (production) Around the published path . The theme that runs through the whole is , Branches should be integrated frequently , And efforts should focus on the health main line that can be released to the production environment at the least cost .


Source code is a vital asset for any software development team , In the past few decades , A lot of source code management software has been developed to keep the code neat . These tools make changes traceable , Let's rebuild the previous version of the software , And you can see how it develops over time . These tools are also coordinate centers with multiple teams of programmers , Everyone works on a common code base . By recording the changes made by each developer , These systems can track multiple work lines at once , And help developers figure out how to combine these multiple work lines .

The splitting and merging of this work line is the core workflow of the software development team , And some patterns have evolved a way to help us deal with these activities . Like most software patterns , None of them is the golden rule that the team must abide by . The workflow of software development is very dependent on the environment (context), In particular, the social structure of the team and other practices followed by the team .

In this article , My task is to discuss these patterns , And in the context of a single article . In this article, I describe patterns , But the narrative part is interspersed in the interpretation of the model , These narrative parts can better explain the relationship between environment and model . In order to distinguish them more easily , I use “*” The symbol marks the part of the pattern .

The basic pattern

When thinking about these patterns , I find it useful to develop two main categories . One group focuses on Integrate , That is, how multiple developers combine their work into a coherent whole . The other group focused on The path to production , Use branches to help manage the path from the integrated code base to the product running in production . Some patterns support both of them , I'll see this as a basic model . The remaining patterns are neither basic patterns , Nor can it be attributed to these two main groups —— So I'll save them for the last .

Source code branching behavior *

Create a copy and record all changes to that copy .

If several people work in the same code base , Then it will soon become impossible to work on the same file . If I want to run the compiler , And my colleague is typing an expression , Then the compilation will fail . We'll have to yell at each other :“ I'm compiling , Don't change things ”. Even if there are only two people , It's hard to last , Not to mention a larger team .

The simple answer to this question is , Each developer holds a copy of the code base . Now we can easily work on our own functions , But a new problem arises : When we finish our work , How to merge our two copies together again ?

The source control system makes this process easier . The key lies in , It records every change in each branch as a commit (commit). This not only ensures that no one forgets their feelings about utils.java Small changes made , And record changes can make merging easier , Especially when several people modify the same file .

This leads me to the definition of branches to be used in this article . I define a branch as a specific commit sequence in the code base . The head of the branch , Or the top , Is the latest submission in the sequence .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c2c53c3846c24da48f6265a1a35567d6~tplv-k3u1fbpfcp-zoom-1.image

  1. A branch is a series of submissions
  2. Head ( Or top ) This is the latest submission in this series

This is a noun , But there are also verbs ,“ To branch (to branch)”. At this point, I mean creating a new branch , It can also be seen as splitting the original branch into two . When the commit of one branch is applied to another branch , Branches merge .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9d247183f58c4e2f8606a336d87f3a27~tplv-k3u1fbpfcp-zoom-1.image

  1. When two submissions are created in parallel , A branch will separate
  2. One branch can be merged into another branch . There will be some work to deal with these parallel changes
  3. If there is no change since the last merge , A change on one branch can be simply applied to another

I am right. “ Branch ” The definitions used are consistent with the way most developers talk about them... I have observed . But source control systems tend to be used in a more specific way “ Branch ”. I can illustrate this with a common situation in modern development teams ( The team keeps the source code in a shared git Warehouse ). A name Scarlett Developers need to make some changes , So she cloned git Warehouse , And detected (checkout) 了 master Branch . She made several changes , And submitted it to her master. meanwhile , Another developer , We call her Violet, Clone the warehouse onto her desktop , And detected master Branch . that Scarlett and Violet Working in the same branch , Or on different branches ? They are all “master” To work on , But their submissions are independent of each other , And when they push their changes to the shared warehouse , Need to merge . If Scarlett I'm not sure about the changes I've made , So she labeled the last submission , And put her master Branch reset to origin/master( The last submission she cloned from the shared warehouse ), So what happens ?

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/df1733b3afcd41feaf19e62bfa85631d~tplv-k3u1fbpfcp-zoom-1.image

According to my previous definition of branch ,Scarlett and Violet It works on separate branches , They are separated from each other , Also share the warehouse with master Branch separation . When Scarlett Put her work label aside , By my definition , It's still a branch ( And she probably thinks it's a branch ), But with git That's what I'm saying , It's a labeled code line .

stay git In such a distributed version control system , This means that whenever we further clone a warehouse , We'll also get additional branches . If Scarlett Cloned her local warehouse , Put it on her notebook ( Preparation for going home by train ), She created a third master Branch . stay GitHub On fork The same effect will happen when —— Every quilt fork All warehouses have their own additional set of branches .

When we encounter different version control systems , This confusion of terminology is even more serious , Because they all have their own definitions of what a branch is .Mercurial Branches and git The branches in are completely different ,git The branch in is closer to Mercurial The concept of bookmarks in .Mercurial You can also use unnamed head Create a branch , also Mercurial Users of often create branches by cloning repositories .

All the confusion about this term has led some people to avoid it . A more general term would be useful here , That's it Code line (codeline). I define a code line as a sequence of specific versions of a code base . It can end with a tag , It can also be a branch , Or lost in git Of reflog in . You will notice that there is a strong similarity between my definition of branches and my definition of codelines .Codeline It is a more useful term in many ways , I do use it , But it is not widely used in practice . So in this article , Unless in git( Or other tools ) The specific context of the term , Otherwise, I'll use the words branch and code line alternately .

The result of this definition is , No matter what version control system you use , As long as each developer makes local modifications , You will have at least one personal code line in the working copy on your machine . If I clone a project git Warehouse , Detected master, And updated some files —— Even before I submit anything , This is also a new code line . Again , If I create my own subversion Working copy of the trunk of the warehouse , This working copy is its own code line , Even if it doesn't involve subversion Branch .

When to use it

An old joke says , If you fall from a tall building , Falling doesn't hurt you , But landing will . therefore , For source code : Creating branches is easy , Merging is more difficult .

The source control system that records every change on the submission does make the merge process easier , But they don't make the merger trivial . If Scarlett and Violet Change a variable to a different name at the same time , Then the source code management system can not solve the conflict without human intervention . What's more embarrassing is , At least this Text conflict It can be found by the source control system , And remind humans to take a look . But there is often another conflict : There is no problem with text merging , But the system still doesn't work . Imagine ,Scarlett Changed the name of a function , and Violet Added some code to her branch , Call this function with its old name . This is what I call Semantic conflict . When these conflicts occur , The system may not be able to build , Or it can be built with errors at run time .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e05677f0c19e4c38bf308b31dc0fef2b~tplv-k3u1fbpfcp-zoom-1.image

Jonny LeRoy Like to point out that people ( Including me ) When drawing the branch graph defects

  1. How do most people draw branch diagrams
  2. How should we actually draw them , To show differences over time

For anyone who has worked in concurrent or distributed computing , This question will be familiar . We have some shared states ( The code base ), Developers can create updates in parallel . We need some way to serialize these updates into consensus updates to combine them . Having a system execute and run correctly means that the shared state has very complex validity criteria , This fact complicates our task . There is no way to create a deterministic algorithm to find consensus . Humans need to find this consensus , This consensus may involve mixing the selected parts of different updates . Usually , Only by solving the conflict through the original update can a consensus be reached .

I :“ What if there were no branches ”. Everyone edits real-time code , Half baked changes can paralyze the system , People trample on each other . therefore , We give people the illusion of freezing time , They are the only people who have changed the system , These changes can wait until they are fully baked before they bring risks to the system . But this is an illusion , The price will eventually be paid . Who will pay ? When ? How much ? This is what these patterns are talking about : An alternative to paying the piper .

——Kent Beck

therefore , In the rest of this article , I listed various patterns , They support the pleasant isolation and the wind at your hair when you fall , But minimize the inevitable consequences of contact with hard ground .

Thread *

A single 、 Shared 、 As a branch of the current state of the product .

Thread Is a special code line , We think it's the current state of the team code . Whenever I want to start a new job , I will pull the code from the main line to my local warehouse , Start working again . Whenever I want to share my work with other team members , I'll update my work to the main line , It's best to use what I'll discuss soon Mainline integration Pattern .

Different teams use different names for this particular branch , This is usually determined by the conventions of the version control system used .git Users often call it “master”,subversion Users often call it “trunk”.

I must emphasize here , The main line is a single 、 Shared Codeline . When people are git Talk about “master” when , They can refer to several different things , Because each version library clone has its own local master. Usually such a team has a The central warehouse —— A shared warehouse , As a single record point of the project , And it's the source of most clones . Starting from scratch, a new job means cloning this central warehouse . If I already have a clone , I'll pull... From the central warehouse master Start , So it can be consistent with the main line . under these circumstances , The main line is... In the central warehouse master Branch .

When developing my features , I will have my own personal development branch , It may be my local master, Or I might create a separate local branch . If I work here for a while , I can pull the changes of the main line at regular intervals , And merge it into my personal development branch , To synchronize the latest changes in the main line .

similarly , If I want to create a new version of the product for release , I can start with the current main line . If I need to fix bug To make the product stable enough to be released , I can use one Release branch To achieve the goal .

When to use it

I remember being 21 Talking to a customer's Construction Engineer at the beginning of the century . His job is to build the product the team is developing . He will send an email to each member of the team , Then they will send a file of the code base they are ready to integrate in response . then , He copies these files into his integration tree , And try to compile the code base . It usually takes him weeks to create a build that can be compiled , And prepare for some form of test .

by comparison , With the main line , Anyone can quickly start a new product build from the top of the main line . Besides , The mainline not only makes it easier to see the state of the code base , It is also the basis for many other models I will explore soon .

An alternative to the main line is Release the train .

Healthy branches *

At each submission , Perform automatic checks , Usually build and run tests , To ensure that there are no defects on the branch .

because Thread Have shared and verified status , So it's important to keep it stable . Still 21 At the beginning of the century , I remember talking to a team in another organization , This team is famous for building each of their products every day . This was considered quite advanced at that time , And this organization is praised for doing so . But what is not mentioned in these articles is , These daily builds are not always successful . in fact , It's easy to find teams that haven't compiled their daily builds for months .

To solve this problem , We can try to keep our branches healthy —— This means that it can successfully build , And software rarely appears at runtime bug( If any ). To make sure that , I found that writing Self test code (Self Testing Code) Is crucial . This development practice means that we write production code at the same time , Also write a comprehensive set of automated tests , So we can be sure , If these tests pass , Then the code does not contain any bug. If we do that , Then we can keep a branch healthy by running a build at each commit , This build includes running the test suite . If the system fails to compile , Or the test fails , Then our first task is to fix them before doing anything else on the branch . This usually means that we have to “ frozen ” This branch —— No commit will be allowed until this branch is restored to health .

Around the degree of testing , There is a tension (tension) To provide enough health confidence . Many more thorough tests take a lot of time to run , Delayed submission of healthy feedback . The team passed in Deployment pipeline (Development Pipeline) Divide the test into multiple phases to deal with this problem . The first phase of these tests should run quickly , Usually no more than 10 minute , But it should still be more comprehensive . I call such a suite a submission suite ( Although it is often called “ unit testing ”, Because submission kits are usually unit testing ).

Ideally , All tests should run on each submission . However , If the test is slow , For example, performance testing requires soaking the server for several hours , This is not very realistic . Now? , Teams can usually build a submission suite that can run on each submission , And run the later stages of the deployment pipeline as often as possible .

The code does not run bug Not enough to say that the code is good . In order to maintain a stable delivery speed , We need to maintain the internal quality of the code . A popular method is to use Pre integration review (Pre-Integration Review), Although we will see , There are other options .

When to use it

Each team should have clear criteria for the health of each branch of its development workflow . Keeping the main line healthy is of great value . If the main line is healthy , Then developers can start a new job by pulling the current main line , Without being bothered by the defects that hinder their work . We often hear people before starting a new job , It takes days to fix or tweak the errors in the code they pull down .

A healthy main line can also make the path to production smoother . A new production candidate (production candidate) Can be constructed from the head of the main line at any time . The best teams find that they only need to do very little to stabilize such a code base , It can always be released directly from the main line to production .

The key to having a healthy main line is Self test code ( Its submission suite can run in a few minutes ). Building this capacity can be a huge investment , But once we can make sure that my submission doesn't break anything in a few minutes , Then it will completely change our whole development process . We can make changes faster , Confidently restructure Our code , Make it easy to work , And greatly shorten the cycle from the capabilities we need to run the code in production .

For the personal development branch , It's wise to keep them healthy , Because this can achieve Comparative debugging (Diff Debugging). But this desire is associated with frequent submissions to checkpoint the current state (checkpoint) Contrary to your practice . If I'm going to try a different path , I might create a checkpoint if the compilation fails . My solution to this contradiction is , Once I finish my current work , Just compress any unhealthy submissions (squash). thus , After a few hours, only healthy submissions will remain on my branch .

If I keep my personal branch healthy , This will also make it easier for me to submit to the main line —— I'll know Mainline integration Any errors in are caused by integration , Not because of an error in my code base . This will make me faster 、 It's easier to find and fix them .

Integration mode

Branching behavior is about managing the interaction between isolation and integration . It doesn't work for everyone to work in a single shared code base all the time , Because if you're entering a variable name , I can't compile the program . So at least in a way , We need the concept of a private workspace where we can work for a while . Modern source control tools make it easy to manipulate branches and monitor changes on them . However , At some point , We need to integrate . Thinking about branching strategy is actually deciding how and when we integrate .

Mainline integration *

Developers pull from the mainline 、 Merger and —— If healthy —— Push back to the main line to integrate their work .

The main line gives a clear definition of what the current state of the team software is . One of the biggest benefits of using mainlines is that it simplifies integration . If there is no main line , The collaboration between each member of my above-mentioned team will be a complex task . However , With the mainline, each developer can integrate on their own .

I'll use an example to show how this works . A developer , I call her Scarlett, By cloning the main line to her own warehouse to start working . stay git in , If she doesn't have a clone from the central warehouse , She'll clone it and detect (checkout)master Branch . If she already has a clone , She'll pull the main line to her local master. Then she can work locally , To her local master Submit .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b5eba8f5c6974ba4b1ee0d5c722a4193~tplv-k3u1fbpfcp-zoom-1.image

While she was working , Her colleagues Violet Push some changes to the main line . Because she works in her own code line ,Scarlett You can forget these changes while focusing on your tasks .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3e1d203a0534431cacf2a563e5f86067~tplv-k3u1fbpfcp-zoom-1.image

At some point , She has reached the level of integration she wants . The first part of the integration is to capture the current state of the mainline (fetch) To her local master Branch , This will pull in Violet Modification of . Because she is local master To work on , The submitted content will be in origin/master It is displayed as a separate code line .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3913d45b2d724c12b46f442f305723ff~tplv-k3u1fbpfcp-zoom-1.image

Now she needs to put her changes and Violet Combined with the changes of . Some teams like to merge (merge) The way , Some use variable bases (rebase) The way . Generally speaking , When people talk about integrating branches together, they use “ Merge (merge)” The word , Whether they actually use git merge still rebase operation . I will follow this usage , So unless I'm really talking about merge and rebase The difference between , Otherwise, I will “ Merge ” As a logical task that can be implemented in either way .

About whether to use native merge (vanilla merge), Use or avoid fast forward (fast-forward) Merge , Or use rebase, There is a complete other discussion . This is beyond the scope of this article , Although if people send me enough Tripel Karmeliet, I may write an article on this issue . After all , Recently, I exchanged things for things (quid-pro-quos) Is very popular .

If Scarlett It's lucky , Merge Violet The code will be a clean merge , If not , She will have some conflicts to deal with . These may be textual conflicts , Most of the source control systems can automatically process . But semantic conflicts are more difficult to deal with , This is it. Self test code It's time to use .( There will be a lot of work due to conflict , And always introduce risks to a lot of work , So I marked them with an obvious yellow .)

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/156ac698a75c4109ae23816ed29b4d89~tplv-k3u1fbpfcp-zoom-1.image

here ,Scarlett You need to verify that the merged code meets the health standards of the mainline ( Suppose the main line is Health Branch ). This usually means building code and running any tests from the mainline commit Suite . Even clean mergers , She needs to do the same , Because even clean merges hide semantic conflicts . Any failure in the commit suite should be purely a result of consolidation , Because two merged parents (merge parent) Should be normal . Knowing this should help her find the problem , Because she can learn from the difference (diff) Looking for clues .

Through this build and test , She has successfully pulled the mainline into her code line , however —— This is both important and often overlooked —— She hasn't finished integrating with the main line yet . In order to complete the integration , She has to push her change to the main line . Unless she does , Otherwise, the rest of the team will be isolated from her changes —— There is actually no integration . Integration is both pull and push —— Only Scarlett The part that has been pushed is the work integrated with other parts of the project .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3fe8560b7f644e9dac38db47d6e83613~tplv-k3u1fbpfcp-zoom-1.image

Recently, many teams have asked to submit (commit) Code review before adding to the mainline —— One I call Pre integration review The pattern of , Then I'll talk about .

Occasionally someone is Scarlett Integrate with the main line before pushing . under these circumstances , She had to pull (pull) And merge again . Usually this is just an accidental problem , No further coordination is needed to solve . I've seen teams with long build processes use the integration baton , In this way, only developers with a baton can integrate . But in recent years , As build time improves , I've hardly heard such a thing again .

When to use it

seeing the name of a thing one thinks of its function , Only when our products are using the main line , I can use mainline Integration .

One option to use mainline integration is to pull directly from the mainline (pull), Merge these changes into the personal development branch . This may be useful —— Pulling can at least remind Scarlett Notice the changes that others have integrated , And find the conflict between her work and the main line . But it was not until the Scarlett Before pushing ,Violet Will not find her work and Scarlett Any conflict between changes to .

When people use “ Integrate ” This word , They often ignore this important problem . I often hear people say that they are integrating the main line into their branches , And they're just pulling . I learned to be wary of this statement , And further explore , See if they mean simple pull or appropriate mainline integration . The results of the two are very different , So it's very important not to confuse these terms .

Another option is , When Scarlett On the way to some work that is not yet ready for full integration with other members of the team , But these jobs are related to Violet There are overlapping parts , also Scarlett Want to share with her . under these circumstances , They can choose to create a Collaboration Branch .

Function branch mode *

Put all the work of a function on its own branch , When the function is completed, it will be integrated into the main line .

In the process of using function branching mode , Developers open a branch when they start working , Continue to work until the function is completed , Then integrated into the main line .

for example , Let's follow Scarlett have a look . She developed the ability to add a collection of local sales taxes to their website . She started with a stable version of the current product , She'll pull the main line to her local warehouse , Then create a new branch from the top of the current mainline . As long as there is a need , She will develop this feature , A series of commits are made on this local branch .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f3c7dedb7251471eb1d971a4f51478a7~tplv-k3u1fbpfcp-zoom-1.image

She might push this branch to the project repo in , So that others can see her changes .

While she was working , Other submissions continue to fall on the main line . therefore , She may pull from the main line from time to time , So she can know if there are changes that may affect her future .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b9d52d791acb4b25b4b7d9c43d7a0912~tplv-k3u1fbpfcp-zoom-1.image

Note that this is not the integration I mentioned above , Because she didn't push back to the main line . At this time, only she can see her work , Others can't see .

Some teams like to make sure that all the code , Whether integrated or not , All kept in the central warehouse . under these circumstances ,Scarlett Will push her functional branches to the central warehouse . It will also let other team members see what she is doing , Even if it hasn't been integrated into the work of others .

When she has finished the work of this function , She will perform Mainline integration , Incorporate this feature into the product .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d5f4a84842714bb49f8666d85cef1709~tplv-k3u1fbpfcp-zoom-1.image

If Scarlett Develop more than one function at the same time , She will open a separate branch for each function .

When to use it

Function branching mode is a popular mode in the industry . To discuss when to use it , I need to introduce its main alternatives —— Continuous integration . But first I need to talk about the integration frequency .

Integration frequency

The frequency of our integration has a great impact on the operation of a team . come from 《State Of Dev Ops Report》 According to the study , The integration frequency of elite development teams is significantly higher than that of underperforming teams —— This observation is consistent with my experience and the experience of many peers in the industry . I will pass by Scarlett and Violet Two examples of dominant integrated frequencies are used to illustrate this .

Low frequency integration

Let me talk about low frequency first . ad locum , Our two heroes opened a chapter of work : Clone the main line into their branches , Then complete some local submissions they don't want to push yet .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8466a53cb14a4103b3298f91aa479622~tplv-k3u1fbpfcp-zoom-1.image

When they work , Others put some submissions on the main line .( I can't think of another vivid name quickly —— Maybe Grayham?)

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6df4a344622f4461a1e87ad1b6bcb1a2~tplv-k3u1fbpfcp-zoom-1.image

The way the team works is to keep a healthy branch , And pull... From the main line after each submission . Since the main line has not changed ,Scarlett I can't get anything after the first two submissions , But now we need to M1 Pull it down .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1d857a4f3acc42a4a3dfa9513f468424~tplv-k3u1fbpfcp-zoom-1.image

I have marked the merge node with a yellow box . This node merges S1...3 and M1 These submissions . Soon ,Violet The same thing needs to be done .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e1c58323a3444b7cafecfd436589bdc7~tplv-k3u1fbpfcp-zoom-1.image

here , Both developers have updated to the latest mainline , But they haven't integrated yet , Because they are isolated from each other .Scarlett Be unaware of Violet stay V1 To V3 Any changes made in .

Scarlett Several more local submissions have been completed , Then prepare for mainline integration . It's easy for her , Because she pulled earlier M1.

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/91ab1c5b997b44efbd9faa561eeb5034~tplv-k3u1fbpfcp-zoom-1.image

However ,Violet There is a more complex job . When she does mainline Integration , She must now S1...5 And V1...6 Integrate .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/41db4a8e75a54ea7bd9181f8ea04cff9~tplv-k3u1fbpfcp-zoom-1.image

Based on the number of submissions involved , Scientifically calculated the scale of the merger . however , Even if you ignore the tongue bulge on my cheek , You will agree Violet The merger of is most likely to be difficult .

High frequency integration

In the previous example , Our two colorful developers integrated after a small number of local submissions . Let's see what happens if they do mainline integration after each local commit .

Violet The changes in the first submission are clear , Because she immediately integrated . Since the main line has not been modified , So this is just a simple push .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/874b130c4c7843068b23460e53f92c4d~tplv-k3u1fbpfcp-zoom-1.image

Scarlett The first submission of will also be subject to mainline integration , But because of Violet I did , So she needs a merger . But because she only needs to merge V1 and S1, So the workload of merging is very small .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d84f094a00dc401ab334225a9dba4642~tplv-k3u1fbpfcp-zoom-1.image

Scarlett The next integration is a simple push , It means Violet Your next submission also needs to be with Scarlett The latest two submissions merge . However , This is still a fairly small merger : come from Violet One of the , come from Scarlett Of the two .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d86112af273c47939eb858e1deb50026~tplv-k3u1fbpfcp-zoom-1.image

When an external submission pushed to the mainline appears , It will follow Scarlett and Violet The consistent rhythm of is integrated by each .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4beed6bb23fe4c51a558cd2f770aaed9~tplv-k3u1fbpfcp-zoom-1.image

Although this is similar to what happened before , But integration has become smaller .Scarlett This time just need to S3 And M1 Integrate , because S1 and S2 It's already on the main line . It means Grayham It's pushing M1 Before , Must integrate anything already on the mainline (S1...2, V1...2).

Developers continue with the rest of their work , And integrate at each submission .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a7d86916103e4d3f897cf8f3fdbbe94b~tplv-k3u1fbpfcp-zoom-1.image

Compare integration frequency

Let's take another look at these two overall pictures .

Low frequency

https://martinfowler.com/articles/branching-patterns/low-freq-V-push.png

high frequency

https://martinfowler.com/articles/branching-patterns/high-freq-V6.png

There are two very obvious differences . First , High frequency integration , seeing the name of a thing one thinks of its function , There will be more integration —— In this toy example alone, there are twice as many . But more importantly, these integrations are much smaller than those at low frequencies . Smaller integration means less work , Fewer changes cause fewer conflicts . But compared with less work , More importantly, the risk is smaller . The problem with big mergers is not the work they involve , It's the uncertainty of these jobs . Most of the time , Even a big merger will go well , But sometimes very, very bad things happen . In the end, this occasional pain will be worse than the regular pain . If I spend more per Integration 10 Minutes and have 50 Divided 1 The chance to spend 6 Repair an integration in an hour , Which one would I prefer ? If you only look at the workload , that 50 Divided 1 The odds are better , Because it takes six hours instead of eight hours and twenty minutes . But this uncertainty makes 50 Divided 1 The situation feels worse , This uncertainty leads to a fear of integration .

Integrated fear When the team has had several bad merger experiences , They tend to be wary of integration . This can easily become a positive feedback loop —— Like many positive feedback loops , With very negative consequences . The most obvious consequence is that the team reduces the frequency of integration , This will lead to more unfriendly mergers , This leads to lower frequency integration ... wait . A more subtle problem is , The team will stop doing what they think will make integration more difficult . Specially , This will make them resist refactoring . But reducing refactoring can lead to an increasingly unhealthy code base , Difficult to understand and modify , This will drag down the functional delivery of the team . Because it takes longer to complete the function , This will further reduce the integration frequency , Promote a debilitating positive feedback loop . The counterintuitive answer to this question is as the slogan says ——” If the pain ...... Just do it more often “

Let's look at the difference between these frequencies from another angle . If Scarlett and Violet There was a conflict between the initial submissions of , What's going to happen ? When will they find out that the conflict has happened ? At low frequencies , until Violet Only when they finally merge will they find , Because that's S1 and V1 The first time they were put together . But at high frequencies , They are in Scarlett When you merge for the first time, you will find .

Low frequency

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/efec9320b6d04822ba95fb85641cf43d~tplv-k3u1fbpfcp-zoom-1.image

high frequency

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/30849bf632c94f74bbc5300cc9172865~tplv-k3u1fbpfcp-zoom-1.image

Frequent integration increases the frequency of merging , But it reduces its complexity and risk . Frequent integration can also quickly alert the team to conflicts . Of course , These two things are related . Annoying mergers are usually caused by conflicts lurking in team work , Only when integration occurs will it emerge .

Maybe Violet Looking at a billing calculation , See that it includes assessment tax ( The author assumes a specific tax mechanism ). Her function requires different treatment of taxes , So the direct way is to take the tax from the billing calculation , And then make a separate function . Billing calculations are invoked only in a few places , So it's easy to use Move Statements to Callers To deal with it —— And this result is more meaningful for the future development of the program . However ,Scarlett Don't know Violet Is doing this , When she wrote about her function, the fake design fee function had dealt with the tax problem .

Self test code Here is our life-saving straw . If we have a powerful test suite , Use it as part of the health branch , You can find conflict , This will greatly reduce bug The probability of entering the production environment . however , Even with a powerful test suite as the main line goalkeeper , Large scale integration can also make life more difficult . The more code we need to integrate , The harder it is to find bug. There will also be a higher chance of multiple interfering bug, And these bug Is particularly difficult to understand . If the submission is small , Not only do we need to see less , It can also be used Diff Debugging To help narrow the scope of the changes that cause the problem .

Many people don't realize that source control system is a communication tool . It allows the Scarlett See what the rest of the team is doing . Through frequent integration , She can not only be reminded immediately when there is a conflict , And know more clearly what everyone is doing , And how the code base developed . We are not like those individuals who struggle alone with difficulties , It's more like a team working together .

An important reason to reduce the size of functions is to increase the integration frequency , But there are other benefits . The smaller the function , The faster you build , The faster it enters production , The faster you start providing value . Besides , Smaller features reduce feedback time , Enable the team to make better functional decisions while knowing more about customers .

Continuous integration *

Once developers have a healthy submission to share , The mainline integration takes place immediately , Usually less than a day's work .

Once a team experiences high-frequency integration, it will be more efficient , There will be less pressure , Naturally, the question is “ How often can we ?” The functional branching pattern implies a lower bound on the size of the variation set —— You can't be smaller than a cohesive function .

Continuous integration uses a different set of integration triggers —— As long as you make some progress in a function , And your branch is still healthy , Integration . We don't expect this feature to be complete , Just expect valuable changes to be submitted to the code base . The rule of thumb is “ Everyone submits to the main line every day ”, Or to be more precise : No more than one day's work should not be integrated in your local warehouse . In practice , Most practitioners of continuous integration integrate many times a day , And happy to integrate work in an hour or less .

More details on how to effectively conduct continuous integration , Please look at my Detailed article . More details , Please refer to Paul Duvall, Steve Matyas, and Andrew Glover Of This book .Paul Hammant stay trunkbaseddevelopment.com A website full of continuous integration technology is maintained on .

Developers using continuous integration need to get used to reaching integration points frequently , With partially built functions . They need to think about how to do this without exposing part of the built functionality in the operating system . Usually it's easy : If I'm implementing a discount algorithm that relies on coupon code , And this code is not in the valid list , Then my code will not be called even in the production environment . Again , If I'm adding a function to ask insurance claimants if they smoke , I can build and test logic in the code behind it , And by leaving the user interface for asking questions until the last day of this function , To ensure that this function will not be used in production . By connecting at the end Keystone Interface To hide partially built functions is usually an effective technique .

If there is no way to easily hide some functions , We can use feature flags. In addition to hiding some built-in functions , such flag It also allows the function to be selectively disclosed to a subset of users —— This is very convenient for the gradual introduction of a new feature .

The way to integrate the functions built in part is also concerned that those concerns will be introduced into the main line bug People who . therefore , People who use continuous integration also need Self test code , In this way, we are confident that even if there are some built functions on the main line, they will not add bug The risk of . In this way , Developers not only write the partially built functional code, but also write corresponding tests for it , And submit the function code and test to the main line ( May use Test-driven development ).

In the case of local warehouses , Most people who use continuous integration disdain using separate local branches to work . It is usually submitted directly to the local master, Mainline integration after completion . However , If developers like , It's also great to open a functional branch and work there , Just integrate back locally at a frequent interval master And the trunk . The difference between functional branching mode and continuous integration is not whether there is functional branching , It's about when developers integrate with the mainline .

When to use it

Continuous integration is Function branch mode An alternative to . The trade-off between the two is enough for them to have their own chapters in this article , Now is the time to solve this problem .

Continuous integration and backbone based development (Trunk-Based Development) When Thoughtworks stay 2000 When continuous integration began in , We wrote CruiseControl, A daemon that automatically builds software products after each submission to the mainline . From then on , Many of these tools ( Such as Jenkins、Team City、Travis CI、Circle CI、Bamboo And many other tools ) To be developed . However, most organizations that use these tools automatically build functional branches at submission time —— Although this is very useful , But that means they don't really practice continuous integration .( For them , A better name might be the continuous build tool ). Because of this Semantic diffusion , Some people began to use ” Backbone based development “ Use this term instead of ” Continuous integration “.( Some people do make a subtle distinction between the two terms , But there is no consistent usage .) Although I am usually a descriptorist in language , But I prefer to use ” Continuous integration “. Part of the reason is that I don't think constantly coming up with new terms is a feasible way to combat semantic diffusion . However , Perhaps the main reason is , I think changing the terminology will rudely erase the contribution of the early pioneers of extreme programming , especially Kent Beck, He was in 20 century 90 The s created and clearly defined the practice of continuous integration .

Compare functional branching patterns with continuous integration

Functional branching seems to be the most common branching strategy in the industry , But a group of practitioners with a voice think , Continuous integration is usually a better approach . The key advantage of continuous integration is that it supports higher , Usually a much higher integration frequency .

The frequency of integration varies depending on how small a team can make its functionality . If the functions of a team can be completed in one day , Then functional branching mode and continuation Chengdu are the ways they can execute . But the functional length of most teams is longer than this —— The longer the function length , The greater the difference between the two models .

As I have pointed out , The higher the integration frequency , The less complex the integration will be , And there will be less fear of integration . This is often a difficult thing to convey . If you live in a world where integration takes place only once every few weeks or months , So integration is likely to be a very disturbing activity . It may be hard to believe that this is something you can do many times a day . however , Integration is a kind of Use frequency to reduce difficulty Things about . This is a counter intuitive concept ——“ If the pain —— Just do it more often ”. however , The smaller the integration , The less likely they are to become an epic merger of pain and despair . The functional branching model advocates smaller functions : Days, not weeks ( Months of no longer exist ).

Continuous integration allows the team to gain the benefits of high-frequency Integration , At the same time, the function length is decoupled from the integration frequency . If a team prefers a functional length of one or two weeks , Continuous integration allows them to do this while , You can still get all the benefits from the highest integration frequency . Merge smaller , There is less work to deal with . what's more , As I explained above , Merge more frequently , Can reduce the risk of unpleasant mergers , This not only reduces the bad accidents , It also reduces the overall fear of merger . If there is a conflict in the code , High frequency integrations will quickly find them before they cause those annoying integration problems . These benefits are powerful enough , So that some team functions only take a few days , But still continuous integration .

The obvious disadvantage of continuous integration is , It lacks the closure of the climax integration to the main line . It's not just a loss of celebration , And for a team that is not good at keeping healthy branches, it will also be a risk . Putting all feature submissions together may also delay the decision whether to add a feature to an upcoming release . Even though feature flags Allows functions to be turned on or off from the user's perspective , But the code for this function is still in the product . Concerns about this are often exaggerated , After all, code has no weight , But this does mean that teams that want continuous integration must develop a strong set of testing guidelines , So they can be sure , Even if there are many integrations every day , The main line can still stay healthy . Some teams find this skill unimaginable , But others think it's both possible and liberating . This prerequisite does mean that the functional branching model is more suitable for branches that do not insist on health , And need a team to stabilize the release branch of the code before release .

Although the size and uncertainty of the merger are the most obvious problems of the functional branching model , But perhaps its biggest problem is that it prevents refactoring . When refactoring occurs regularly with less friction , Refactoring is the most effective . Refactoring introduces conflicts , If these conflicts cannot be quickly detected and resolved , Merger will become difficult . therefore , Reconfiguration works best in high frequency integration , So it acts as Extreme programming (xp) It's not surprising that some of them have become popular ( Extreme programming also takes continuous integration as one of the original practices ). The function branching pattern also prevents developers from modifying parts of functions that are not being built , This undermines the ability of refactoring to stabilize and improve the code base .

When I come across scientific research on software development practice , Because there are serious problems with their methods , I'm usually not convinced . One exception is State Of Dev Ops Report, The report establishes indicators of software delivery performance , They relate it to broader organizational performance measures , This criterion is in turn related to business indicators such as return on investment and profitability .2016 year , They evaluated continuous integration for the first time , Found that it helps to improve software development performance , This finding was repeated in every subsequent survey .

We found that , Before being merged into the trunk , To branch or bifurcate (fork) The life cycle of is very short ( Less than a day ), And there are less than three active branches in total , These are important aspects of continuous delivery , And both help improve performance . Merge code into every day thunk or master So it is with .

——State of DevOps Report 2016

Using continuous integration does not eliminate other advantages of keeping functionality small . Frequent release of widgets provides a quick feedback cycle , This is very helpful to improve the product . Many teams using continuous integration also strive to build thin products , And release new features as often as possible .

 Function branch mode
All code in a function can be evaluated as a unit
The function code will be added to the product only after the function is completed
Lower frequency merging
Continuous integration
Support higher frequency integration than function length
Less time to find conflicts
Smaller mergers
Encourage refactoring
A commitment to keep the branch healthy ( So you need to test your code )
Scientific evidence shows that it helps to improve software delivery performance
 Copy code 

Functional branching pattern and open source

Many people attribute the popularity of the functional branching model to GitHub And from open source development pull-request Model . In view of this , We need to understand the huge difference between open source work and many commercial software development . Open source projects have many different structures , But a common structure is that a person or a small group acts as a maintainer , Do most of the programming . Maintainers work with a larger group of programmers as contributors . Defenders often don't know contributors , So there is no expectation of the quality of the code they contribute . Defenders are not sure how much time contributors will devote to their work , Not to mention their efficiency in completing the work .

under these circumstances , The functional branching model is of great significance . If someone wants to add a large or small function , And I don't know when it ( Or Yes No ) Will complete , So it makes sense to wait for it to complete before integration . Besides , More importantly, be able to review the code , To make sure it passes any quality thresholds I set for the code base .

But many commercial software teams have a very different working environment . They will have a full-time team , These teams will focus on Software . The project leader knows these people well ( Except when they first started ), And you can have a reliable expectation of code quality and delivery capability . Because they are paid employees , Leaders also have greater control over the time invested in the project, coding standards and team habits .

Pull Requests In my submission pull requests Is designed to support Function branch mode and Pre integration review The combination mechanism of . Decide whether and how to use pull requests, I will first think about the role of those underlying patterns in team workflow .

Given this very different environment , It should be clear that , The branching strategy of the business team does not need to be the same as that operating in the open source world . Continuous integration is almost impossible for temporary contributors to open source work , But it is a realistic choice for business work . Teams should not assume that effective methods in open source environments are automatically correct for their different environments .

Pre integration review *

Each submission to the main line is subject to peer review before being accepted (peer review).

For a long time , Code review has always been encouraged as improving code quality 、 Improve modularity 、 Readability and a way to eliminate defects . For all that , Business organizations often find it difficult to adapt to the workflow of software development . However , This idea is widely adopted in the open source world : Contributions to projects should be reviewed before accepting them into the main line of the project . This method has been widely spread in development organizations in recent years , Especially in Silicon Valley . A workflow like this is similar to GitHub Of pull-requests The mechanism is particularly suitable .

When Scarlett Completed a large piece of work she wanted to integrate , This workflow begins . Once she succeeds in building , She just Mainline integration ( Suppose her team practices like this ), But before she pushes it to the main line , She will send her submission for review . Other members of the team , such as Violet, The submission will be code reviewed . If she has questions about the submission , She will make some comments , Then back and forth , until Scarlett and Violet Satisfied with everything . Only when they're done , Submission will be put on the main line .

Pre integration reviews are becoming popular in open source , It fits well with the organizational model of dedicated maintainers and temporary contributors . It enables maintainers to pay close attention to any contribution . It can also communicate with Function branch mode Well combined , Because a completed function marks a clear node to do such code review . If you're not sure that a contributor is about to complete a function , Why review some of their work ? It's best to wait until the function is completed . This practice is also widely spread in larger Internet companies ,Google and Facebook Have established special tools to help such work go smoothly .

It is important to develop discipline for timely pre integration reviews . If a developer does something , Then go and do something else for a few days , So when the review feedback , This job is no longer his top priority . This is frustrating for a function that has been completed , It's even worse for a partially completed function , Because until the review is determined , It may be difficult to make further progress . In principle , It's going on Continuous integration It is possible to conduct a pre integration review at the same time , And it is also feasible in practice ——Google Just In this way . however , Although it is possible , But it's hard , It is also relatively rare . Pre integration reviews and functional branching patterns are more common combinations .

When to use it

Although pre integration review has become a popular practice in the past decade , But there are also shortcomings and alternatives . Even if you do well , The pre integration review will also introduce some delays in the integration process , And encourage lower integration frequency . Pair programming Provides a continuous code review process , There is a faster feedback cycle than waiting for code review .( Like continuous integration and refactoring , It is Extreme programming (xp) One of the original practices of .)

Camille Fournier: Questioning the value of mandatory code review is definitely the most popular underground belief held by senior engineers I know . Ian Nowland: I think mandatory censorship , And like asking for comments Every The purpose of the function is to do this , It is the envy and passion of enterprise engineers for open source / Or the worship of goods . Camille Fournier: Confuse the needs of open source software and private software development teams , Just like the original sin of the current software development ceremony .

Many teams that use pre integration reviews don't do it fast enough . The valuable feedback they can provide comes too late , So useless . under these circumstances , There was an awkward choice : It's a lot of rework , Or accept something that might work , But something that secretly destroys the quality of the code base .

Code review is not limited to before the code enters the main line . Many technical leaders have found that , It is useful to review code after a submission , When they find something worth noting , Can follow up with developers . At this time, reconstructing culture is of great value . If it's done well , This establishes a community , Everyone on the team regularly reviews the code base , And fix what they see .

The trade-offs around the pre integration review mainly depend on the social structure of the team . As I have already mentioned , Open source projects usually have a structure consisting of several trusted maintainers and many untrusted contributors . Business teams are usually full-time , But there may be a similar structure . Project leader ( Like a defender ) Trust a small part ( It may be a single ) Maintainer , And be vigilant about the code contributed by other members of the team . Team members may be assigned to multiple projects at the same time , This makes them more like open source contributors . If there is such a social structure , Then the pre integration review and functional branching pattern are of great significance . however , A team with higher credibility will often find that there is no friction in the integration process , Other mechanisms for maintaining high code quality at the same time .

therefore , Although pre integration review can be a valuable practice , But it is by no means a necessary path to a healthy code base , Especially if you want to develop a balanced , A team that does not rely too much on the original leader ,

Integrated friction

One of the issues of pre integration review , Yes, it often makes integration more cumbersome . This is an example of integrated friction ( Integration friction is an activity that takes time or effort to integrate ). The more integrated friction , The more developers prefer a lower integration frequency . Imagine , some ( Dysfunctional ) organization , They insist that all submissions to the main line fill out a form that takes half an hour . Such a system will prevent people from integrating frequently . Whatever your attitude towards functional branching patterns and continuous integration , It's valuable to check anything that increases this friction . Unless it significantly adds value , Otherwise any such friction should be removed .

Pull requests Increased overhead to deal with low trust situations , for example , Allow people you don't know to contribute to your project . take pull requests Impose on developers in your own team , It's like letting your family go through the airport security station and then enter your home .——Kief Morris

Manual operation is a common source of friction , Especially when it comes to coordination with different organizations . This friction can usually be achieved by using automated processes , Train developers ( To eliminate the need for this operation ), And push the steps back to Deployment pipeline or Production environment Medium QA Later steps to reduce . You can find more ideas to eliminate this friction in the materials of continuous integration and continuous delivery . This friction also occurs on the road to the production environment , With the same difficulties and methods .

One reason people are reluctant to consider continuous integration is , They may have only worked in environments with highly integrated friction . If each integration takes an hour , So it's obviously absurd to do it several times a day . Joining an integration team is a disappointment , Or a team that can be done quickly in a few minutes , It feels like a completely different world . I suspect that most of the arguments about the advantages of functional branching patterns and continuous integration are vague , Because people have not experienced both worlds at the same time , Therefore, we can't fully understand these two views .

Cultural factors can affect integration friction —— Especially the trust between team members . If I were the leader of a team , And I don't believe my colleagues will do well , Then I probably want to stop submissions that break the code base . Naturally , This is also one of the drivers of pre integration review . however , If I'm in a team where I trust the judgment of my colleagues , I may be more comfortable with post submission review , Or cut the censorship completely , Rely on common refactoring to clean up any problems . In this environment , My gain is to eliminate the friction caused by pre submission review , This encourages higher frequency integration . Usually , Team trust is the most important factor in the debate between functional branching model and continuous integration .

The importance of modularity

Most people who care about software architecture will emphasize the importance of modularity to a good system . If I'm faced with making a small change to a less modular system , I have to know almost everything about it , Because even a small change can affect many parts of the code base . However , With good modularity , I just need to know the code of one or two modules , And the interfaces of several other modules , And you can ignore the rest . This ability to reduce the difficulty of my understanding , That's why with the development of the system , The reason why it's worth so much effort on modularity .

Modularity also affects integration . If a system has good modules , So most of the time ,Scarlett and Violet Will work in separate parts of the code base , Their changes will not cause conflict . Good modularity also enhances things like Keystone Interface and Branch By Abstraction Technology like this , To avoid the need for isolation provided by branches . Usually , Teams are forced to use source code branching behavior , Because of the lack of modularity, they have no other choice .

The functional branching model is a poor modular architecture , Not built at runtime / A system that can be easily turned on and off during deployment , Instead, they couple themselves to source control , This mechanism is provided by manual merging . ——Dan Bodart

This support is two-way . Despite many attempts , But it's still very difficult to build a good modular architecture before we start programming . To achieve modularity , We need to keep observing as the system grows , And guide it in a more modular direction . Refactoring is the key to achieving this goal , Reconfiguration requires high-frequency integration . therefore , Modularity and rapid integration support each other in a healthy code base .

All this is saying , Modularity is difficult to achieve , But it's worth the effort . This effort includes good development practices , Learning design mode , And learn from the experience of the code base . Chaotic mergers should not be put aside because of an understandable desire to forget them , Instead, ask why mergers are chaotic . These answers are often important clues to how to improve modularity , This improves the health of the code base , So as to improve the productivity of the team .

Personal views on Integration Patterns

My purpose as a writer is not to persuade you to follow a specific path , It tells you the factors you should consider when deciding which way to go . For all that , I will still talk about which mode I prefer among the previously mentioned modes .

in general , I prefer to use Continuous integration Team work . I realize , Environment is the key , In many cases , Continuous integration is not the best choice —— But my reaction is to do something to change this environment . The reason why I have such a preference , Because I want to be in such an environment , Everyone can easily refactor the code base , Improve its modularity , Keep it healthy —— All this is to enable us to respond quickly to changing business needs .

These days I'm more of a writer , Not developers , But I still choose to Thoughtworks Work , There are many people in this company who agree with this way of working . This is because I believe in this Extreme programming (xp) Style is one of the most effective ways for us to develop software , I want to focus on the way the team further develops , To improve the efficiency of our industry .

Path from mainline to production release

The main line is an active branch , With the regular release of new and modified code . It's important to keep it healthy , So when people start a new job , They will start from a stable foundation . If it's healthy enough , You can also release code directly from the main line to the production environment .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/8db289f1fd4646e1b36d68be3d2989a0~tplv-k3u1fbpfcp-zoom-1.image

The philosophy of keeping the main line always releasable is Continuous delivery The core tenet of . Do that , Must have the determination and skills to maintain the main line as a Healthy branches , Usually there are Deployment pipeline (Deployment Pipelines) To support the required intensive testing .

Teams working in this way can usually pass in each release (version) Use tags on to track their releases (releases). But teams that don't use continuous delivery need another approach .

Release branch *

A branch that accepts only these submissions , That is why these submissions were accepted , To create a stable version of the product ready for release .

A typical publishing branch is copied from the current mainline , However, it is not allowed to add any new features on it . The main development team will continue to add functionality to the mainline , These functions will be put into future releases . Developers working on the release focus only on eliminating obstacles to production readiness for the release (production-ready) Any defects in . Any fixes to these defects will be created on the publishing Branch , And merge into the main line . Once there are no more defects to deal with , This branch can be used for production release (production release) 了 .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4a7cbe4bc580465a8e2f86009b580154~tplv-k3u1fbpfcp-zoom-1.image

Although the scope of work of the repair on the release Branch ( if only ) Smaller than the new function code , But over time , It will be more and more difficult to merge them into the main line . Branches inevitably differ , So as more and more submissions are made to modify the mainline , Merging publishing branches into the mainline is also becoming more and more difficult .

One problem with applying a commit to the publishing branch in this way is , It's too easy to forget to copy them to the main line , Especially because the occurrence of differences will become more difficult . The resulting regression (regression) It's very embarrassing . therefore , some people Support the creation of Submission on the mainline , Once they work on the main line , Then put them cherry-pick Publish on branch .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0cbc81c347cb40d981eb2c2542de19a7~tplv-k3u1fbpfcp-zoom-1.image

cherry-pick It refers to copying a commit from one branch to another , But the two branches do not merge . in other words , Only one submission is copied , Instead of all submissions since the branch point . In this case , If I put F1 Merge into publishing Branch , Then this will include M4 and M5. but cherry-pick Just take F1.cherry-pick It may not be fully applicable to publishing branches , Because it may depend on M4 and M5 Modification of .

Writing release fixes on the main line makes it more difficult for many teams , And it's frustrating , One way repair on the main line , Before publishing, you have to do the same work on the publishing Branch . When there is progress pressure on the release , This is especially true .

In a production environment, a team with only one version at a time only needs a single release Branch , But some products have many versions in production and use . Software running on the customer's Suite , Upgrade only if the customer wants to upgrade . Many customers are reluctant to upgrade , Unless there are new features that attract them , Because they were hurt by upgrade failure . However , Such customers still want bug fixes , Especially when it comes to safety . under these circumstances , The development team maintains open release branches for each version that is still in use , And repair it as needed .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cec746a9fda441e0a04876dbedf141bd~tplv-k3u1fbpfcp-zoom-1.image

As the development goes on , It becomes more and more difficult to repair the old version , But this is often the cost of doing business . This can only be mitigated by encouraging customers to upgrade to the latest version frequently . Maintaining the stability of the product is crucial to this , It will be difficult for customers who have been injured to be willing to upgrade unnecessarily .

( Other terms I've heard of the publishing branch include .“ Publish ready Branch (release-preparation branch)”、” Stable branches (stabilization branch)“、” Candidate branches (candidate branch)“、” Hardened branches (hardening branch)“. but ” Release branch “ Seems to be the most common .)

When to use it

When a team cannot keep its main line healthy , Publishing branches is a valuable tool . It allows a part of the team to focus on the necessary bug Repair , In order to prepare for production . Testers can pull the most stable and latest candidate version from the top of this branch (recent candidate). Everyone can see what has been done to stabilize the product .

Although publishing branches are valuable , But most good teams don't produce alone (single-production) Our products use this model , Because they don't have to . If you keep healthy enough , Then any submission to the mainline can be published directly . under these circumstances , The release should be marked with a publicly visible version and build number .

You may have noticed that I added in the last paragraph ” Single production “ This clumsy Adjective . This is because when the team needs to manage multiple versions in production , This model becomes crucial .

When there is significant friction in the release process , Publishing branches can also come in handy —— For example, there is a release committee that must approve all production versions . just as Chris Oldwood said :” When the gears of the enterprise rotate slowly , In these cases , The publishing branch acts more like an isolation zone “. Generally speaking , This friction should be eliminated from the release process as much as possible , Like we need to eliminate Integrated friction equally . However , In some cases , For example, mobile app store , Maybe not . In many cases, one label is enough , Only when there are some necessary changes to the source code do you need to open the branch .

The publishing branch can also be Environment Branch , The problem that needs attention also belongs to that model . There is another kind. Long term publishing branch A variation of the , I'll talk about it soon .

Mature branches *

A branch of the latest version whose header marks the maturity of the code base .

Teams often want to know what the latest version of the source code is , This fact can be complicated in a code base with different maturity . One QA Engineers may want to see the latest pre release of the product (staging) edition , A person who is debugging a production failure wants to see the latest production version .

Mature branches provide a way to do this . The idea is , Once a version of the code base has reached a certain level of preparation , It will be copied to a specific branch .

Consider a mature branch for production . When we prepare a production version , We will open a release branch to stabilize the product . Once it's ready , Let's copy it to a long-running production branch . I think it's a copy, not a merge , Because we want the production code to be exactly the same as the code tested on the upstream branch .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a0530051abd643e7806afa54ec5daa4f~tplv-k3u1fbpfcp-zoom-1.image

One of the charms of a mature branch is , It can clearly show the version of each code that reaches this stage in the release workflow . So in the example above , We just want one in the production branch that will M1-3 and F1-2 Combined submission . To do this requires several deceptive tricks of Supply Chain Management , But anyway , This has lost the connection with fine-grained Submission on the main line . These submissions should be recorded in the submission information , To help people track them later .

Mature branches are usually named after the appropriate stage in the development flow . So there is ” Production branch “、” Pre release branch (staging branch)“、”QA Branch “ Such claim . Occasionally I hear people call the mature branch of production ” Release branch (release branch)“.

When to use it

The source control system supports collaboration and tracking the history of the code base . Using mature branches allows people to , Through the historical version of a specific stage that appears in the publishing workflow , To get some small but important information .

I can view the header of the relevant branch , Find the latest version , For example, currently running production code . If there is one that I'm sure doesn't exist before bug, I can see what previous versions on this branch are like , Then look at the changes in the specific code base in production .

Automation can be linked to changes in specific branches —— for example , As long as the production branch has submitted , Automated processes can deploy a version to a production environment .

An alternative to a mature branch is to apply a tagging scheme (tagging scheme). Once a version is ready for QA, It can be marked as QA—— Usually in a way that includes a build number . therefore , When the version 762 Be ready for QA when , It can be marked as ”qa-762“, When ready for production , It can be marked as ”prod-762“. Then we can get the history by searching the tags in the code base that match our tag scheme . Automated hooks can also be assigned based on tags .

therefore , A mature branch can add some convenience to workflow , And many organizations find labels work very well . I see this as one of those models that have no strong benefits or costs . However , Usually , You need to use a source management system for such tracking , It's a team Deployment pipeline Poor performance of tools .

variant : Long term publishing branch

I can think of this as a variation of the publishing branching pattern , It is related to the release candidate (release candidate) Combined with mature branches of . When we want to release , We copy the mainline to this distribution branch . As with every publishing Branch , Commit on the publishing branch only for stability . These revisions will also be incorporated into the main line . We label it when we release it , When we want to do another release , You can copy the main line .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c27eb08f99c04de19ef2c54aae11dc3f~tplv-k3u1fbpfcp-zoom-1.image

Submissions can be copied or merged , As in the more typical mature branch . If it is merged , We must take care that the header of the publishing branch exactly matches the header of the mainline . One way to do this is , Before the merger ,revert All fixes applied to the mainline . Some teams will also merge squash Submit , To ensure that each submission represents a complete candidate version .( People who find this troublesome have good reasons to choose to cut a new branch for each release instead ).

This method is only suitable for products with only one single release at a time .

One reason the team likes this approach is , It ensures that the head of the publication branch always points to the next candidate publication , Instead of having to dig out the head of the latest release Branch . However , At least in the git in , We can set up a ” Release “ Branch names to achieve the same effect , When the team cuts out a new release Branch , The name of this branch will follow a hard reset Command to move , And leave a label on the old publishing Branch .

Environment Branch *

Submit through source code , Configure a product to run in a new environment .

Software usually needs to run in different environments , Such as the developer's workstation , Production server , There may also be various testing and pre release environments . Usually running in these different environments requires some configuration changes , For example, for accessing the database URL, The location of the messaging system and the location of key resources URL.

Environment branch refers to the branch that contains , Apply to the source code to reconfigure the submission of products running in different environments , The branch of . We may have a version 2.4 Running on the main line , Now we want to run it on our pre publisher . So , We started with version 2.4 Cut out a new branch , Make appropriate environmental changes , Rebuild the product , And deploy it to the pre release environment .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2ba29e680bd44030997578f34cbc7e5d~tplv-k3u1fbpfcp-zoom-1.image

  1. Branches for pre Publishing
  2. Configuration changes for the pre release environment

These changes are usually made manually , Although if the person in charge is right git be familiar with , They can learn from earlier branches cherry pick modify .

Environmental branching patterns are often associated with Mature branches Combination . A long-term QA Mature branches may include pairs of QA Configuration adjustment of environment . After merging into the environment Branch , We need to remove these configuration changes . similarly , A long-term release branch may also include these configuration changes .

When to use it

Environmental branching is an attractive approach . It allows us to adjust the application in any way , Prepare it for the new environment . We can save these changes in a diff in , So that it can be cherry-pick To future versions of the product . However , It's a Anti pattern A classic example of —— Some things look attractive when you start , But soon it will lead to a world full of pain 、 The world of dragons and coronaviruses .

If the behavior of an application changes as we move it from one environment to another , Then the danger will stand out . If we can't debug the version running in production on the developer's workstation , Then fixing the problem will become more difficult . We may introduce... That only occurs in a specific environment bug, The most dangerous is the production environment . Because of this danger , We want to make sure as much as possible that the code running in the production environment is the same as the code running elsewhere .

The problem with environmental branches is the super flexibility that makes them so attractive . Because we can be in those diff Modify any aspect of the code in , We can easily introduce configuration patches , This leads to different behaviors and subsequent bug.

therefore , Many organizations wisely adhere to an iron rule : Once an executable program is compiled , Then the same program should run in all environments . If different configurations are required , Then they must be isolated through some mechanism , Such as displayed configuration files or environment variables . such , They can be minimized to simple constant settings that do not change during execution , by bug The breeding of leaves less space .

The simple dividing line between executable and configuration can easily become very blurred in software that directly executes its source code ( for example ,JavaScript、Python、Ruby), But the same principle applies . Keep any environmental changes to a minimum , And don't use source branching behavior on it . The general rule of thumb is , Any version of the product you can check out , Should be able to run in any environment , So anything that changes purely due to different deployment environments should not be in source control . There is a debate about whether to store combinations of default parameters in source control , But each version of the application should be able to , Based on dynamic factors such as environment variables , Switch between these different configurations .

The environment branch is a branch that takes the source code behavior as The modular architecture of the poor Example . If an application needs to run in different environments , Then the ability to switch in different environments needs to be a first-class consideration in its design . For applications that lack this design , Environmental branching is useful as a mechanism to cut corners , But then priority should be given to removing it with a sustainable alternative .

Hot repair branch *

A branch used to capture the work of repairing emergency production defects .

If there is a serious problem in the production environment bug, Then it needs to be repaired as soon as possible . This bug Your repair priority will be higher than anything else the team is working on , And other work can not drag down the completion progress of this hot repair .

Hot fix work needs to be done in source control , So that the team can properly record and collaborate . They can open a branch on the latest release , And apply any changes for hot fix to this branch to do this .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c848b7c88457471eb476a938ac0c0b6e~tplv-k3u1fbpfcp-zoom-1.image

Once the fix is applied to the production environment , Everyone has a chance to sleep well , Thermal repair can then be applied to the mainline , To ensure that regression does not occur in the next release . If there is a release branch open for the next version , Then thermal repair also needs to be carried out on this branch . If the interval between two releases is too long , Then the hot fix is likely to build on the changed code , So it will be more difficult to fit into . In this case, you can expose bug A good test will be very helpful .

If a team uses a publishing Branch , The hot fix can be done on the release Branch , After that, a new version is ready . essentially , This turns the old release branch into a hot fix Branch .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1125f8ba741f459a9ede72eb9bc35df8~tplv-k3u1fbpfcp-zoom-1.image

Just like the publishing Branch , Hot repair can also be done on the main line , And then put them cherry-pick Publish on branch . But it's not common , Because thermal repair is usually done under great time pressure .

If a team implements continuous delivery , Then it can release the hot fix directly to the main line . They may still use a hot repair branch , But they will start with the latest submission , Instead of starting with the last release submission .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ffdc6b943f06493cae49eb80342fe45f~tplv-k3u1fbpfcp-zoom-1.image

I pasted the new version 2.2.1 The label of , Because if a team works this way , that M4 and M5 Probably won't expose new features . If they're exposed , Then the thermal repair may be folded into 2.3 edition . Of course , This shows that in continuous delivery , Hot fix does not need to avoid the normal release process . If a team has a responsive release process , Then thermal repair can be handled as normal —— This is an important benefit of continuously delivering ideas .

A special approach for continuous delivery teams is , It is not allowed to submit anything to the main line until the hot repair is completed . This is in line with “ No one has a more important task than repairing the main line ” This slogan —— in fact , This is true for any defect found on the main line , Even those defects that have not yet been put into production .( So I don't think this is really a special treatment .)

When to use it

Thermal repair is usually carried out under considerable pressure , And a team is most likely to make mistakes when it is under the greatest pressure . under these circumstances , Using source control is more valuable than usual , It also seems more reasonable to submit more frequently than usual . Let this work on a branch , Let us know what we are doing to deal with this problem . The only exception is that simple fixes can be applied directly to the mainline .

The more interesting question here is to judge what is the heat that needs to be repaired bug(hot bug), What can be left to be solved in the normal development workflow . The more frequently a team releases , The more it can save production bug fixes for the regular development rhythm . in the majority of cases , This judgment mainly depends on this bug Business impact , And how it matches the team's release frequency .

Release the train *

Publish at regular intervals , It's like a train starting on a regular schedule . When developers complete their functions , Choose a train to take .

The team using the release train will set a regular release rhythm , Like every two weeks or every six months . The date is based on when the team cuts out the release branch for each release , It's like a train timetable . People decide which train to take for one of their functions , And use that train to establish their work , When the train is loading, put their submission on the appropriate branch . Once the train leaves , The branch will be Release branch , And only accept repairs .

A team using monthly trains will be released in February , Open a branch for March . They will add new features as the month progresses . On a set date , Maybe the third Wednesday of the month , This train will leave —— Freeze the functions of this branch . They opened a new branch for the April train , And add new features to it . meanwhile , Some developers will stabilize the March train , Release it to production when it's ready . Any repair applied to the March train will be cherry-pick On the train to April .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2c0b760c937740c6ad4d04d9b6d07c4c~tplv-k3u1fbpfcp-zoom-1.image

Release trains often and Function branch mode Use it together . When Scarlett Feel when her function can be completed , She will decide what train to take . If she thinks she can finish it in the March release , She'll be integrated into the March train , But if not , She will wait for the next shift and integrate there .

Some teams use soft freeze a few days before the train leaves ( The departure of the train is hard frozen ). Once released, the train is in a soft frozen state , Then developers should not put their work on the train , Unless they are confident that their functionality is stable and ready for release . Anything added after soft freezing is bug All functions will be restored ( Push off the train ), Instead of repairing it on the train .

Recently, , When people hear “ Release the train ” when , They often hear from SAFe Of Agile release train The concept of .SAFe Agile release train is a team organizational structure , It refers to a team in a large team , It shares a common release train schedule . Although it uses the mode of releasing trains , But it's not the same as what I described here .

When to use it

A core concept of the release train mode is the regularity of the release process . If you know in advance when the train will leave , You can plan what functions to complete to take that train . If you think you can't finish your function before the train leaves in March , Then you know you'll catch the next shift .

When there is obvious friction in the release process , Releasing trains is particularly useful . An external test team takes weeks to validate a version , Or a release committee needs to agree on a new version of the product before it appears . If that's the case , It is usually wise to try to eliminate release friction , Allow more frequent releases . Of course , In some cases , It's almost impossible , For example, the verification process used by the app store on the mobile device . Adjust the release train to match such a release , May make the situation the best .

Releasing the train mechanism helps to focus everyone's attention on what functions should appear and when , This helps to predict the completion time of the function .

An obvious disadvantage of this method is , The function completed in the early stage of the train will sit on it and read while waiting for departure . If these functions are important , That means the product will miss an important function for weeks or months .

Release trains can be a valuable stage in improving the team's release process . If it's hard for a team to make a stable release , So jumping to continuous delivery may be too big . Pick an appropriate release cycle , A difficult but plausible cycle , It could be a good start . As the team learns skills , They can increase the frequency of trains , As their abilities grow , Finally abandon the train for continuous delivery .

variant : Loading future trains

A basic example of a functional train is when the previous train leaves , A new train arrives at the platform to carry the function . But another way is to let multiple trains receive functions at the same time . If Scarlett I don't think her function will be completed during the March train , She can push most of her completed functions to the April train , And push the submission one step ahead of the train to complete it .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0f4b58847a2c44a188426b28e050a268~tplv-k3u1fbpfcp-zoom-1.image

Every once in a while , We'll take the train from March to April . Some teams like to do this when the train leaves in March , So they only need to merge once , But those of us who know that small-scale mergers can be exponentially easier hope to pull the submission of each March as soon as possible .

Loading future trains allows developers who are developing April features to cooperate , Without affecting the work on the March train . Its disadvantages are , When the changes made by people in April conflict with the work in March , People in March don't get feedback , This makes future mergers more complex .

Compare with the pattern of regular release

One of the main benefits of releasing trains is the regular rhythm of release to production . But setting up multiple branches for new development adds complexity . If our goal is to publish regularly , We can also use the main line to achieve this goal . Decide what the release schedule is , Then, based on this schedule, cut a release branch from the tip of the main line .

https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a410b58bcf164a8daab652d7cf726ea8~tplv-k3u1fbpfcp-zoom-1.image

If there is a Release ready mainline , You don't need a publishing Branch . For regular releases like this , If it is before the regular release date , Developers can still choose not to push to the main line , Shelve the near - finished functionality for the next release . about Continuous integration , If people want a feature, wait until the next regular release , Then they can always place by delay keystone Or let one feature flag Close to achieve this .

Release ready mainline *

Keep healthy enough , Make the head of the main line (head) It can always be put directly into the production environment .

When I started this part , As I said , If you turn the main line into a healthy Branch , And let the health examination reach a sufficient height , Then you can release directly from the main line whenever you like , And use labels to record the version .

https://martinfowler.com/articles/branching-patterns/mainline-release.png

I've spent a lot of time describing alternative patterns for this simple mechanism , So I think it's time to emphasize this mechanism , Because if a team can practice it , It would be a great choice .

Every submission applied to the mainline can be published , But that doesn't mean it should be released . This is it. Continuous delivery and Continuous deployment The subtle difference between . Teams using continuous deployment will release each change as the mainline receives it , But in continuous delivery , Although every change is releasable , But whether to publish or not depends on the business .( therefore , Continuous deployment is a subset of continuous delivery .) We can think that continuous delivery gives us the option to release at any time , Our decision to implement this choice depends on the broader issue .

When to use it

Except as Continuous delivery Part of Continuous integration , The main line of release readiness is also a common feature of efficient teams . In view of this , And my well-known passion for continuous delivery , You might think , I would say that the release ready mainline is always better than the alternatives I described in this section .

However , The pattern depends on the situation . A good pattern in one case can be a trap in another . The effectiveness of the release ready mainline is determined by the team Integration frequency Decisive . If the team uses Function branch mode , And usually only one new function is integrated once a month , Then the team is likely to be in a bad situation , Sticking to the release ready mainline may actually hinder their promotion . The bad thing is that they can't respond to changing product needs , Because the cycle from idea to production is too long . They may also have complex merging and validation , Because every function is big , Can lead to many conflicts . These things may appear during integration , Or it's a kind of continuous consumption when developers pull the main line to their functional branches . This drag hinders refactoring , Hindering refactoring reduces modularity , This has exacerbated the seriousness of the problem .

The key to getting out of this trap is to improve the integration frequency , But in many cases , It can be difficult to do this while maintaining the release ready mainline . under these circumstances , Abandon the release ready mainline , Encourage more frequent Integration , And use Release branch To stabilize the main line for production , It's often better . Of course , as time goes on , We hope to eliminate the need for publishing branches by improving the deployment pipeline .

In the environment of high frequency integration , The release ready mainline has the obvious advantage of simplicity . Don't worry about the complexity of the various branches I describe . Even thermal repair can be applied to the main line , Then apply it to production , Make them no longer special enough to have a name .

Besides , Keeping mainline releases ready encourages a valuable discipline . It puts production readiness at the top of the developer's mind , Ensure that the problem does not gradually invade the system , No matter what it is bug Or as a process problem that slows down the product cycle . All disciplines for continuous delivery —— Developers integrate it many times a day without breaking the mainline —— It seems to be a daunting difficulty for many people . However , Once realized and become a habit , The team will find that it significantly reduces stress , And it's relatively easy to keep . That's why it's Agile Fluency Model Of Delivery area (delivering zone) A key factor in .

Other branching modes

The purpose of this article is to discuss the patterns around team integration and the path to production . But I also want to mention some other patterns .

Experimental branch *

Collect the experimental work in the code base , These efforts are not expected to be directly integrated into the product .

The experimental branch is used by developers to try some ideas , But I don't want their changes to be simply integrated back into the main line . I may have found a new library , I think it can be a good substitute for a library we are using . To help me decide whether to replace , I opened a branch , And try to use it to write or rewrite relevant parts of the system . The purpose of the job is not to contribute code to the code base , It's about understanding the applicability of a new tool in my specific context . I can do it alone , You can also do it with some colleagues .

similarly , I have a new function to implement , You can see there are several ways to get close to it . I spent a few days studying each method to help me decide which one to adopt .

The key point here is , We would expect the code on the experimental branch to be discarded , Will not merge into the main line . It's not absolute —— If I happen to like the result , And the code can be easily integrated , Then I won't ignore this opportunity —— But I don't expect this to happen . I may not follow some usual habits so much , Less testing , Some random code repetition , Instead of trying to refactor it clean . I hope , If I like this experiment , I'll apply this idea to production code from scratch , Use the experimental branch as a reminder and guidance , But don't use any of these submissions .

Once I've done my work on an experimental branch , stay git I usually add a label in , Then delete the branch . The label keeps the code line , In case I revisit it later —— I use a convention , For example, label the name with “exp” start , To clarify its nature .

When to use it

Whenever I want to try something , But when you're not sure if you'll eventually use it , The experimental branch is very useful . such , I can do anything I like , No matter how strange , I can put it aside with confidence and ease .

Sometimes I think I'm doing routine work , But I finally realized that what I did was actually an experiment . If this happens , I can open a new experimental branch , And reset my main work branch to the last stable submission .

Future branches *

A single branch , It exists for changes that are too aggressive to deal with by other means .

This is a rare pattern , But when people use continuous integration, there are occasional . occasionally , A team needs to make a very intrusive change to the code base , And for integrating ongoing work (work-in-progress) The usual techniques are not applicable . under these circumstances , The team will do something that looks like a functional branching pattern , They cut out a future branch , And pull only from the main line , We didn't do mainline integration until the end .

The biggest difference between the future branch and the functional branch is that there is only one future branch . therefore , People who work on future branches will never deviate too far from the main line , And there will be no other forked branches to deal with .

There may be some developers working on future branches , under these circumstances , They continue to integrate on future branches . When doing Integration , They first pull the main line to the future branch , Then integrate their changes . This will slow down the integration process , But this is the price of using future branches .

When to use it

I should stress that this is a rare pattern . I suspect that most teams implementing continuous integration never need to use it . I've seen it used to make particularly aggressive changes to the architecture in the system . Generally speaking , This is the last resort , Only when we can't figure out how to use something like Branch By Abstraction Will be used only when .

Future branches should still be kept as short as possible , Because they create a partition in the team , Just like partitions in any distributed system , We need to keep them to an absolute minimum .

Collaboration Branch *

A branch for developers to share work with other team members without formal integration .

When a team uses Thread when , Most collaboration takes place through the main line . Only when Mainline integration occurs , The rest of the team will see what a developer is doing .

Sometimes a developer wants to share their work before integration . Open a branch for collaboration , They can do this on a temporary basis . This branch can be pushed to the team's central warehouse , Collaborators can pull and push... Directly from their personal warehouse , Or set up a short-term warehouse to deal with cooperation .

Collaboration branches are usually temporary , Once the work is integrated into the main line, it will close .

When to use it

Collaboration branches become more useful as integration frequency decreases . If team members need to coordinate some changes to code areas that are important to some people , Then long-term functional branches often require informal collaboration . And one uses Continuous integration Your team will probably never need to open a collaboration branch , Because their work is invisible to each other for a very short time . The main exception to this is Experimental branch , According to the definition , It will never be integrated . If several people do an experiment together , They need to make this experimental branch a collaborative Branch .

Team integration branch

Before integration with the mainline , Let a sub team integrate with each other .

Larger projects may have several teams working on a single logical code base . A team integration branch can integrate with all members of the project without using the mainline , Let team members integrate with each other .

In fact, the team sees the team integration branch as the internal main line , Integrate with it , Just as they will integrate with the main line of the overall project . In addition to these integrations , The team will also make additional efforts to integrate with the project main line .

When to use it

The most obvious motivation for using the team integration branch is the code base actively developed by many developers , And it makes sense to divide these developers into different teams . But we should be wary of this assumption , Because I've met a lot of teams , They seem too big to work together on a single main line , But I managed to do it .( I have reported on this team of up to 100 developers .)

A more important driving force for using the team integration branch is the difference in the expected integration frequency . If the project as a whole wants the team to use functional branches that are weeks long , But sub teams prefer continuous integration , Then the team can establish a team integration branch , Use this branch for continuous integration , Once the functionality they are working on is complete , Just integrate it with the main line .

If used for Health Branch There are differences between the standards used by the overall project and the health standards used by the sub teams , A similar effect will occur . If the larger project cannot maintain the main line at a sufficiently high degree of stability , Then the sub team may choose to operate at a more stringent health level . Again , If the sub team struggles to make its submission healthy enough , To achieve a well controlled main line , They may choose to use the team integration branch , And use your own release branch to stabilize the code before entering the main line . This is not what I usually like , But some particularly difficult situations may be necessary .

We can also think of the team integration branch as a more structured form of the collaboration Branch , It is based on formal project organization rather than ad hoc collaboration .

Some branching strategies

Git-Flow

Git-Flow It has become one of the most common branching strategies I have encountered . It is from Vincent Driessen stay 2010 Written in , Appear in the git When it came to fashion . stay git In the days before , Branching patterns are often seen as a high-level topic .Git Make the branch more attractive , Part of the reason is the improvement of tools ( For example, better file movement processing ), But also because a repository of clones is essentially a branch , Similar thinking about consolidation is needed when pushing back to the central warehouse .

Git-Flow In a single “origin” Used in the warehouse Thread ( Call it “develop”). It USES Function branch mode To coordinate multiple developers . Developers are encouraged to use their personal repository as Collaboration Branch To work with developers doing similar work .

Traditionally git The core branch of is called “master”, stay Git-Flow in ,master As a production Mature branches To use .Git-Flow Use one Release branch To get work from “develop” Pass it to “master”. Thermal repair is through Hot repair branch To organize the .

Git-Flow There is no discussion about the length of functional branches , Therefore, we don't expect the content about integration frequency . It also doesn't mention whether the main line should be a Health Branch , If so , How healthy do you need . The existence of the publishing branch means that it does not have a Release ready mainline .

just as Driessen As pointed out in the appendix this year ,Git-Flow It is designed for projects that release multiple versions in production , For example, software installed at the customer site . Of course , Having multiple active versions is one of the main incentives to use the publishing Branch . However , Many users are in a single production environment webapp I chose Git-Flow—— Such a branching structure can easily become more complex than needed .

Even though Git-Flow Very popular , It seems that many people say they are using it , But often find those who say they're using Git-Flow People are actually doing something completely different . Usually , Their actual practice is closer to GitHub Flow.

GitHub Flow

Even though Git-Flow It's really popular , But its branching structure is for web There is unnecessary complexity for applications , So there are many alternatives . With GitHub The popularity of , The branching strategy used by its developers ( be called GitHub Flow) It's not surprising to become famous .Scott Chacon To make the Best description .

With GitHub Flow Such a name , Not surprisingly , It is deliberately based on and confrontation Git-Flow. The essential difference between the two lies in the different types of applicable products , This means different usage scenarios , So the pattern is different .Git-Flow It is assumed that the product has multiple versions in production . and GitHub Flow It is assumed that the product has only a single version in the production environment , And will frequently report to Release ready mainline Upper integration . under these circumstances , Release branch It's no longer necessary . Production problems are fixed in the same way as regular functions are developed , So no need Hot repair branch , Because the hot repair branch usually means a deviation from the normal process . Removing these branches greatly simplifies the branch structure , The main line and functional branches remain .

GitHub Flow Call the main line “master”. Used by developers Function branch mode Work on . They regularly push functional branches to the central warehouse , To provide visibility , However, the function branch will not be integrated into the main line until it is completed .Chacon Pointed out that , The functional branch may only have one line of code , It may also run for a few weeks . This process works in the same way in both cases . As GitHub,pull-request The mechanism is Mainline integration Part of , And will use Pre integration review .

Git-Flow and GitHub Flow Often confused , So as always , Dig deep behind the name to understand what happened . The general theme of both is the use of mainlines and functional branches .

Trunk-Based Development( Backbone based development )

As I wrote before , Most I hear “trunk-driven development( Development of trunk driver )” It is often used as a synonym for continuous integration . But put Trunk-Driven Development See as Git-Flow and GitHub Flow The alternative branching strategy is also reasonable .Paul Hammant Wrote a Deep web site To explain this method .Paul It's me. Thoughtworks Long term colleagues , He uses his reliable blade to defuse the rigid branch structure of customers , And has a solid record .

Trunk-Based Development Focus on Thread ( be called “ The trunk (thunk)”, yes “ Thread (mainline)” A common synonym for ) Do all the work on , Thus avoiding any form of long-term branching . Smaller teams use Mainline integration Submit directly to the main line , Larger teams may use short-term Function branch mode , among “ short-term ” It means no more than a few days —— In practice, this may be similar to Continuous integration almost . Teams can use Release branch ( be called “ Branches for publishing ”) or Release ready mainline (“ Publish from the trunk ”).

Final thoughts and recommendations

Start with the earliest program , People find out , If they want a program that is a little different from the existing program , You can get a copy of the source code , Then adjust it to the desired shape to easily do . With all the source code , I have the ability to make any change I want . But as this behavior goes on , My copy is more difficult to accept the new functions and bug fixes in the original source code . Final , It may become impossible , As many enterprises in their early COBOL As found in the program , And in today's extensive customization ERP Suffering in the bag . Even if you don't use that name , Any time we copy the source code and modify it , We are all doing Source code branching behavior , Although there is no version control system involved .

As I said at the beginning of this long article : Creating branches is easy , Merging is more difficult . Branching is a powerful technology , But it reminds me of goto sentence 、 Global variables and concurrent locks . Powerful 、 Easy to use , But it's easy to overuse , They often become traps for careless and inexperienced people . Source control systems can help control branching behavior by carefully tracking changes , But in the end, they can only be witnesses to the problem .

I'm not a person who can say that branches are evil . On some daily issues , For example, multiple developers contribute to a single code base , It is necessary to use branches wisely . But we should always be vigilant against it , And remember Paracelsus The observation of : The difference between a good medicine and a poison is the dose .

therefore , My first suggestion for branching is : Whenever you consider using a branch , Figure out how you will merge . Any time you use any technology , You are weighing alternatives . If you don't understand all the costs of a technology , You can't make a wise trade-off decision , In branching behavior , When you merge , The piper will charge her .

therefore , The next guide is : Make sure you understand the alternatives to branching , They are usually better . remember Bodart The law of , Is there a way to solve your problem by improving modularity ? Can you improve your deployment pipeline ? Is one label enough ? What changes to your process would make this branch unnecessary ? It is likely that actually branching is the best route now —— But it's a reminder that you have a deeper , The smell of problems that should be solved in the coming months . Getting rid of the need for branching is usually a good thing .

remember LeRoy Illustration of : As the work goes on , Without integration , Branches will vary exponentially . So consider the frequency of your integration branches . Strive to double your integration frequency .( There is obviously a limit here , But unless you're in Continuous integration Region , Otherwise you won't get close to it .) There are some obstacles to more frequent Integration , But these obstacles are often exactly what needs to be given excessive explosives , Something to improve your development process .

Because merging is the hardest part of branching behavior , So pay attention to what makes merging difficult . Sometimes it's a process problem , Sometimes it's because of architecture failure . No matter what , Don't give in to Stockholm Syndrome . Any merger issues , Especially the problems that led to the crisis , It is a signpost to improve the efficiency of the team . remember , Only when you learn from your mistakes , Mistakes are valuable .

The pattern I describe here outlines the common branch configurations that my colleagues and I encountered on the trip . I want to name them 、 explain , And most importantly , Explain when they are useful , To help you assess when to use them . please remember , Just like any model , They are rarely universal, good or bad —— Their value to you depends on your environment . When you encounter a branching strategy ( Whether it is well known, such as Git-Flow or Trunk-Based Development, Or something created in the development organization ) when , I hope understanding the patterns will help you decide whether they are suitable for your situation , And what other patterns to mix in will help .

Acknowledgement

Badri Janakiraman、Brad Appleton、Dave Farley、James Shore、Kent Beck、Kevin Yeung、Marcos Brizeno、Paul Hammant、Pete Hodgson and Tim Cochran Read the draft of this article , And gave me feedback on how to improve .

Peter Becker Remind me ,forks It's also a form of branching . I started from Steve Berczuk Of 《 Software configuration management mode 》 We have achieved “ Thread ” The name .

Extended reading

There is a lot of material about branching , I can't seriously investigate all the materials . But I do want to emphasize Steve Berczuk The book of :《 Software configuration management mode 》.Steve And his contributors Brad Appleton Works , It has had a lasting impact on the way I think about source management .

Major revisions

2021 year 1 month 4 Japan : Added about pull requests Sidebar for .

2021 year 1 month 2 Japan : take 《 Submitted for review 》 Renamed as 《 Pre integration review 》, I think it's a clearer name .

2020 year 5 month 28 Japan : Published the last chapter .

2020 year 5 month 27 Japan : Published 《 Some branching strategies 》.

2020 year 5 month 21 Japan : Published 《 Collaboration Branch 》 and 《 Team integration branch 》.

2020 year 5 month 20 Japan : Drafted the final thinking .

2020 year 5 month 19 Japan : Published 《 Future branches 》.

2020 year 5 month 18 Japan : Published 《 Experimental branch 》.

2020 year 5 month 14 Japan : Published 《 Release ready mainline 》.

2020 year 5 month 13 Japan : Drafted a chapter on branching strategy .

2020 year 5 month 13 Japan : Published 《 Release the train 》.

2020 year 5 month 12 Japan : Published 《 Hot repair branch 》.

2020 year 5 month 11 Japan : Drafted 《 Release ready mainline 》.

2020 year 5 month 11 Japan : Published 《 Environment Branch 》.

2020 year 5 month 7 Japan : Published 《 Mature branches 》.

2020 year 5 month 6 Japan : Published 《 Release branch 》.

2020 year 5 month 5 Japan : Published 《 Integrated friction 》《 The importance of modularity 》 as well as 《 My personal thoughts on Integration Patterns 》.

2020 year 5 month 4 Japan : Published 《 Submitted for review 》.

2020 year 4 month 30 Japan : Published 《 Continuous integration vs. functional branching 》.

2020 year 4 month 29 Japan : Published 《 Continuous integration 》.

2020 year 4 month 28 Japan : draft : Added a section on modularity .

2020 year 4 month 28 Japan : Published 《 Integration frequency 》.

2020 year 4 month 27 Japan : draft : General 《 Production branch to mature branch 》.

2020 year 4 month 27 Japan : Published 《 Function branch mode 》.

2020 year 4 month 23 Japan : Published 《 Mainline integration 》.

2020 year 4 month 22 Japan : Published 《 Healthy branches 》.

2020 year 4 month 21 Japan : Published 《 Thread 》.

2020 year 4 month 20 Japan : Published the first chapter :《 Source code branching behavior 》.

2020 year 4 month 5 Japan : The Fifth Draft : Handled the review comments on the release mode , Prepared the release plan , Revised source code branching behavior .

2020 year 3 month 30 Japan : Fourth draft : Handled most of the review comments on the basic and integration parts . Make source code branching a pattern .

2020 year 3 month 12 Japan : Third draft : Rewrite the mode to a special chapter .

2020 year 3 month 5 Japan : Second draft : Reorganize text into integration mode and path to production . Added illustrations for publishing branches and hot fixes , And rewritten the text to match it .

2020 year 2 month 24 Japan : First draft : Share with reviewers .

2020 year 1 month 28 Japan : Start writing .

Translated in 2021 year 8 month 6 Japan , Some of the content may change over time .

版权声明
本文为[ryougifujino]所创,转载请带上原文链接,感谢
https://fheadline.com/2021/08/20210809160327212O.html
相似文章

2021-08-09