Cadê o anúncio que estava aqui?
Parece que você está usando um bloqueador de anúncios. Mas dependemos deles para continuar criando conteúdo gratuito e de qualidade para você. Se você gosta do nosso conteúdo, por favor apoie nosso site desativando seu bloqueador de anúncios. Alternativamente, se você vem aqui com frequência, por favor considere fazer uma doação.Dica para desenvolvedores que usam Git: já sentiu dificuldade ao fazer um merge? Sabia que é possível resolver conflitos com o auxílio de interfaces gráficas que facilitam bastante o trabalho? Hoje veremos dois aplicativos que podem nos ajudar a resolver conflitos: o editor de texto Atom e a ferramenta de diff e merge Meld.
Fazendo merge e resolvendo conflitos
Antes da dica propriamente dita, para garantir que estamos todos na mesma página, vejamos como normalmente se faz git merge e se resolve conflitos.
Imagine que você e um colega trabalham em um projeto de desenvolvimento e usam um repositório do Git para armazenar o código-fonte. Além do branch principal (master
), cada um possui seu próprio branch (por exemplo, antonio
e jose
). Ao terminar o desenvolvimento de uma funcionalidade, cada um deve fazer merge do seu branch para o branch principal.
Imagine também que vocês trabalharam em paralelo no mesmo arquivo, editando linhas próximas (ou as mesmas linhas), mas seu colega fez merge com o branch master
primeiro. Quando você fizer merge do seu branch com o master
, o Git acusará um conflito de arquivo:
Um exemplo que aconteceu comigo na vida real, ao trazer atualizações do upstream para um fork:
1
2
3
4
5
6
7
8
9
10
11
12
13
$ git checkout master1
$ git merge upstream1
Auto-merging publish.sh
Auto-merging libs/popper.js/1.16.0/umd/popper.js
...
Auto-merging _layouts/post.html
Auto-merging _layouts/default.html
Auto-merging _includes/sidebar.html
Auto-merging _includes/head.html
CONFLICT (content): Merge conflict in _includes/head.html
Auto-merging _includes/footer.html
CONFLICT (content): Merge conflict in _includes/footer.html
Automatic merge failed; fix conflicts and then commit the result.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ git status
On branch master1
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
modified: _includes/adsense.html
modified: _includes/sidebar.html
...
new file: libs/popper.js/1.16.0/umd/popper.min.js.map
modified: publish.sh
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
both modified: _includes/footer.html
both modified: _includes/head.html
deleted by us: _posts/2015-08-25-welcome-to-jekyll.markdown
both modified: assets/css/main.css
Em caso de conflito durante o merge, você deve editar manualmente os arquivos conflituosos, comparando as alterações que você e o seu colega fizeram, elaborar a versão final do arquivo e, por fim, executar git commit para concluir o merge.
Resolvendo conflitos com o Atom
Se você ainda não conhece, o Atom é um editor de texto feito pelo GitHub, por desenvolvedores e para desenvolvedores. Possui muitas funcionalidades, é bastante inteligente já em sua configuração padrão, mas pode receber extensões. O Atom faz lembrar o Sublime Text, mas é software livre e gratuito.
Para instalar o Atom no Linux Kamarada ou no openSUSE, baixe e instale o pacote RPM do seu site:
Ao abrir um arquivo conflituoso com o Atom, ele permite facilmente escolher entre uma versão ou outra das linhas, basta clicar no botão Use me referente à versão desejada:
Note que a decisão não precisa ser binária: você pode escolher uma das versões e editá-la para obter um meio termo. O que importa é o conteúdo final do arquivo na hora de salvar.
Resolvendo conflitos com o Meld
O Meld é uma ferramenta gráfica de diff e merge feita para desenvolvedores. Permite comparar arquivos e pastas em duas ou três vias e suporta vários sistemas de controle de versão, dentre eles o Git. Para instalar o Meld no Linux Kamarada ou no openSUSE, execute:
1
# zypper in meld meld-lang
Você pode usar o Meld sozinho, abrindo o aplicativo e selecionando os arquivos ou pastas que deseja comparar, mas não vou entrar em detalhes nesse sentido, porque nosso objetivo aqui é ver como usar o Meld integrado ao Git.
Para resolver conflitos com o Meld, execute o comando git mergetool:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ git mergetool
This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc codecompare emerge vimdiff
Merging:
_includes/footer.html
_includes/head.html
_posts/2015-08-25-welcome-to-jekyll.markdown
assets/css/main.css
Normal merge conflict for '_includes/footer.html':
{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (meld):
A função do comando git mergetool é iniciar uma ferramenta apropriada para a resolução de conflitos. Ele exibe essa mensagem comprida na primeira utilização porque ainda não configuramos uma ferramenta. Note que ele suporta várias ferramentas, dentre elas o Meld, que é a primeira da lista e é também a que ele sugere usar. Tecle Enter para iniciar o Meld.
O Meld abre o arquivo conflituoso em três vias: à esquerda, a versão anterior do branch atual (nesse exemplo, o branch master1
); no meio, a versão mesclada (esse é o resultado que irá no commit do merge); e à direita, a versão do branch que está sendo mesclado (upstream1
):
Você pode usar as setas ao lado das linhas para copiar trechos de código de um lado para o outro.
Note que também no Meld as decisões não precisam ser binárias: você pode simplesmente posicionar o cursor na via do meio e começar a digitar. A versão final do arquivo mesclado será tudo que estiver na via do meio, não importando se o conteúdo veio da via da esquerda, da via da direita ou se foi digitado à mão.
Quando terminar de resolver o conflito, clique em Salvar.
Para que o Git sempre use o Meld para resolver conflitos sem perguntar qual ferramenta usar, execute os comandos a seguir:
1
2
$ git config --global merge.tool meld
$ git config --global mergetool.prompt false
Feito isso, aquela mensagem comprida não aparecerá mais ao executar git mergetool: o Git indicará qual arquivo está mesclando e já abrirá o Meld (você não precisará teclar Enter).
Além de resolver conflitos, o Meld pode ser usado para comparar versões de arquivos controladas pelo Git.
Comparando versões de arquivos
Para comparar versões de um mesmo arquivo (por exemplo, qual a diferença entre um arquivo em um branch e esse mesmo arquivo em outro branch, ou o que mudou em um arquivo entre dois commits), você pode usar o comando git diff:
1
2
$ git checkout master1
$ git diff upstream1 -- _includes/footer.html
Nesse exemplo, queremos saber o que mudou no arquivo _includes/footer.html
do branch upstream1
(especificado como referência inicial) para o branch atual (master1
):
Talvez usando o Meld essa comparação fique mais interessante. Vejamos.
Comparando versões de arquivos com o Meld
Como se fosse uma mistura do git diff com o git mergetool é o comando git difftool:
1
$ git difftool upstream1 -- _includes/footer.html
De forma semelhante, no primeiro uso ele alerta que não foi configurado e pergunta se deseja iniciar o Meld:
1
2
3
4
5
6
7
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:
meld opendiff kdiff3 tkdiff xxdiff kompare gvimdiff diffuse diffmerge ecmerge p4merge araxis bc codecompare emerge vimdiff
Viewing (1/1): '_includes/footer.html'
Launch 'meld' [Y/n]?
Tecle Enter para iniciar o Meld. Dessa vez, ele faz uma comparação em duas vias: à esquerda, é exibida a versão especificada como referência (nesse caso, a versão do branch upstream1
), e à direita, é exibida a versão do branch atual (nesse caso, o branch master1
):
Configurar o git difftool para sempre usar o Meld sem perguntar também é parecido:
1
2
$ git config --global diff.tool meld
$ git config --global difftool.prompt false