Git on Windows: How do you set up a mergetool? - windows

I've tried msysGit and Git on Cygwin. Both work just fine in and of themselves and both run gitk and git-gui perfectly.
Now how the heck do I configure a mergetool? (Vimdiff works on Cygwin, but preferably I would like something a little more user-friendly for some of our Windows-loving coworkers.)

To follow-up on Charles Bailey's answer, here's my git setup that's using p4merge (free cross-platform 3way merge tool); tested on msys Git (Windows) install:
git config --global merge.tool p4merge
git config --global mergetool.p4merge.cmd 'p4merge.exe \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"'
or, from a windows cmd.exe shell, the second line becomes :
git config --global mergetool.p4merge.cmd "p4merge.exe \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\""
The changes (relative to Charles Bailey):
added to global git config, i.e. valid for all git projects not just the current one
the custom tool config value resides in "mergetool.[tool].cmd", not "merge.[tool].cmd" (silly me, spent an hour troubleshooting why git kept complaining about non-existing tool)
added double quotes for all file names so that files with spaces can still be found by the merge tool (I tested this in msys Git from Powershell)
note that by default Perforce will add its installation dir to PATH, thus no need to specify full path to p4merge in the command
Download: http://www.perforce.com/product/components/perforce-visual-merge-and-diff-tools
EDIT (Feb 2014)
As pointed out by #Gregory Pakosz, latest msys git now "natively" supports p4merge (tested on 1.8.5.2.msysgit.0).
You can display list of supported tools by running:
git mergetool --tool-help
You should see p4merge in either available or valid list. If not, please update your git.
If p4merge was listed as available, it is in your PATH and you only have to set merge.tool:
git config --global merge.tool p4merge
If it was listed as valid, you have to define mergetool.p4merge.path in addition to merge.tool:
git config --global mergetool.p4merge.path c:/Users/my-login/AppData/Local/Perforce/p4merge.exe
The above is an example path when p4merge was installed for the current user, not system-wide (does not need admin rights or UAC elevation)
Although ~ should expand to current user's home directory (so in theory the path should be ~/AppData/Local/Perforce/p4merge.exe), this did not work for me
Even better would have been to take advantage of an environment variable (e.g. $LOCALAPPDATA/Perforce/p4merge.exe), git does not seem to be expanding environment variables for paths (if you know how to get this working, please let me know or update this answer)

setting mergetool.p4merge.cmd will not work anymore since Git has started trying to support p4merge, see libexec/git-core/git-mergetool--lib.so we just need to specify the mergetool path for git,for example the p4merge:
git config --global mergetool.p4merge.path 'C:\Program Files\Perforce\p4merge.exe'
git config --global merge.tool p4merge
Then it will work.

I'm using Portable Git on WinXP (works a treat!), and needed to resolve a conflict that came up in branching. Of all the gui's I checked, KDiff3 proved to be the most transparent to use.
But I found the instructions I needed to get it working in Windows in this blog post, instructions which differ slightly from the other approaches listed here. It basically amounted to adding these lines to my .gitconfig file:
[merge]
tool = kdiff3
[mergetool "kdiff3"]
path = C:/YourPathToBinaryHere/KDiff3/kdiff3.exe
keepBackup = false
trustExitCode = false
Working nicely now!

Under Cygwin, the only thing that worked for me is the following:
git config --global merge.tool myp4merge
git config --global mergetool.myp4merge.cmd 'p4merge.exe "$(cygpath -wla $BASE)" "$(cygpath -wla $LOCAL)" "$(cygpath -wla $REMOTE)" "$(cygpath -wla $MERGED)"'
git config --global diff.tool myp4diff
git config --global difftool.myp4diff.cmd 'p4merge.exe "$(cygpath -wla $LOCAL)" "$(cygpath -wla $REMOTE)"'
Also, I like to turn off the prompt message for difftool:
git config --global difftool.prompt false

