Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Let's say I have a feature (topic) branch that I keep rebased on top of my development branch. During the course of the project (before merging in my feature branch), I decide that I need to make a large refactor to my project (for example, after updating a 3rd part module).

So I do this large refactoring on my development branch. Now I want to rebase my feature branch so I can take advantages of my refactoring.

The problem

There are still things in my feature branch that need refactored to match the changes I made in my development branch.

Should I:

  1. Go back through my feature branch's history trying to edit commits (with rebase -i) to make the branch look as though all of the work had been done after the refactoring.

    • The advantage to this is that it keeps the history clean.
    • The disadvantage is that this can take a whole lot of time if the changes made in the development branch cause a lot of changes to need to be made in the feature branch.
  2. Fix the things that need to be refactored in my feature branch and make a commit for this.

    • The advantage here is that it will be much easier to identify and fix things that need to be fixed
    • The disadvantage is that now the tree will have two commits in it for the refactor. One for the refactor done for the entire development branch, and a smaller commit done for the feature branch, once merged in it will look a little funny.

Which strategy should I go with?


An Example

Lets say on the development branch I rename functionA to functionB.

Now In my feature branch I've never modified the file containing functionA (now functionB in development). So when I run rebase development while on my feature branch it rebases cleanly.

The problem is if I've ever made a call to functionA in my feature branch, it's going to fail now since it was renamed functionB.

Now, should I just do a find and replace for functionA -> functionB and make one commit on the feature branch (option 2). Or should I go back through my history, finding where I introduced the call to functionA and rewrite the commit so it is introduced as calling functionB (option 1)?

share|improve this question
add comment

4 Answers

Neither

Option 1 sounds like a lot of unnecessary work. Why do you wan't to hide the fact that this code was written before the refactoring of dev?

Another disadvantage with option 2: After the rebase you will have a lot of possibly non-working commits before the 2nd refactoring commit. This will give you problems when bisecting since those commits might be untestable.

Option 3: Merge dev branch into feature branch.

  • Pro: you will get the rectoring from dev and may refactor the rest of the feature branch in the merge to get a working project.
  • Pro: No commit gets untested. (assuming the commits already made is tested).
  • Con: You will not be able to continue rebasing onto dev branch.
share|improve this answer
add comment

It seems that the git revolution has created a new neurosis called commit history anxiety. No one besides you cares what's in your commits. Just get the work done as efficiently as possible. Then you can use the time you saved to fix a bug or add a feature.

share|improve this answer
2  
I know at least two use cases that benefit significantly from organizing the commits in logical steps. One is searching for causes of regression by interval halving (git bisect), the other is using commit logs to track notes about code (to avoid reintroducing old bugs, you need to look at history of code in question, but it only works well if the steps are logical and described). –  Jan Hudec Jan 24 '13 at 8:05
add comment

Not sure why you would do a rebase -i. I would just do a rebase, and fix the problems as they come in you feature commits.

I find fixing one and one commit is easier than fixing every error afterwords. You can then also make sure, between each commit, that your tests still runs (given that you have tests that is).

Lastly, I find 2) to be problematic if you plan to continue rebasing in the future, if your feature is not yet done. Rebasing in a merge is really not something I would do if I could avoid it. If the feature is done and you don't care to much about history however, you could just merge.

Conclusion: I would personally rebase, without the -i, and fix each commit. The reason is that I find a tidy log quite useful, and I often feel that it is the easiest way to do it.

EDIT: By your example, I would say it depends. If there are a huge amount of commits, you have called functionA a lot of times, and it basically is a huge pain to rebase every single commit, I would probably fall back to just do a search-replace in a single commit. If I knew there were only a few places, and the rebasing would be easy, I would rebase.

Since you ask, I guess the former is the situation you are in, and I would have though about how much pain will it be to clean up the log.

share|improve this answer
    
Sorry I think my question needed an example. See the updated OP. Making a merge commit is out of the question (and I never really considered it an option) precisely for the reason you described. –  Evan Purkhiser Jan 24 '13 at 17:17
add comment

Basically, you shouldn't be using git branches for feature branches.

http://blog.newrelic.com/2012/11/14/long-running-branches-considered-harmful/

http://martinfowler.com/bliki/FeatureBranch.html

Indeed I see this as the decisive reason why Feature Branching is a bad idea. Once a team is afraid to refactor to keep their code healthy they are on downward spiral with no pretty end.

In the quoted text, Martin Fowler is using 'Feature Branching' specifically to mean 'using dvcs branching to manage large-feature development in a way where one dvcs branch maps to one feature'. Which lots of people do. Some of those people are in an environment where they never really need to refactor anything, some of them haven't been doing it long enough to hit the problems, a few have developed tools or procedures on top of git to work around the problems (http://dymitruk.com/blog/2012/02/05/branch-per-feature/), while others are simply in denial as to how much trouble it is causing them.

Thing is, just because an abstract concept and a tool feature have the same name doesn't make them a good match for each other. As you are finding, there isn't really a good way to use the two together, just a variety of less-bad ways.

So, assuming you do really need feature branches, then look through the features your tooling and platform support and find a better match.

Sticking with git, using forks and pull requests is one increasingly common strategy:

http://hintjens.com/blog:24

Worst case, even the humble if [config-setting] statement (known as a 'feature toggle') is very likely going to be a time-saver and quality-booster compared to where you are now.

share|improve this answer
    
I'm really not sure I understand your answer. But I can say it's a pretty bold claim to say that using git branches for working on features is a bad idea, considering this is an extreamly common workflow –  Evan Purkhiser Feb 17 '13 at 10:53
    
yes, it is a very common mistake to use git 'branching' on 'features' to do 'feature branching'. Names can mislead: it used to be a very common mistake to use a 'goto' statement to 'go' from one block of code 'to' another... –  soru Feb 18 '13 at 12:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.