Thursday, May 10, 2012

MSysGit mergetool broken after 1.7.7

I've been using Git on Windows (MSysGit) happily with BeyondCompare 3 for quite a while. Mostly I use BC3 to view changes. Occasionally I use it to merge conflicts. I don't merge very often, thanks to Git's powerful merging capability. It has worked fine. Recently I upgraded to version 1.7.10-preview20120409, and suddenly the git's merge command always fail with below error messages:

Merging:
my/path/filename.cs

Normal merge conflict for 'my/path/filename.cs':
  {local}: modified file
  {remote}: modified file
Hit return to start merge resolution tool (BC3):
git_path/libexec/git-core/mergetools/BC3: line 9: bcompare: command not found
my/path/filename.cs seems unchanged.
Was the merge successful? [y/n] n


Where is this line 9? It turns out that it seems MSysGit (or Git?) has put all merge tools to a folder named "git_path/libexec/git-core/mergetools/". In my installation, I can already find quite a bunch of tools:

araxis
bc3
defaults
deltawalker
diffuse
ecmerge
emerge
kdiff3
kompare
meld
opendiff
p4merge
tkdiff
tortoisemerge
vim
xxdiff


and they are actually bash scripts. For example, the bc3 file is like below:

diff_cmd () {
 "$merge_tool_path" "$LOCAL" "$REMOTE"
}

merge_cmd () {
 touch "$BACKUP"
 if $base_present
 then
  "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" \
   -mergeoutput="$MERGED"
 else
  "$merge_tool_path" "$LOCAL" "$REMOTE" \
   -mergeoutput="$MERGED"
 fi
 check_unchanged
}

translate_merge_tool_path() {
 if type bcomp >/dev/null 2>/dev/null
 then
  echo bcomp
 else
  echo bcompare
 fi
}


and there is really is a line 9! Of course directly modify the file will do the trick. But I guess there are better ways. After testing around, trying to override the merge_tool_path environment variable, I found it's easier if I just put BC3's folder to path, and nothing else need to be changed!

Friday, May 4, 2012

Git: generate patches, after or before commit happens.

Occasionally, if not often, I need to generate patches to be applied to another git copy. This can happen either before I commit or after. It turns out, the ways to do it for the two scenarios are different.

If the change set is already committed, then below command line can generate the patch:



git format-patch -1

This will create a patch in the current folder with file name like 0001-comments-in-the-commit.patch.

-1 in the command line means generating patch for last one commit. If you want to patch in more commits, specify the number here. If you don't like the default file name and want to specify your own output file name, then you can direct output to stdout and the redirect stdout to a file, like below:


  git format-patch -1 --stdout > your_file_name.patch

So how do you do it when you don't want to commit the changes? A simple way is to generate the diff output and redirect it to a file. The problems is, like most people, I'm not satisfied with git's diff output and I use a graphical tool, BeyandCompare, to do the diff viewing. If I execute

git diff > pathfile.txt


the BC is invoked and there is nothing redirected to the patch file, unsurprisingly. So how to force the diff command to skip the GUI tool? As in most of the cases, a command line switch comes to help: --no-ext-diff. Below command line will happily output the result to console and skip BC:

 git diff --no-ext-diff Applying patches generated with git diff is simple:
patch -p1 < patch-file.txt