开发者

Should I create a branch for single commits?

I'm new to Git and to branching. Within our t开发者_运维知识库eam, we have a bunch of websites that require simple maintenance (adding a new page, fixing some links, etc). The commits would normally contain all of the requested functionality. I am not sure if we should create a branch, or if we can just commit to master? After all, the commits are named and make it clear what we have done. I feel that branches actually create more complexity for such simple tasks. Or am I mistaken?


As a rough guideline:

Commits exist to update the state of a branch, and branches exist as alternative views of your codebase.

If it makes sense that your changes can be seen as moving "forward in time" of the master branch, then you should use commits only. If you are going to do something that is an "alternate reality" of the master branch, you should make a different branch.

In this case, if I understand your situation, I would guess you're really truly updating the state of your codebase, so I would just commit your changes.

In this respect Git is similar to any SCM. What makes Git different with branching is that branches are very easy to create and (somewhat) easy to merge. That means that a common workflow is to branch master into a work in progress for a new feature, then make your edits. When you're satisfied, you can merge your branch into master. This is just an improvement on straight commits - you are creating an "alternate reality" of an unstable master, improving it, then merging it back into the real master - but the net effect is the same: your commits in the alternate reality end up landing in master as if you had always made them there. The end goal of all this runaround is that your commits show a linear march through time of changes.


Branches do create more complexity but at the same time they give you more power. Once you start branching you can easily shuffle them, take the changes from one but not the other and so on. For simple scenarios just working on the master branch is enough of course (it becomes really similar to svn use). You would have to find your own way into git which best suits your needs. Here is a good resource.


May I suggest taking a look at Git flow? http://nvie.com/posts/a-successful-git-branching-model/

https://github.com/nvie/gitflow

Some people say that you should avoid branching where possible, but I think that git flow can provide a great solution for an environment where you have people working on different features at once.


One of the beautiful things about Git is that it accommodates many different ways of working.

  • You can create a branch for every change, or never create one at all.
  • You can use remote branches shared among developers, or only local branches.
  • You can merge branches and leave the branches visible, or you can heavily rebase and fast-forward merge so your history never shows a single parallel line.

Anything we tell you here will be just a matter of personal preference. My personal preference is to always create a local branch for any type of change. That's because:

  • I have no-ff turned on, and it's easy to back out a change or series of changes if they have an associated merge commit.
  • It's easy to keep several different changes from getting mixed up. I may be in the middle of a non-urgent change, when an urgent one comes across. You can use git stash to hold your changes, but I find separate branches less confusing. (Often I'll check in my work with a commit message of "WORK IN PROGRESS." Then when I return to the branch, I do git reset HEAD~1 to undo that last commit [but keep the changes] and keep working.)
  • Having a branch encourages me to create smaller commits (fewer changes), which makes it easier to merge them correctly later.

These are some reasons to consider always creating a branch. Try it for a while, see if it works for you, and then keep it as a new technique or discard it if you don't care for it.


Here is my way of working. You can also see some good comments from Martin Fowler and others. Good discussion: https://plus.google.com/109096274754593704906/posts/R4qkeyRadLR

This may apply well to you if you want to have some control on what you release. But the fact that your "features" are small, you may relate to this type of workflow.

Branch-per-Feature

The big WHY: Fast, flexible, high quality and confident development/deployment/testing etc. This makes business happy.

In point form, unorganized and rough:

Features are small

Old-school branch-per-feature meant that branches were large and long living to avoid having to integrate because it was a pain. This was a vicious circle as the feature would diverge further and further from other features or the mainline. Features should be as atomic as possible and your development process should abide by the Open Close Principle. Features should be small.

Integrate relentlessly

They should be integrated into an integration branch almost as often as you commit to them. This gives feedback immediately. You have some sort of CI running off of the integration branch to tell you if your changes are not adversely affecting other work. This gives you the immediate feedback of trunk-based integration while keeping your work organized and malleable.

Don't do back-merges

Or at least avoid them. A back-merge is where you want to use something from the integration branch to help you get your work done on the feature. This is a smell that you don't have independent stories. A reasonable middle-ground is cherry-picking. A successfully cherry-picked commit will not cause you issues when you merge in the future.