git mergetool is fully configurable so you can pretty much chose your favourite tool.
The full documentation is here: http://www.kernel.org/pub/software/scm/git/docs/git-mergetool.html
In brief, you can set a default mergetool by setting the user config variable merge.tool.
If the merge tool is one of the ones supported natively by it you just have to set mergetool.<tool>.path to the full path to the tool (replace <tool> by what you have configured merge.tool to be.
Otherwise, you can set mergetool.<tool>.cmd to a bit of shell to be eval'ed at runtime with the shell variables $BASE, $LOCAL, $REMOTE, $MERGED set to the appropriate files. You have to be a bit careful with the escaping whether you directly edit a config file or set the variable with the git config command.
Something like this should give the flavour of what you can do ('mymerge' is a fictional tool).
git config merge.tool mymerge
git config merge.mymerge.cmd 'mymerge.exe --base "$BASE" "$LOCAL" "$REMOTE" -o "$MERGED"'
Once you've setup your favourite merge tool, it's simply a matter of running git mergetool whenever you have conflicts to resolve.
The p4merge tool from Perforce is a pretty good standalone merge tool.

For beyond compare on Windows 7
git config --global merge.tool bc3
git config --global mergetool.bc3.path "C:\Program Files (x86)\Beyond Compare 3\BCompare.exe"

It seems that newer git versions support p4merge directly, so
git config --global merge.tool p4merge
should be all you need, if p4merge.exe is on your path. No need to set up cmd or path.

I found two ways to configure "SourceGear DiffMerge" as difftool and mergetool in github Windows.
The following commands in a Command Prompt window will update your .gitconfig to configure GIT use DiffMerge:
git config --global diff.tool diffmerge
git config --global difftool.diffmerge.cmd 'C:/Program\ Files/SourceGear/Common/DiffMerge/sgdm.exe \"$LOCAL\" \"$REMOTE\"'
git config --global merge.tool diffmerge
git config --global mergetool.diffmerge.cmd 'C:/Program\ Files/SourceGear/Common/DiffMerge/sgdm.exe -merge -result=\"$MERGED\" \"$LOCAL\" \"$BASE\" \"$REMOTE\"'
[OR]
Add the following lines to your .gitconfig. This file should be in your home directory in C:\Users\UserName:
[diff]
tool = diffmerge
[difftool "diffmerge"]
cmd = C:/Program\\ Files/SourceGear/Common/DiffMerge/sgdm.exe \"$LOCAL\" \"$REMOTE\"
[merge]
tool = diffmerge
[mergetool "diffmerge"]
trustExitCode = true
cmd = C:/Program\\ Files/SourceGear/Common/DiffMerge/sgdm.exe -merge -result=\"$MERGED\" \"$LOCAL\" \"$BASE\" \"$REMOTE\"

As already answered here (and here and here), mergetool is the command to configure this. For a nice graphical frontend I recommend kdiff3 (GPL).

I had to drop the extra quoting using msysGit on windows 7, not sure why.
git config --global merge.tool p4merge
git config --global mergetool.p4merge.cmd 'p4merge $BASE $LOCAL $REMOTE $MERGED'

If you're doing this through cygwin, you may need to use cygpath:
git config --global merge.tool p4merge
git config --global mergetool.p4merge.cmd 'p4merge `cygpath -w $BASE` `cygpath -w $LOCAL` `cygpath -w $REMOTE` `cygpath -w $MERGED`'

Bah, this finally worked for me (Windows 7 + Cygwin + TortoiseMerge):
In .git/config:
cmd = TortoiseMerge.exe /base:$(cygpath -d \"$BASE\") /theirs:$(cygpath -d \"$REMOTE\") /mine:$(cygpath -d \"$LOCAL\") /merged:$(cygpath -d \"$MERGED\")
Thanks to previous posters for the tip to use cygpath!

i use an app called WinMerge ( http://winmerge.org/ )
info from their manual ( http://manual.winmerge.org/CommandLine.html )
this is the bash script i use from the mergetool directive via .gitconfig
#!/bin/sh
# using winmerge with git
# replaces unix style null files with a newly created empty windows temp file
file1=$1
if [ "$file1" == '/dev/null' ] || [ "$file1" == '\\.\nul' ] || [ ! -e "$file1" ]
then
file1="/tmp/gitnull"
`echo "">$file1`
fi
file2=$2
if [ "$file2" == '/dev/null' ] || [ "$file2" == '\\.\nul' ] || [ ! -e "$file2" ]
then
file2="/tmp/gitnull"
`echo "">$file2`
fi
echo diff : $1 -- $2
"C:\Program files (x86)\WinMerge\WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$file1" "$file2"
basically the bash accounts for when the result of the diff in an empty file and creates a new temp file in the correct location.

You may want to add these options too:
git config --global merge.tool p4mergetool
git config --global mergetool.p4merge.cmd 'p4merge $BASE $LOCAL $REMOTE $MERGED'
git config --global mergetool.p4mergetool.trustExitCode false
git config --global mergetool.keepBackup false
Also, I don't know why but the quoting and slash from Milan Gardian's answer screwed things up for me.

If anyone wants to use gvim as their diff tool on TortoiseGit, then this is what you need to enter into the text input for the path to the external diff tool:
path\to\gvim.exe -f -d -c "wincmd R" -c "wincmd R" -c "wincmd h" -c "wincmd J"

For IntelliJ IDEA (Community Edition) 3-way git mergetool configuration in Windows environment (~/.gitconfig)
Cygwin
[mergetool "ideamerge"]
cmd = C:/Program\\ Files\\ \\(x86\\)/JetBrains/IntelliJ\\ IDEA\\ Community\\ Edition\\ 14.1.3/bin/idea.exe merge `cygpath -wa $LOCAL` `cygpath -wa $REMOTE` `cygpath -wa $BASE` `cygpath -wa $MERGED`
[merge]
tool = ideamerge
Msys
[mergetool "ideamerge"]
cmd = "/c/Program\\ Files\\ \\(x86\\)/JetBrains/IntelliJ\\ IDEA\\ Community\\ Edition\\ 14.1.3/bin/idea.exe" merge `~/winpath.sh $LOCAL` `~/winpath.sh $REMOTE` `~/winpath.sh $BASE` `~/winpath.sh $MERGED`
[merge]
tool = ideamerge
The ~/winpath.sh is to convert paths to Windows on msys and is taken from msys path conversion question on stackoverflow
#! /bin/sh
function wpath {
if [ -z "$1" ]; then
echo "$#"
else
if [ -f "$1" ]; then
local dir=$(dirname "$1")
local fn=$(basename "$1")
echo "$(cd "$dir"; echo "$(pwd -W)/$fn")" | sed 's|/|\\|g';
else
if [ -d "$1" ]; then
echo "$(cd "$1"; pwd -W)" | sed 's|/|\\|g';
else
echo "$1" | sed 's|^/\(.\)/|\1:\\|g; s|/|\\|g';
fi
fi
fi
}
wpath "$#"

For kdiff3 you can use:
git config --global merge.tool kdiff3
git config --global mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
git config --global mergetool.kdiff3.trustExitCode false
git config --global diff.guitool kdiff3
git config --global difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
git config --global difftool.kdiff3.trustExitCode false

To setup p4merge, installed using chocolatey on windows for both merge and diff, take a look here:
https://gist.github.com/CamW/88e95ea8d9f0786d746a

If you're having problems opening p4merge from SourceTree look for you local configuration file named config under MyRepo.git and delete any merge configuration.
In my case it was trying to open Meld which I just uninstalled

Related

Git alias to open the git installation folder

I want to create a git alias git dir, which when used should open the git installation folder via Windows Explorer, how to implement such an alias?
If using Git Bash, try:
git config --global alias.dir '!start "" "$(git --exec-path)"'
Reference: Can I use the "start" command with spaces in the path?
Starting an alias with ! treats it as a command.
I don't have a windows machine at hand, but for Linux:
git config --global alias.open '!git --exec-path | xargs xdg-open'
Works as described.
So the command you're looking for will probably look something like:
git config --global alias.open "!git --exec-path | 'sed s~/~\\~g' | xargs explorer"

Creating git aliases

I am trying to add the following aliases in ubuntu
alias l=log --pretty=format:"%C(yellow)%h\\ %ad%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --date=short
$ source ~/.aliases
bash: alias: --decorate: not found
bash: alias: --decorate: not found
bash: alias: --numstat: not found
I could use this command outside with git
I am not so sure why? Can someone help me? I tried googling but I did not go far with it. I do not know bash so much.
This is bit older question but it is very important to understand and create git alias as this will save lot of time of yours.
In your question you are close to answer just a silly mistake done is you are trying to create alias using script.
Alias needs to be defined in .gitconfig file. Not just alias but all config part like
[core], [color], [pack], [help], [alias] etc
I would like to share some basic and useful alias with you to have things handy and you can change it further per your need and daily usage
[alias]
lg = log -p
lol = log --graph --decorate --pretty=oneline --abbrev-commit
lola = log --graph --decorate --pretty=oneline --abbrev-commit --all
st = status
co = checkout
ci = commit -a -m
br = branch
ls = ls-files
po = push origin
f = fetch
p = pull
delete = branch -d master
com = checkout master
cob = checkout -b
unstage = reset HEAD
url = remote set-url origin
ign = ls-files -o -i --exclude-standard
cp = cherry-pick
You can also create an alias for a combination of multiple git commands in a single one as, for instance:
rdev = !git checkout dev && git pull && git checkout - && git rebase dev
Let me know if any other understanding needed.
You are almost there. You just need to put the alias in the right file. Because Git doesn’t automatically infer your command if you type it in partially, you can easily set up an alias for each command using git config like so:
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
And then you use it the aliases like: git ci, git co, git br, git st in any repo.
You can also run an external command through an alias. In that case, you start the command with a ! character. This is useful if you write your own tools that work with a Git repository:
git config --global alias.visual '!gitk'
You might have also noticed that the config command takes in several parameters (like the --global one). If we look at the docs man git config:
For writing options: write to global ~/.gitconfig file rather than the repository .git/config, write to $XDG_CONFIG_HOME/git/config file if this file exists and the ~/.gitconfig file doesn’t.
For reading options: read only from global ~/.gitconfig and from $XDG_CONFIG_HOME/git/config rather than from all available files.
See also the section called “FILES”.
There is also --system, which writes to /etc/gitconfig, --local, for the local repo .git/gitconfig, and --worktree, which is similar to --local.
But you can just directly edit the files themselves. It will look similar to this:
# in ~/.gitconfig
[alias]
lg = log --all --stat --pretty=oneline --graph --format='%h %d %an %cr %s' --oneline
l = log --all --stat --graph --format='%h %d %an %cr %s'
up = pull --rebase
br = branch --verbose -a
sfp = push --force-with-lease
You should set the alias in your git aliases and use it from the command line
You can directly edit the configuration file or do it from CLI:
Git Alias
Use the git config --global alias.<name> in order to add git alias
git config --global alias.l 'log --pretty=format:"%C(yellow)%h\\ %ad%Cred%d\\ %Creset%s%Cblue\\ [%cn]" --decorate'
now you should be able to use it with: git l
Ubuntu Alias
If you wish to add an alias to your shell in Ubuntu:
alias gitl='git l'

Why is my difftool not working anymore?

It used to work but after changing my laptop, it is not recognized anymore. Any help is highly appreciated!
Here is what I tried using Git Bash (git version 2.16.2.windows.1):
$ git config --list --show-origin
...
file:"C:\\Git\\mingw64/etc/gitconfig" difftool.kdiff3.cmd='C:/Program Files/KDiff3/kdiff3' $LOCAL $REMOTE
file:"C:\\Git\\mingw64/etc/gitconfig" difftool.kdiff3.keepbackup=false
file:"C:\\Git\\mingw64/etc/gitconfig" difftool.kdiff3.trustexitcode=false
file:"C:\\Git\\mingw64/etc/gitconfig" merge.conflictstyle=diff3
...
I copied the old working config file. But then:
$ git difftool master devSQC
This message is displayed because 'diff.tool' is not configured.
See 'git difftool --tool-help' or 'git help config' for more details.
'git difftool' will now attempt to use one of the following tools:
kompare emerge vimdiff
...
$ git difftool --tool-help
'git difftool --tool=<tool>' may be set to one of the following:
vimdiff
vimdiff2
vimdiff3
user-defined:
kdiff3.cmd 'C:/Program Files/KDiff3/kdiff3' $LOCAL $REMOTE
The following tools are valid, but not currently available:
araxis
bc
bc3
codecompare
deltawalker
diffmerge
diffuse
ecmerge
emerge
examdiff
gvimdiff
gvimdiff2
gvimdiff3
kdiff3
kompare
meld
opendiff
p4merge
tkdiff
winmerge
xxdiff
Some of the tools listed above only work in a windowed
environment. If run in a terminal-only session, they will fail.
$ git difftool -t=kdiff3 master devSQC
Viewing (1/61): '.gitignore'
Launch '_kdiff3' [Y/n]? y
Unknown merge tool _kdiff3
fatal: external diff died, stopping at .gitignore
You have to change this line:
git difftool -t=kdiff3 master devSQC
by either:
git difftool -t kdiff3 master devSQC
or:
git difftool --tool=kdiff3 master devSQC
Usually, short arguments like -t are followed by a space character. And long options like --tool are followed by a =. It is kind of a convention.

Add new command on Windows Git Bash

I would like to add new command on my Git Bash (just now i am under Windows OS). I tryed to look on Web different solutions but I did not find anything. The command that i like to add is:
commitall -> git add --all && git commit -m "$*"
There is a way to add this command on Windows Git Bash?
Thanks
Use Git aliases, like so:
git config --global alias.commitall '!git add --all && git commit -m'
There's no need to use $* because all the arguments you specify will simply be appended to the line above, i.e. if you run:
git comitall "a message"
…the following will be executed:
git add --all && git commit -m "a message"

How can I edit my Git config?

I feel like this issue has been addressed before, but I couldn't find it after search through a bunch of posts.
I am doing a beginner's tutorial on Git. Someone had this Mac before me and used multiple Git Applications (SourceTree, etc) that seem to have added all kinds of config preferences.
When I type git config --list, I get an enormous list (shown below), unlike the tutorial that I am watching on Lynda.com where the author only shows a list of user.name and user.email.
core.excludesfile=~/.gitignore
core.legacyheaders=false
core.quotepath=false
core.pager=less -r
mergetool.keepbackup=true
push.default=simple
color.ui=auto
color.interactive=auto
repack.usedeltabaseoffset=true
alias.s=status
alias.a=!git add . && git status
alias.au=!git add -u . && git status
alias.aa=!git add . && git add -u . && git status
alias.c=commit
alias.cm=commit -m
alias.ca=commit --amend
alias.ac=!git add . && git commit
alias.acm=!git add . && git commit -m
alias.l=log --graph --all --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(white)- %an, %ar%Creset'
alias.ll=log --stat --abbrev-commit
alias.lg=log --color --graph --pretty=format:'%C(bold white)%h%Creset -%C(bold green)%d%Creset %s %C(bold green)(%cr)%Creset %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative
alias.llg=log --color --graph --pretty=format:'%C(bold white)%H %d%Creset%n%s%n%+b%C(bold blue)%an <%ae>%Creset %C(bold green)%cr (%ci)' --abbrev-commit
alias.d=diff
alias.master=checkout master
alias.spull=svn rebase
alias.spush=svn dcommit
alias.alias=!git config --list | grep 'alias\.' | sed 's/alias\.\([^=]*\)=\(.*\)/\1\ => \2/' | sort
include.path=~/.gitcinclude
include.path=.githubconfig
include.path=.gitcredential
diff.exif.textconv=exif
credential.helper=osxkeychain
mergetool.sourcetree.cmd=--null
user.name=username
user.email=email
Ultimately, I would like to remove all of these additional settings. I tried uninstalling Git, but that didn't make a difference. Is there a command to undo all of these? Any help would be appreciated.
Your Git configuration is spread across up to three config files (one for each level).
You can edit your config (add/remove entries) by editing those files, or by using the right git-config commands (more robust, but possibly more tedious). The problem is simply to locate which part of your config is located in which config file. Instead of running
git config --list
which lists the contents of all three files (i.e. your entire Git configuration), you can run three different commands for listing the contents of each of those three config files.
System-level config file
Usually located at /usr/local/etc/gitconfig; at least, that's where mine is on my Mac (I installed Git with Homebrew). You can list its contents by running:
git config --system --list
User-level config file
Usually located at $HOME/.gitconfig. You can list its contents by running:
git config --global --list
Repository-level config file
Usually located at <repo-root-folder>/.git/config. You can list its contents by running:
git config --local --list
If you only want to retain the user.name and user.email fields from your current config and get rid of all the rest, the easiest thing is to delete all three config files and then simply run
git config --global user.name <your-name>
git config --global user.email <your-email>
(The user.name and user.email fields are most commonly set in the user-level config file.)

Resources