Date Category Git

Git is awesome in many ways but comes with a quite high learning curve. Adopting Git requires learning. One of the concept I teach is "don't fear git rebase"! Curiously, once this ritual becomes usual I tend to see very offending rebases.

rebase is great

Yes, git rebase is great! This is likely how you should integrate changes of the mainline into your ongoing work as a contributor.

Conflicts are to be expected and git rerere is a nice helper. Not to talk how git rebase --interactive is wonderful.

Don't rely on Git for solving your conflicts

Most users know that Git will stop and alert when hitting conflicts. Hence, it becomes natural to rebase and just see if there are conflicts to solve. Notice this is true while merging, too.

However, "blindly" rebasing is rather wrong.

What are conflicts

Conflicts are incompatible changes.

Everyone know them. When one makes changes on a file and someone else makes other changes in the same area, Git will stop at some point and complain about those incompatible changes.

I call those "textual" conflicts. Git (or whatever content manager you use) don't know how to get them solve. Human intervention is required.

However, there are many other kinds of incompatible changes that your SCM won't care at all. For those, you won't be warned.

Semantic changes

Semantic changes are about renames and the easiest to depict my point. The code base is:

def hello():

Locally, you use this function in your ongoing work by adding yet another call to the hello() function.

# My new code block.

Since you'd like to integrate upstream changes, you start a new rebase. Everything goes fine without any apparent conflicts. Hence, you decide to release your work or request a merge.

This is WRONG. If upstream changed the function name from hello() to hi() , your freshly rebased code is sightly broken. And Git did not warn you about that.

Other significant incompatible changes

There are many kind of other incompatible changes. It's not the point to list them all. Though, here are some that you might be missing while blindly rebasing:

  • signature (arguments changes or returned type)
  • locking strategy (e.g.: from pessimistic to optimistic locking)
  • exception handling
  • database
  • CSS
  • template
  • events
  • etc

Always read the changes introduced since the common ancestor

Checking if code changes are about to hurt is a matter of knowing what changed in which way.

Commit messages

You know how to write good commit messages. You like to write good commit messages. Help others to provide GOOD commit messages.

Commit messages are the first helpers to track down changes. You already stopped using git pull in favour of git fetch and git rebase .

When doing a git fetch on a remote repository, Git will display the ranges of changes. This is a good start to read them as soon as they are fetched:

> git fetch
remote: Counting objects: 1761, done.
remote: Compressing objects: 100% (738/738), done.
remote: Total 1761 (delta 1118), reused 1523 (delta 1021)
Receiving objects: 100% (1761/1761), 2.43 MiB | 2.40 MiB/s, done.
Resolving deltas: 100% (1118/1118), done.
From git://
   e0688e9b2..9d77b0405  master     -> origin/master
   e7e07d5a4..7c9c2f8c3  maint      -> origin/maint
   76c07830f..ad4152297  next       -> origin/next
 + 706d305d9...e0f560f03 pu         -> origin/pu  (forced update)
   000dd595e..ee9787006  todo       -> origin/todo

Then, inspect the logs of the new master:

> git log --decorate --topo-order e0688e9b2..9d77b0405

or inspect what was introduced since you started MY_BRANCH (off of master ),

> git log --decorate --topo-order MY_BRANCH..origin/master

Read the patches

Next, read the patches including those you're not sure what the commits are about.

> git log --decorate --topo-order -p MY_BRANCH..origin/master

or, for each specific commit,

> git show 9d77b0405


Never ever trust a rebase (or a merge) just because there was no conflict.

Rebasing means integrating topics that could work in the mainline but might really NOT play well with yours.

Same goes while merging. Each topic can work well as-is until it's merged with other stuff.

It's definelty not the job of the SCM to warn you about all the possible conflicts. Actually, it would be too hard to achieve for a program.

It's your job to make sure that the upstream changes are fully compatible with yours while rebasing. Never ever skip all the required checks or you might go into serious troubles.

Of course, run the tests again! ,-)