Thursday, February 23, 2012

Anticipating Git 1.7.10

According to the Git Calendar, we still have a few more weeks until the feature freeze for the next release Git 1.7.10, in which there will be one backward-incompatible improvement that potentially can bite people who used the git merge command in their scripts.

[Update: the above phrasing is a bit too alarming; here is a clarification you may want to read after finishing this entry]

Following the advice given in an article at LWN.net by Jake Edge:
Most free software projects discuss planned changes well in advance of their implementation and give users lots of opportunities to try out early versions. But engaging the project is best done with well-reasoned, specific descriptions of problems, missing features, and so on—not endless streams of "Project XYZ sucks!" messages to mailing lists or comment threads.
let's describe what we have decided, why, and how users can use the upcoming release in their work.

Traditionally, when the git merge command attempted to merge two or more histories, it prepared a canned commit log message based on what is being merged, and recorded the result in a merge commit without any user intervention, if the automatic merge logic successfully computed the resulting tree without conflict. When the automatic logic did not manage to come up with a clean merge result, it gave up, leaving the conflicted state in the index and in the working tree files, and asked the user to resolve them and run the git commit command to record the outcome.

Most merges do cleanly resolve, and this behavior resulted in people making their merges too easily and lightly, even when the reason why the merge was made in the first place should be explained. Nobody explained why the merge was made in a merge commit, because in order to do so after git merge already made the commit, they have to go back and run git commit --amend to do so.

Recently in a discussion on the Git mailing list, Linus admitted (and I agreed) that this was one of the design mistakes we made early in the history of Git. And in 1.7.10 and later, the git merge command that is run in an interactive session (i.e. both its standard input and its standard output connected to a terminal) will open an editor before creating a commit to record the merge result, to give the user a chance to explain the merge, just like the git commit command the user runs after resolving a conflicted merge already does.

There are two recommendations we give to end users to adjust to this behaviour change.

(1) When using git merge interactively, there are two cases:
  • Merging updated upstream into your work-in-progress topic without having a good reason is generally considered a bad practice. Such a merge in the wrong direction should be done only when it is absolutely necessary, e.g. your work-in-progress needs to take advantage of recent advancement made on the upstream.  Otherwise, your topic branch will stop being about any particular topic but just a garbage heap that absorbs commits from many sources, both from you to work on a specific goal, and also from the upstream that contains work by others made for random other unfocused purposes. So if you are merging from upstream into your topic branch, you can use the command without any option to take advantage of the new behavior, let it open an editor for you, and justify the merge. You no longer have to amend the commit after you made the merge to explain it.
  • When you are merging your topic into your own integration (or testing) branch, on the other hand, such a merge is often self-explanatory.  The topic is fully cooked, and ready to be pushed out, and that is the reason why you are merging. In such a case, it will be sufficient to run the command with the --no-edit option and accept the canned commit log message without editing.
(2) If you have a script that runs git merge, and you left its standard input and output kept connected to the terminal, it may start to ask whoever is running the script to edit and explain the merge. This may or may not be a desirable thing depending on the reason why the script is making a merge.  Often, scripts are used to merge many branches into temporary testing branch in bulk, and want to run unattended if they merge cleanly. In such a case, you do not want to change the old behavior of the script. You do not have to add --no-edit to all your invocations of the git merge command to update such a script. Instead, you can export GIT_MERGE_AUTOEDIT=no at the beginning of your script, and the git merge command will silently make commits when there is no conflict.

Please try out the updated git merge before 1.7.10 release is tagged from the master branch, and adjust your scripts and work habit as needed. Also, please suggest improvements to our development mailing list, git@vger.kernel.org, regarding:
  • the documentation,
  • error, advice and general messages output from the program,
  • logic to detect the interactiveness.
One thing that is not open to discussion is that the merge command will launch the editor when interactive by default. This will not change, because, as Linus says, the default matters, and the behavior we had so far was a bad default.

Finally, spread the word so that other users can start adjusting their use of the command early.

[EDIT]

Linus has this to say in his re-share:

This change hopefully makes people write merge messages to explain their merges, and maybe even decide not to merge at all when it's not necessary. 
I've been using that git feature for the last few weeks now, and it has resulted in my merges from submaintainers having various notes in them (well, at least if the submainter gave me any). So I'm trying to lead by example.
But if you don't like explaining your merges, this might be annoying. Of course, if you don't explain your merges, you are annoying, so it all evens out in the end. "Karmic balance", so to say.
Note that this new feature will not be in 1.7.9.3 release.