5

So I've heard of the branch-per-feature workflow using Git, and I've also read some reasons why this could be a bad idea.

My real question is this - if I'm developing just a small feature (like a simple regex time parser), after merging this branch back into the trunk, what happens (or should happen) to that branch? Does it just sit there? Since I created it for that one, very specific feature, I can't think of a reason I'd have to go back and use the branch. Should I somehow mark this branch as defunct, or do I just move on and forget about it?

Thanks

Wayne Werner
  • 41,650
  • 21
  • 173
  • 260
  • 3
    You can delete the branch once you're done, can't you? (`git branch -d`) – Platinum Azure Oct 31 '11 at 20:43
  • 1
    Yup, git branch -d is always safe, it can't lose any revisions that might subsequently be garbage collected. git branch -D will delete even branches that contain changes not found anywhere else. This is useful mostly when you've determined that an approach was a complete dead-end. Given how cheap disk space is, you should probably be loathe to use git branch -D – tialaramex Oct 31 '11 at 20:52
  • It might help you to remember that a branch is merely a pointer to a commit. Once you're done working on a branch, and you've merged that commit, you have no need to point to it anymore. – Cascabel Nov 01 '11 at 00:25
  • Ah, @Platinum and @tialaramex, I think that's where my confusion was - I used the `-D` switch before and it gave me a warning about possibly losing commits. I didn't realize there was a `-d`, although I'm not sure why, since most options when they have an uppercase have a lowercase variant. Lesson learned! (Let's see how well it sticks...) – Wayne Werner Nov 01 '11 at 13:19
  • Similar question: [What to do with experimental non-merged git branches?](http://stackoverflow.com/questions/8988240/what-to-do-with-experimental-non-merged-git-branches/8989747#8989747) – sleske Jun 21 '12 at 09:06

5 Answers5

14

When I use feature branches, I like to retain the fact that a feature was developed in a branch after the merge. That makes browsing the history much easier. It groups changes by feature or bug and makes it easier to know the most important thing: why a change was done.

Which is why when I merge, I deliberately disable fast forwarding with git merge --no-ff. This retains the structure of the branch in history. Then I'm free to delete the branch label (git branch -d branch_name), the merge point contains the branch name, and clean up the set of branches.

In contrast, when working on a branch I prefer to rebase the upstream branch. This keeps the history of the branch nice and clean, free of lots of upstream merge noise and conflict resolution. I will generally rebase upstream before merging to make the job of integrating easier (as the branch author I can fix conflicts and broken tests) and the resulting merge cleaner.

This approach retains the history of the branches while preventing old branches no longer being developed from clogging things up. It makes visualizing the history with gitk or GitX very useful.

I agree with the basic points in the article you linked, as you get more and more large feature branches which are worked on simultaneously there's more and more chance of conflict and integration problems. The isolation which makes them so useful becomes a liability. One of the solutions is to not have large, old feature branches. If you can bust a feature branch up into smaller pieces which can be completed and integrated, then you avoid the problem. This is often useful for many other reasons, like the poor slob that has to review the code.

If it is possible to continuously integrate a feature branch into mainline, then the feature branch must have useful, working, tested, documented work. If it has that, then those could be sliced off into their own branches.

I freely admit I may be reading too much into this, but one of the possibly telling flaws in the article is that the branches are named for people and not features. This implies that each branch is for "whatever Jim is working on" rather than "adding blue widgets". It implies a number of developmental problems...

  • features and branches are owned by individuals or teams
  • branches are not for discrete features
    • instead, branches are personal playgrounds
    • with no defined feature, they can go on and on
  • development is done in silos
    • individuals do not speak to each other regularly
    • individuals do not work together on branches
    • individuals do not talk about their changes until integration

A lot of this is not a technical problem but a social problem. Much of it can be solved by strong use of a good issue tracker strongly linked with version control, such as Github's. The main change is:

  • branches should be for defined features
  • developers should report an issue before going off and doing a bunch of work
  • nobody "owns" a feature (though they may be responsible for it)

That second one is, unfortunately, discouraged by most project's bug tracking policies. The urge to have a patch ready before reporting a bug is a very strong one.

Good branch management requires good socialization which is facilitated by a good issue tracker with strong version control integration and a welcoming policy.

Schwern
  • 127,817
  • 21
  • 150
  • 290
3

Delete it, if you don't need it anymore. If you realize later, that you need it again, you can create it again. And because you merged the changes back into "trunk" nothing is lost.

KingCrunch
  • 119,075
  • 18
  • 142
  • 167
3

The nice thing about Git and branches is that each branch is essentially a pointer to a commit. Once you've merged your branch, the commits that used to form your branch are now an integral part of the main history.

                                  your branch
                                    main
                                      |
  (main)  -------x----x----x-x---x----x
                  \                  /
  (your branch)    \--x--x-x--x-x---/

At this point, if you delete your branch using "git branch -d", you're left with:

                                    main
                                      |
  (main)  -------x----x----x-x---x----x
                  \                  /
  (your branch)    \--x--x-x--x-x---/

As you can see, the commits from your branch are still safe. All that has changed is that the pointer called "your branch" has been deleted.

Note, that if you had not merged into main, then "git branch -d" would have failed. If you force deleted it at that point, you'd be left with:

                                  main
                                    |
  (main)  -------x----x----x-x---x--x
                  \
  (your branch)    \--x--x-x--x-x

Since there is no branch pointer at this stage, the commits are "dangling" and will be removed the next time git does its garbage collection.

Long story short, if your branch has been merged, you can and should delete it. If it has not been merged, you shouldn't.

Carl
  • 39,407
  • 10
  • 74
  • 99
1

Two things to consider:

  1. Maybe you should have a habit of rebasing these branches onto the tip of master (or wherever) before landing them. This way, they are strictly redundant as KingCrush suggests above, and can be destroyed to be recreated later if you find a problem.

  2. Use rename to mark branches you're not sure if you'll need again with a specific prefix, so that you can scan past them quickly in a list of branches when you know you're not looking for an obsolete feature branch.

You could use some mixture of these techniques, e.g. always rebase, then rename branch foo to landed-foo, and then after a set interval (say, one release, or 30 days) delete the landed-foo branch.

Notice that if you don't rebase (and run any tests on the rebased version) you have no way to be sure that a bug found after it lands was actually in the code as developed, and not caused by the impact of merging it after development, so in this case you might want to keep the branch for a while. This will happen more often with invasive / very large changes, not like your question scenario.

tialaramex
  • 3,630
  • 1
  • 19
  • 23
  • Rebasing is not always a good idea as it destroys the way, the feature was developed. There is absolutely no harm in merging it correctly, and git was actually developed to handle wide-spread branching and merging. Having a clear branch showing in the history later shows you that the feature was developed individually, and you can easily identify it later on if you need to. In the same way it is completely safe to delete branches, as they are only pointers to commits within the history. Deleting a branch will not delete the history it belongs to; the history will always show branching/merging. – poke Oct 31 '11 at 20:56
0

The only reasons, that I can see, you would want to keep it around is:

  • You want a history of when you last worked on it.
  • You could infer when development on it started.
Andy
  • 38,684
  • 13
  • 64
  • 66
  • 1
    You can get both by looking at the history even without having an actual branch pointing to the commits. There is no real reason to keep a branch around, when the work with it is completed and it’s merged back into some other branch. – poke Oct 31 '11 at 20:57
  • Agreed. However, I think it would be much easier to see a useful branch name, rather than reverse engineering what the branch did from commit messages. – Andy Oct 31 '11 at 21:17