Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrate indentation & content changes in Git during merge: Best practices?

I'm using Git to track some matlab code. A toy example best illustrates the problem. The project so far looks like this.

    C
   /
A--
   \
    B

Contents of A are x=5

We make commit C, where the line is changed to x=6

We then make commit B, where our content becomes as below

if flag==1
    x=5
end

If we attempt a merge with the goal of the project looking like

    C
   / \
A--   D
   \ /
    B

with the merge result in D, we'll get a conflict, because the main line has been changed in both (indentation added in B, 5 changed to 6 in C).

Is there a best practice way for integrating indentation changes from one branch, and content changes from another branch, to get a merge result?

I've read about one strategy in https://stackoverflow.com/a/5262473/288545, and while that would avoid the conflict, it would discard the indent in favor of the content change (which is an improvement, but still makes for harder to read code).

I suppose I could just suck it up and not change indentation when writing my code. This makes it less readable, but isn't a huge deal in matlab. However, in python, indentation really matters, so how do python folks deal with it? This gets much uglier if there are large blocks of code that we later change to be inside of control structures, so the diff touches many lines and makes merge conflicts a huge headache.

Is there a merge strategy that will handle spacing changes and content changes separately, and then integrate them? I'd like the result of the merge to be

if flag==1
    x=6
end
like image 547
Daniel Kessler Avatar asked Sep 11 '12 19:09

Daniel Kessler


2 Answers

The key to solving your problem is treating whitespace cleanups and function rewrites as separate commits.

As someone who does a lot of branch integration, I can honestly say the two most annoying things for integrators are: 1) coders who like to reformat files they didn't author or functions they didn't rewrite, and 2) IDEs that reformat whole files simply by opening and saving them. Sure the files are more readable in both cases, but it completely defeats the point of version control: Commits should be intelligently sized, constructed, and reviewed. Their order should have meaning. Kitchen sink commits make for useless history, and history should be nothing but useful.

This philosophy implies "Don't dump whitespace changes in commits where they don't belong." If you're rewriting the touched function, sure, improve the spacing. Otherwise leave it to its own commit and make sure others working on that file know whitespace changes are coming. That'll save you hassle at integration time.

Additionally, you can avoid accidental whitespace errors (trailing spaces, tabs after spaces, and the like) with git's stock pre-commit hook. Issue this command in your repository to set it up:

mv .git/hooks/pre-commit.sample .git/hooks/pre-commit

It more or less issues git diff --check, which is also incredibly useful for detecting these types of problems.

like image 29
Christopher Avatar answered Nov 04 '22 09:11

Christopher


Some diff tools are better than others. I use KDiff3, and have it set up to be invoked automatically using git mergetool. It's still not perfect, but it can often detect merges of the sort you describe and automatically produce a sensible merge.

like image 184
me_and Avatar answered Nov 04 '22 08:11

me_and