Saturday, February 25, 2012

Updates to "git merge" in upcoming 1.7.10

The previous entry about a potential incompatible update to the behavior of the git merge command may have been unnecessarily alarming for casual readers and it deserves a bit of clarification. The update is designed to primarily target the interactive use, and not to negatively affect typical uses of the command in scripts.

Let's look at a few example use cases of the git merge command in end user scripts, and how well these scripts will work with the upcoming version.

(1) Your script may be designed to be run by your end users (e.g. it may be an implementation of the git my-merge command) to implement extra checks that are specific to your project or corporate environment before invoking the actual merge, perhaps like this:

#!/bin/sh
# Make sure you do not have uncommitted changes
test 0 = $( ( 
  git diff --name-only
  git diff --cached --name-only
 ) | wc -l ) &&
# Perhaps other project specific checks here...
# ... and finally
git merge "$@"

There is no need to update the above script in preparation for 1.7.10. The script is directly facing the end user, and with 1.7.10, the user can take advantage of the updated behavior that automatically opens the editor to make it easy for him to explain the merge. Also note that in a user-facing script like this, the underlying git merge command is typically passed the command line arguments given by the end user to the script (notice the use of "$@" in the above example). The end user can pass the --no-edit option to the script if he wants to silently conclude the merge.


(2) You may be responsible for the overall QA after receiving various topics from your contributors and co-workers, and may be using a script like the following to regularly merge many topic branches into an integration branch for testing:


#!/bin/sh
if test -f topics
then 
  # Prepare topics to be integrated just once
  list-topics >topics &&
  # And checkout the tip of the master to integrate them all
  git checkout -B test master || exit
fi
while read topic
do
  git merge "$topic" || exit
done <topics
# All done
rm -f topics

In such a case, you do not have to explain each and every such merge to rebuild the test integration branch, and you do not want the change in 1.7.10 to affect the above script. 


And we didn't want to break such a script, either. Notice that the git merge command in this example is not facing the end userits standard input is connected to the file that lists the topics, from which the surrounding while loop is reading, and not to the user's terminal. Because of this, the command will not automatically open an editor to ask your user to explain the merge, and there is no need to worry about the compatibility.


(3) Your project may run integration test every time its members update the master branch of the central shared repository, and as a part of the integration test, it may merge the updated master to the test repository that has mock data for testing. Such a script may look like this:

#!/bin/sh
# Called from the post-update hook of the central repository
unset GIT_DIR
cd /srv/test.repo &&
git pull /srv/central.repo master || {
  logger "The updated master does not cleanly merge -- no automated test done"
  git reset --hard exit 1}
make test || {
  logger "The updated master does not pass test"
  git reset --hard
  exit 1
}


If you run such a script interactively, the git pull command will invoke the underlying git merge command interactively, which in turn will open the editor and ask you to explain the merge. But if it is run from a post-update hook, the standard input is not likely to be connected to any interactive terminal (this is also true if such an automated merge is done as part of a continuous integration testing). Hence, in practice, 1.7.10 will not change the behaviour of the git merge command used in such a script, and there is no need to worry about the compatibility.

(4) If your script uses git merge, is run interactively by the end user, and it keeps the standard input to the git merge command connected to the terminal, but for whatever reason you do not need your users to explain the merge, you do need to worry about the compatibility. You could add the --no-edit option to the git merge command invocations in your script as necessary, but there is a quicker way:

#!/bin/sh
GIT_MERGE_AUTOEDIT=no
export GIT_MERGE_AUTOEDIT
# whatever your script did originally
...
git merge foo
git merge bar
...

You can set GIT_MERGE_AUTOEDIT environment variable to no at the beginning of your script, and all the git merge command invocations will work as if they were given the --no-edit option.

Hopefully it is now clearer that there is not much to fear in the update to the git merge command planned in the upcoming 1.7.10 release.

Happy Gitting!