Existe uma maneira de usar o Winmerge dentro do git para fazer Diffs?
Existe uma maneira de usar o Winmerge dentro do git para fazer Diffs?
Respostas:
Atualização de junho de 2015, 6 anos depois:
Conforme detalhado em " git mergetool winmerge ", um simples git config diff.tool winmerge
será suficiente.
O Git 2.5+ (2º trimestre de 2015) agora reconhece o Winmerge como uma ferramenta de comparação ou fusão!
Resposta original (2009-2012)
(msysgit, 1.6.5, sessão DOS)
A primeira parte (usando o winmerge) é descrita em " Como faço para visualizar a saída 'git diff' com o programa visual diff? "
C:\myGitRepo>git config --replace --global diff.tool winmerge
C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\""
C:\myGitRepo>git config --replace --global difftool.prompt false
Com winmerge.sh
armazenado em uma parte do diretório de PATH
:
#!/bin/sh
echo Launching WinMergeU.exe: $1 $2
"$PROGRAMFILES/WinMerge/WinMergeU.exe" -e -u -dl "Local" -dr "Remote" "$1" "$2"
(consulte as opções de linha de comando do WinMerge )
git difftool
irá agora iniciar o WinMerge.
Se você deseja git diff
iniciar o WinMerge, basta definir:
set GIT_EXTERNAL_DIFF=winmerge.sh
Mas o verdadeiro valor agregado vem da capacidade de usar a mesma ferramenta de comparação para apresentar todas as diferenças em um lote, ao invés de apresentá-las sequencialmente, forçando você a fechar as janelas da ferramenta de comparação um arquivo por vez.
Atualização de junho de 2012 (2 anos e meio depois):
A comparação de diretórios em vez de arquivo por arquivo estará disponível em breve:
Veja [ANNOUNCE] Git 1.7.11.rc1 :
"
git difftool
" aprendi a--dir-diff
opção " " de gerar ferramentas diff externas que podem comparar duas hierarquias de diretório por vez após preencher dois diretórios temporários, em vez de executar uma instância da ferramenta externa uma vez por par de arquivos .
Veja " Patch difftool
: ensinar difftool
a lidar com diffs de diretório ", e a resposta " Comparação de diretório de ramificações Git " para mais detalhes.
Difftool original por script de diretórios (dezembro de 2009)
Como Seba Illingworth menciona em sua resposta , um script git-diffall.sh (também colocado no caminho) pode fazer exatamente isso:
#!/bin/sh
git diff --name-only "$@" | while read filename; do
git difftool "$@" --no-prompt "$filename" &
done
Mas isso só funciona abrindo n janelas para n arquivos (se você tentar usar a -s
opção de WinMerge, não funcionará porque os arquivos temporários foram excluídos pelo difftool muito cedo)
É por isso que gosto da abordagem de GitDiff.bat - power-diffing com GI , que permite revisar a lista de arquivos com diferenças, antes de selecionar um para examinar suas diferenças internas.
Eu ajustei para usar apenas comandos DOS
@echo off
setlocal
if "%1" == "-?" (
echo GitDiff - enables diffing of file lists, instead of having to serially
echo diff files without being able to go back to a previous file.
echo Command-line options are passed through to git diff.
echo If GIT_FOLDER_DIFF is set, it is used to diff the file lists. Default is windff.
goto END
)
if "%GIT_DIFF_COPY_FILES%"=="" (
rd /s /q %TEMP%\GitDiff
mkdir %TEMP%\GitDiff
mkdir %TEMP%\GitDiff\old
mkdir %TEMP%\GitDiff\new
REM This batch file will be called by git diff. This env var indicates whether it is
REM being called directly, or inside git diff
set GIT_DIFF_COPY_FILES=1
set GIT_DIFF_OLD_FILES=%TEMP%\GitDiff\old
set GIT_DIFF_NEW_FILES=%TEMP%\GitDiff\new
set GIT_EXTERNAL_DIFF=%~dp0\GitDiff.bat
echo Please wait and press q when you see "(END)" printed in reverse color...
call git diff %*
if defined GIT_FOLDER_DIFF (
REM This command using GIT_FOLDER_DIFF just does not work for some reason.
%GIT_FOLDER_DIFF% %TEMP%\GitDiff\old %TEMP%\GitDiff\new
goto END
)
if exist "%ProgramFiles%\Beyond Compare 2\BC2.exe" (
set GIT_FOLDER_DIFF="%ProgramFiles%\Beyond Compare 2\BC2.exe"
"%ProgramFiles%\Beyond Compare 2\BC2.exe" %TEMP%\GitDiff\old %TEMP%\GitDiff\new
goto END
)
"%ProgramFiles(x86)%\WinMerge\WinMergeU.exe" -r -e -dl "Local" -dr "Remote" %TEMP%\GitDiff\old %TEMP%\GitDiff\new
goto END
)
REM diff is called by git with 7 parameters:
REM path old-file old-hex old-mode new-file new-hex new-mode
copy %TEMP%\%~nx2 %GIT_DIFF_OLD_FILES%\%1
copy %5 %GIT_DIFF_NEW_FILES%
:END
Não é robusto o suficiente para lidar com arquivos com os mesmos nomes em diretórios diferentes, mas dá uma ideia geral do que é possível:
Aqui, apenas um WinMerge será aberto, com a lista de arquivos com diferenças internas. Você pode clicar naqueles que deseja examinar e, em seguida, um simples ESCfechará toda a WinMerge-diff
sessão.
git diff
?
c:\Temp\GitDiff\old
e c:\Temp\GitDiff\new
, não em ' /tmp
'. Tem certeza de que está executando este programa DOS a partir de uma sessão DOS (e não de uma sessão bash)?
""
no meu caso (executando o git config
comando de um CMD do Windows. Mas você está certo: ele avaliaria para ""
se executado de um shell bash.
Tive problemas ao usar a primeira parte em 2 lugares e resolvi da seguinte forma
O segundo comando para configurar winmerge.cmd exigia uma barra extra no cmdline (antes de $ LOCAL e $ REMOTE), caso contrário, o cygwin estava substituindo a variável no cmdline
C:\myGitRepo>git config --replace --global difftool.winmerge.cmd "winmerge.sh \"\$LOCAL\" \"\$REMOTE\""
alterou o arquivo winmerge.sh para (sem isso, estava obtendo erro de caminho correto inválido)
#!/bin/sh
echo Launching WinMergeU.exe: "$(cygpath -aw "$1")" "$(cygpath -aw "$2")"
"$PROGRAMFILES/WinMerge/WinMergeU.exe" -e -ub -dl "Base" -dr "Mine" "$(cygpath -aw "$1")" "$(cygpath -aw "$2")"
Como o tópico está ficando confuso e bifurcado, aqui estão as instruções consolidadas para o método WinMerge "--dir-diff" da Listagem de Diretórios para msysgit Git Windows.
Etapa 1 - Crie um arquivo chamado winmerge.sh em um local acessível ao seu caminho (como /home/bin/winmerge.sh) com o seguinte conteúdo.
#!/bin/sh
echo Launching WinMergeU.exe: $1 $2
"$PROGRAMFILES/WinMerge/WinMergeU.exe" -r -ub -dl "Remote" -dr "Local" "$1" "$2"
Etapa 2 - Digite os seguintes comandos no Git Bash para instruir o git a usar winmerge.sh como difftool (essas opções são armazenadas em /home/.gitconfig):
git config --replace --global diff.tool winmerge
git config --replace --global difftool.winmerge.cmd "winmerge.sh \"$LOCAL\" \"$REMOTE\""
git config --replace --global difftool.prompt false
Etapa 3 - Agora você pode testar digitando o seguinte comando no Git Bash para iniciar o seu diff WinMerge:
git difftool --dir-diff
Etapa 4 - Para acesso mais rápido, crie um alias para este comando adicionando esta linha a .bashrc em sua pasta inicial (ou crie o arquivo .bashrc com esta linha se o arquivo ainda não existir):
alias diffdir='git difftool --dir-diff'
Etapa 5 - Agora você pode ver rapidamente uma diferença no WinMerge apenas digitando o seguinte comando no Git Bash
diffdir
$LOCAL
e $REMOTE
.
Eu tenho um script que irá definir as ferramentas Diff e Merge na configuração do Git com os parâmetros apropriados que não requerem um arquivo .sh separado para existir. Parece estar funcionando bem para mim.
git config --global diff.tool winmerge
git config --global difftool.prompt false
git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\""
git config --global merge.tool winmerge
git config --global mergetool.prompt false
git config --global mergetool.winmerge.trustExitCode true
git config --global mergetool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\" \"\$BASE\" \"\$MERGED\""
Observação - toda a parte .cmd é citada para que os parâmetros sejam listados no .gitconfig corretamente
git config --global difftool.winmerge.cmd "\"\$PROGRAMFILES\"/WinMerge/WinMergeU.exe -r -u -e -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\""
Nota: Este comando deve ser executado a partir de um prompt de comando e não do PowerShell. Adicionar manualmente o seguinte à minha [difftool "winmerge"]
seção .gitconfig funcionou para mim: cmd = 'C:/Program Files (x86)/WinMerge/WinMergeU.exe' -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\"
git config --global mergetool.winmerge.cmd "\"C:\Program Files (x86)\WinMerge\WinMergeU.exe\" -r -u -e -dl \"Local\" -dr \"Remote\" \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\""
. Havia algumas cadeias de caracteres de escape incorretas (observe algumas barras invertidas indesejadas antes do $
- eu acho $
que não precisa ser escapado). Além disso, estava faltando um fim "
depois WinMergeU?.exe
. Corra git config --get mergetool.winmerge.cmd
para ver o que foi definido de fato. De qualquer forma, obrigado pela não .sh
versão: +1!
No Windows, você pode fazer isso desta forma:
1) Abra o arquivo .gitconfig. Ele está localizado em seu diretório inicial: c: \ users \ username.gitconfig
2) Adicione as linhas abaixo. Preste atenção às aspas simples que envolvem o caminho para o winmerge:
[diff]
tool = winmerge
[difftool "winmerge"]
cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" -e "$LOCAL" "$REMOTE"
[difftool]
prompt = false
[merge]
tool = winmerge
[mergetool "winmerge"]
cmd = "'C:/Program Files (x86)/WinMerge/WinMergeU.exe'" \"$MERGED\" \"$REMOTE\"
[mergetool]
keepBackup = false
trustExitCode = false
Sem configuração:
git difftool --tool winmerge
Supondo:
Fiquei confuso sobre por que a solução foi apresentada como um arquivo batch DOS, já que minha instalação do Git veio com um shell bash. Eu também não consegui fazer um contexto DOS rodar no bash, então tentei adaptar o que era compartilhado anteriormente em um contexto bash.
Visto que git diff
parece executar o comando especificado uma vez para cada arquivo, divido minha solução em dois scripts bash:
Primeiro, configure gitprepdiff.sh
para ser o difftool conforme mencionado anteriormente
#!/bin/sh
#echo ...gitprepdiff.sh
cp -v $1 "$TMP/GitDiff/old/$2"
cp -v $2 "$TMP/GitDiff/new"
Também observei que os resultados dos git configure
comandos podem ser encontrados e editados diretamente noC:\Users\<username>\.gitconfigure
gitdiff.sh
é então executado na linha de comando onde você normalmente chamaria git diff
#!/bin/sh
#echo Running gitdiff.sh...
DIFFTEMP=$TMP/GitDiff
echo Deleting and re-creating $DIFFTEMP...
rm -rf $DIFFTEMP;
mkdir $DIFFTEMP;
echo Creating $DIFFTEMP/old...
mkdir $DIFFTEMP/old;
echo Creating $DIFFTEMP/new...
mkdir $DIFFTEMP/new;
git diff --name-only "$@" | while read filename; do
git difftool "$@" --no-prompt "$filename";
done
"$PROGRAMFILES\WinMerge\WinMergeU.exe" -r -e -dl "Repository" -dr "Working" $LOCALAPPDATA\\Temp\\1\\GitDiff\\old $LOCALAPPDATA\\Temp\\1\\GitDiff\\new
Também vale a pena notar que, na minha instalação, /tmp
(em bash) mapeou para %LOCALAPPDATA%\Temp\1\
(no Windows), então é por isso que estou usando o último em minha chamada para WinMerge.
gitprepdiff.sh
para #!/bin/sh #echo ...gitprepdiff.sh mkdir -vp "$TMP/GitDiff/old/$(dirname $2)" cp -v $1 "$TMP/GitDiff/old/$2" cp -v --parents $2 "$TMP/GitDiff/new"
Obrigado!
git config --global diff.tool winmerge
git config --global difftool.winmerge.cmd "\"$PROGRAMFILES\\WinMerge\\WinMergeU.exe\" -u -dl \"Local\" -dr \"Remote\" \"\$LOCAL\" \"\$REMOTE\""
git config --global difftool.prompt false
De acordo com o manual de linha de comando WinMerge : "Os parâmetros são prefixados com uma barra (/) ou traço (-) caractere"