Git Diff External Tool Execution Flow: Meld and P4Merge
I explain the execution flow and how to configure for Git diff external tools and use Meld and P4Merge as my examples. The reason why I want to do this is because almost all the examples I found are always used without any explanation. They just throw out the whole bunch of things or steps and ask you to just follow them without actually knowing what exactly this specific step does or what exactly happened behind the scenes. I will explain all these things as best as I can here.
Meld and P4Merge Configure Steps
(1) To install Meld just run this command:
$ sudo apt-get install meld
To install P4Merge, just download the compressed file from perforce website and extract to somewhere you want, let’s say the executable file p4merge hash the full path :
(2) A simpler way to configure is just wrote some shell script and specify this executable shell script in the .gitconfig file as git external diff tools. The detailed steps as well as their explanations are as follows:
2.a) write a script “git-diff.sh” with the following content and save it into /usr/local/bin and add executable rights with chmod command.
#!/bin/bash meld "$2" "$5" > /dev/null 2>&1
2.b) modify ~
/.gitconfig file and add the following lines:
diff external = /usr/local/bin/git-diff.sh
The work flow: when you type in command git diff, the git will read the configure file and it sees “diff” is specified and it calls the external /usr/local/bin/git-diff.sh and pass 7 parameters to the git-diff.sh script, the 2nd and 5th of which are the old-file and the new-file respectively. The scirpt git-diff.sh accepts the 7 parameters and pass the 2nd “$2″ and “$5″ to meld (otherwise, it will report error). Here “> /dev/null 2>&1″ means we redirect standard error to standout and the standout of the meld output to /dev/null which is usually called “black hole” in linux, this basically means, we throw away all the output and error messages out of meld.
(3) A more general and preferred configuration with P4Merge as an example is using two wrapper scripts. The detailed steps and the explanation are as follows:
3.a) create a shell script /usr/local/bin/extMerge.sh with the following content:
#!/bin/sh /home/yourname/p4merge.d/p4merge $*
3.b) create another shell script /usr/local/bin/extDiff.sh with the following content:
#!/bin/sh [ $# -eq 7 ] && /usr/local/bin/extMerge.sh "$2" "$5"
3.c) add executable rights to the two previous scripts and modify the ~/.gitconfig to add the following contents:
[merge] tool = extMerge.sh [mergetool "extMerge.sh"] cmd = extMerge.sh \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\" trustExitCode = false diff external = extDiff.sh
Work follow: So next time you call git diff, it read the config file and notice the “diff” is specified with some external tools. Then it just runs the extDiff.sh script and pass the “path old-file old-hex old-mode new-file new-hex new-mode” these 7 parameters to the script, as the content in extDiff.sh indicates, it first compare the number of parameters $# to test if it is equal to 7 and if the parameter is correct, then it runs the other script extMerge.sh and pass the two parameters $2 old-file and $5 new-file to the extMerge.sh script. What extMerge.sh does is just to call p4merge and pass p4merge with all the parameters it gets as in $*.
In this post, I just explained the execution flow for Git diff external tools configuration (Meld and P4Merge as examples) so that we know what exactly happened behind the scenes.