Keeping a feature branch filled with commits that only attain what the feature is supposed to do will make working with it much more flexible.

Involve QA from the start

This should not even be a contentious point anymore. We all know how important tight feedback loops are. There should not be a QA department with QA employees. QA should be a hat that is worn at different or same people at different times.

Knowing what your Acceptance Criteria is and how you will prove it from the start is integral to getting a lot of things gelling - including a successful branch-per-feature regiment.

A proper DSL a la Ubiquitous Language (see Domain Driven Design) is at the heart of this. The tool that best communicates across to the Product Owner, Regression/Specification Testing and Behaviour Driven Design feedback is currently StoryTeller. One thing that it offers that no other tools offer is communication to the person writing the Acceptance Tests of what the system is capable of doing with the smallest amount of friction caused by technology. You simply pick what you want to do by clicking on links, filling out text boxes and selecting from drop-downs. There is no guessing as to how a tool might interpret your free-form text with it's regex and English-parsing goodness.

Share your hard work

There will be conflicts when you merge. This is a fact of life when work is done by more than one person. When you integrate often from your feature to the integration branch, the conflicts you solve should be remembered. This is done by git's rerere but could be simulated in other systems with little effort. The key is to set up a way of sharing these auto-resolution conflicts to the rest of the team.

Now anyone that tries to integrate that feature and has that conflict will not have to resolve it. No dev required to put together a build. This is a manual share right now if needed. I should have the script published in about a week that does this behind the scenes. If you want to do it yourself, look no further than the .git/rr-cache folder in your repository. Simple synchronization between all devs is the bare minimum that is needed.

Taking features out is more powerful than putting them in

This might sound counter-intuitive. But at the end of an iteration, a feature that you thought was done may not work as the last bits of testing on the build as a whole make releasing a no-go. Anyone should be able to take out that feature and release anyway.

So the trick is not to take the feature out of the build. You make a build with the problem feature omitted. You can integrate that feature in the next iteration when there is time. Releasing a build should be painless.

Don't make a build to test out of the integration branch. Make a separate branch that can be reset relentlessly and tag release candidates. Reset this branch to the start commit of your iteration and merge all the features you know work.

No conflicts. Remember rerere and the like? Anyone should be able to do this if you followed the practices here. This is "why" the hard work needs to be shared.

The key is we "threw away" all previous merges and have to redo them. But remembering our conflict resolutions, this is now a trivial matter. If in doubt, we haven't really thrown them away, they are still there to reference or use. Git's pick-axe functionality makes it really easy to find certain code changes if you don't know where to look.

Giant refactorings

Your work is as organized as is possible. Whether you elect to do this off of a certain point in time on the integration branch, release candidate branch or you started a feature branch for it, you have a way of tracking that work and can apply it as a merge, rebase or manual patch to another point if necessary.

Any hardships that you may encounter will be tempered by the fact that you are relentlessly sharing your conflict resolutions and continuously integrating. PROPER BRANCH-PER-FEATURE RELIES ON RELENTLESS CONTINUOUS INTEGRATION

Toggles are a hack

There are exceptions. You're a giant company. You need to enable a feature for a small subset of early adopter users. This is now an explicit feature that's important to business. That's where we all want to be but most of us are not.

Having to make architectural changes because you can't effectively organize your work is a process smell plain and simple. Some teams are not mature enough and this may be an OK solution temporarily.

This is Git Flow Improved

Most of this way of working started from the excellent post called "Git Flow a Successful Branching Strategy". The important addition to this process is the idea that you start all features in an iteration from a common point. This would be what you released for the last one. This drives home the granular, atomic, flexible nature that features must exhibit for us to deliver to business in the most effective way.

The other key difference is no back-merge into the feature. Otherwise, you will not be able to exclude this feature later in the iteration.

It will be bad if you use old tools

Not having a snapshot based history will hurt as branching is effectively copying another branch which will be slow. Not having a base of where the branch originated will make merging difficult as you do not have a base to compare how each side of development has changed. There are many other issues with having a connected-only tool to support what you do in order to work with everyone.

Hope this helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