Introduction to Bran-ching in Per-force

Perforce分支管理
本文介绍了Perforce版本控制系统中的分支管理机制,包括基本概念、术语解释、如何创建分支、分支规格等,并提供了几种标准的仓库结构建议。

 

by Robert Cowham, Perforce Consulting Partner

 

http://www.vaccaperna.co.uk/scm/branching.html

 

 

Introduction

 

This web page gives an introduction to Perforce branching mechanisms and explains some aspects that may not be obvious at first sight (well they weren't to me anyway!).

This page gives some additional information to Perforce branching mechanisms.

Other references are given at the bottom of this page.

 

 

Branching introduction

 

Perforce's basic mechanism, Inter-File Branching is described on their web page. The main feature is that branches of files are indicated by changing one or more elements of the depot pathname (or location in the Perforce repository), and this change is done by creating a virtual copy of the file using the integrate command.

 

Examples of this are:

 

//depot/main/jam/jam.c

//depot/r1.0/jam/jam.c

 

or

 

//depot/main/jam/...

//depot/r1.0/jam/...

 

for complete trees of files.

 

The component of the depot path that has been modified is "main" and "r1.0" respectively. In this example, we deduce ("elementary my dear Watson") that the version of jam.c in r1.0 is related to a specific version of the same file in main, and indeed that the r1.0 version was released as part of Release 1.0 for the Jam product.

 

This brings up a key point - you can branch a file from anywhere in the repository to anywhere else. Perforce is clever - it will keep track of what is related to what however complex that relationship. But to keep our lives simpler we need to come up with appropriate conventions so that we can easily "see" the relationships when we are browsing the repository (the KISS principle). Like most computer programs Perforce is stupid enough to do exactly what we tell it to do as opposed to what we meant it to do.

 

 

Terminology Warning...

 

There are some words that Perforce uses somewhat (!) ambiguously (most notably using the word "client" when "workspace" is meant (please change this Perforce even though it's a pain to do - it will make training and support much easier...), and "branch" is one of them. This means any one of:

  • a codeline (most likely meaning when used as a noun)
  • a branch view specification (as in the entity created by "p4 branch" command - also a noun) - these are talked about below
  • when used as a verb ("to branch") it means to use the "p4 integrate" command to create a new codeline (or branch!) of one or more files

Usually it is fairly obvious what is meant once you are comfortable with the 3 alternatives, and to test your understanding I will use them interchangeably below...

 

 

 

Noddy1 creates his first branch --- Very good and important example!!!!

 

Noddy has some code sitting in //depot/main/jam/... which he wants to branch into a release codeline for maintenance purposes. During the creation of his new branch the files in //depot/main/jam/... are the "source" files and the "target" files are somewhere else in the repository (//depot/r1.0/jam/... in this instance).

So he does the following:

  • Use "p4 client" and checks that his client workspace view mapping includes the "source" and "target" of his intended branch.
  • Runs "p4 integrate <source files> <target files>"
  • Runs "p4 submit" to submit changes to the repository after which point they become visible to other people.

E.g.

 

1. p4 client shows:

View:
    //depot/main/jam/...   //client/main/...

so he changes this to:

View:
    //depot/main/jam/...   //client/main/...
    //depot/r1.0/jam/...   //client/r1.0/...

 

There is a gotcha in this example - what happens if your mapping originally had //client/... on the right hand side (no "main"). Well remember that if you change the mapping and do a "p4 sync" Perforce will delete all the old files and move them down one level to underneath "main". Make sure you do not have any files opened for editing or similar when you do this.

 

2. He runs the integrate command which actually does most of the work:

p4 integrate //depot/main/jam/... //depot/r1.0/jam/...

Note that this also copies all the files into his client workspace.

 

3. He submits his changes and the new branch is visible in the repository to everyone.

p4 submit

 

 

 

Behind the Scenes

 

Remember that when you branch a set of files, although it appears that Perforce is copying all the files, (e.g. there are 1,000 files in //depot/main/... and it appears as if there are now another 1,000 files in //depot/r1.0/..., giving 2,000 in total), that the newly branched files are just virtual copies. Perforce has duplicated the metadata in its database to say that all the //depot/r1.0/... files now exist, but they are just pointers to specific version of the real files in //depot/main/....

Behind the scenes, the //depot/main/... files actually have RCS format archives (for text files) to store all the details about the contents of each revision (binary files are normally stored as a compressed version of each revision - see "p4 help filetypes" for more information). The files in //depot/r1.0/... only acquire their own archive file on the server when they are modified (p4 edit and then submit). Thus for typical situations where you branch 1,000 files and yet change less than 100, you only get less than 100 new archive files on the server.

 

 

Branch Specs

 

Branch specs are created using the p4 branch command. --- Very important paragraph!!!

The key thing to remember about them is that they are only a shorthand - creating a branch spec does not branch files from its source to its target. Files are actually branched when you use a branch spec with the integrate command - it's the integrate command which does the work (not the branch command).

 

Branch specs are particularly useful when you have multi-line views - they save lots of typing, getting things wrong, forgetting about things etc.

 

Remember that you can always delete branch specs and yet the work that was done with them (using the integrate command) remains done, even after the branch spec has been deleted (they are similar to client workspace specs in this regard). I recommend that people do delete the branch specs when they are no longer needed because if they aren't there, people can't accidentally use the wrong ones - it's always wise to remove temptation from your users...

 

 

Branch Spec Directions

 

Branch specs have a direction (source -> target). You can use the branch spec and reverse the direction with the -r flag (see below).

 

One thing lots of people do is to create a branch spec for a release branch such as:

Branch:    r1.0
View:
    //depot/main/jam/...   //depot/r1.0/jam/...

 

They then normally only make bug fixes to the r1.0 branch and propagate them back to main and almost never in the reverse direction. This means that they always need to use the -r flag:

p4 integrate -r -b r1.0

 

Why not create the branch spec the "wrong" way round for its first usage (to create the branch):

View:
    //depot/r1.0/jam/...   //depot/main/jam/...

 

and then you will not need to use the -r flag in most subsequent uses because you are always going from r1.0 back to main.

 

Don't forget the branch
component in depot path!

 

It is generally a good idea to have at least one component of the depot pathname as your "branch indicator". In the examples above the "main" or "r1.0" components were the indicator.

Sometimes people rush in and add a whole set of files to the depot without thinking about branching in future. For example adding source files to //depot/jam/... instead of //depot/jam/main/... (or similar). If you do this then you may have problems in the future when it comes to creating new branches for these files - what should the naming convention be?

 

 

Some Standard Depot Structures --- branch naming standard

 

So at this point we have covered some of the basics of the details of branching. The thing we haven't touched on is some of the alternative depot structures that are possible and why one might be better than another (in some situations at least).

 

Standard Release Branches - Indicator first

 

As already covered above, there are some very simple and yet effective structures for basic release purposes. E.g.

//depot/main/jam/...

 

is branched to:

//depot/r1.0/jam/...
//depot/r1.1/jam/...

 

This is very straight forward and easy to understand. One potential drawback, is what happens if we have many releases - well we would tend to clutter up the directory naming convention under //depot. An option might be:

//depot/main/jam/...

 

is branched to:

//depot/release/r1.0/jam/...

//depot/release/r1.1/jam/...

 

 

Standard Release Branches - Indicator Second

 

If we have many products each of which we want to branch independently, then we could do something like:

//depot/productA/main/...

 

is branched to:

//depot/productA/r1.0/...
//depot/productA/r1.1/...

or:

//depot/productA/release/r1.0/...
//depot/productA/release/r1.1/...

 

as we prefer.

 

There is no particular difference, but it might make things easier if we distinguish between the different products and don't mix them up (as they might be when indicator came first).

 

Indicator first (again) --- 2008-12-18 reading to here..

Another alternative which is useful when people have development branches (either team or personal) is:

//depot/main/productA/...

//depot/release/productA/r1.0/...
//depot/release/productA/r1.1/...

//depot/dev/personal/Fred/productA/...
//depot/dev/team/blue_team/productA/...

One advantage of this is that the first component of the path indicates the basic use (main, release, etc.). The depths become slightly more complex but this sort of things works rather well. Notice the components in the /dev/personal and /dev/team to make sure people understand what's going on and who "owns" the branch.

Weaving strands together

If we have a number of products each of which has associated documents and tests etc, then one structure is (assume that all paths are rooted under //depot):

/main/src/

All source files

     productA/...

Sources for Product A

     productB/...

Sources for Product B

     productC/...

etc

/main/doc/

All documentation files

     productA/...

Docs for Product A

     productB/...

etc

/main/test/

All test files and documentation

     productA/...

Sources for Product A

     productB/...

etc

Now we can branch "Product A" for release 1.0 as:

 

/release

All source files

   /productA/1.0/

Release 1.0 of Product A

      src/...

Sources

      doc/...

Documentation

      test/...

Test

 

The problem with the above is that when you branch either to create the release branch in the first place or to propagate changes back, you need multiple lines in your view - an excellent time to use branch view specs mind.

As a general guideline, I prefer to have as simple a branch spec as possible to avoid "forgetting" things. I would try to go for one of the examples shown earlier. However, this is not always possible or indeed desirable.

 

 

Protections, Triggers
and Other Paraphernalia

 

If you have structured your repository thoughtfully, it is very straight forward (as an administrator) to use the protect command to create different protections for different branches. For example you can allow all developers write access to the main line, but only a small group to have write access to a particular release branch for bug fixing. Indeed there might be older "frozen" releases which are no longer being supported from which you could remove all write access.

You can also write triggers which monitor submits to specific branches and for example will not allow direct edits to files in that branch but only integrates from other related branches.

(How to implement this is left as an exercise for the reader...)

 

 

Conclusion

 

Perforce offers a very flexible and powerful mechanism for branches with which you can easily shoot yourself in the foot if you are not careful. Think first, think again, plan, and only then start adding, submitting and branching and remember to KISS and you will be OK (and waste less time restructuring your depot later).

This page has shown a few examples and given a few guidelines as to things to think about. The possibilities of course are endless and as long as you have good reasons for doing things and you (and your colleagues) can understand what is going on then branch away - have fun!

I have made no attempt to look at some of the more complex aspects of branching:

  • sibling branches
  • the nitty gritty of propagating changes and partial integrations and the like
  • integration histories
  • scripting branch stuff

These will be covered at a later point.

 

 

References

 

For more examples of uses of branching and the principles involved I suggest you read:

Software Life-Cycle Modelling in Perforce - a good overview

High-level Best Practices in Software Configuration Management - in particular the description of the mainline branching model.

Please send feedback and comments on this page to <script type="text/javascript"></script> web@vaccaperna.co.uk

 

Footnotes

1) For the non-Brits amongst you, Noddy is a character in Enid Blyton's children's books - whole generations of us came across them. Q: Why do elephants have Big Ears? A: Because Noddy wouldn't pay the ransom!

本课题设计了一种利用Matlab平台开发的植物叶片健康状态识别方案,重点融合了色彩与纹理双重特征以实现对叶片病害的自动化判别。该系统构建了直观的图形操作界面,便于用户提交叶片影像并快速获得分析结论。Matlab作为具备高效数值计算与数据处理能力的工具,在图像分析与模式分类领域应用广泛,本项目正是借助其功能解决农业病害监测的实际问题。 在色彩特征分析方面,叶片影像的颜色分布常与其生理状态密切相关。通常,健康的叶片呈现绿色,而出现黄化、褐变等异常色彩往往指示病害或虫害的发生。Matlab提供了一系列图像处理函数,例如可通过色彩空间转换与直方图统计来量化颜色属性。通过计算各颜色通道的统计参数(如均值、标准差及主成分等),能够提取具有判别力的色彩特征,从而为不同病害类别的区分提供依据。 纹理特征则用于描述叶片表面的微观结构与形态变化,如病斑、皱缩或裂纹等。Matlab中的灰度共生矩阵计算函数可用于提取对比度、均匀性、相关性等纹理指标。此外,局部二值模式与Gabor滤波等方法也能从多尺度刻画纹理细节,进一步增强病害识别的鲁棒性。 系统的人机交互界面基于Matlab的图形用户界面开发环境实现。用户可通过该界面上传待检图像,系统将自动执行图像预处理、特征抽取与分类判断。采用的分类模型包括支持向量机、决策树等机器学习方法,通过对已标注样本的训练,模型能够依据新图像的特征向量预测其所属的病害类别。 此类课题设计有助于深化对Matlab编程、图像处理技术与模式识别原理的理解。通过完整实现从特征提取到分类决策的流程,学生能够将理论知识与实际应用相结合,提升解决复杂工程问题的能力。总体而言,该叶片病害检测系统涵盖了图像分析、特征融合、分类算法及界面开发等多个技术环节,为学习与掌握基于Matlab的智能检测技术提供了综合性实践案例。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值