Resolvendo um conflito do Git com arquivos binários

464

Eu tenho usado o Git no Windows (msysgit) para rastrear alterações em alguns trabalhos de design que tenho realizado.

Hoje estou trabalhando em um PC diferente (com repo remoto brian) e agora estou tentando mesclar as edições feitas hoje novamente na minha versão local normal no meu laptop.

No meu laptop, eu costumava git pull brian mastercolocar as alterações na minha versão local. Tudo estava bem, exceto o documento principal do InDesign - isso mostra como um conflito.

A versão no PC ( brian) é a mais recente que desejo manter, mas não sei quais comandos dizem ao repositório para usá-lo.

Tentei copiar diretamente o arquivo no meu laptop, mas isso parece interromper todo o processo de mesclagem.

Alguém pode me apontar na direção certa?

Kevin Wilson
fonte

Respostas:

854

git checkoutaceita uma opção --oursou --theirspara casos como este. Portanto, se você tiver um conflito de mesclagem e souber que deseja apenas o arquivo da ramificação na qual está mesclando, poderá:

$ git checkout --theirs -- path/to/conflicted-file.txt

para usar essa versão do arquivo. Da mesma forma, se você sabe que deseja sua versão (não a que está sendo mesclada), pode usar

$ git checkout --ours -- path/to/conflicted-file.txt
mipadi
fonte
47
Eu tive que executar o 'git reset HEAD path / to / conflicted-file.txt' no arquivo antes de usar --ours, caso contrário, parecia não ter efeito.
Zitrax 13/10
6
@Zitrax Você alterou o arquivo após a execução git checkout --ours? A página de manual sugere (IMHO) que o checkout --ours / - deles removerá a alteração da lista "ambos modificados, precisam ser mesclados" e a incluirá no índice, e acho que isso não está correto. Acredito que você precisará executar git addapós o checkout.
Tim Keating
15
Nota: você ainda deseja fazer "git add conflicted-file.txt " e "git commit". Comodamente, quando tentei, a mensagem de confirmação foi preenchida previamente com uma nota sobre o conflito.
Edward Falk
2
o fraseado de "o ramo em que você está mesclando" está perigosamente próximo de "o ramo em que você está mesclando", acho que apenas abandonar a preposição seria melhor: "o ramo em que você está mesclando", que também refletirá o comando git (ie git merge branch_name)
precisa saber é o seguinte
13
Alguns pontos importantes que sempre faltam nas explicações deste tópico. Ao fazer a rebase ao invés de mesclar, o significado de --theire --oursé trocado, ou seja, - o ramo == atualmente com check-out e --ours é o ramo, geralmente um ramo remoto ou especificação de caminho que você está tentando mesclar no atual ramo. A [space]--[space]opção desambigua a especificação do caminho entre o nome do ramo e o caminho que ambos existem com o mesmo nome (por exemplo, um nome do ramo existente é "abc" e existe um diretório chamado "abc").
BoiseBaked
147

Você precisa resolver o conflito manualmente (copiando o arquivo) e depois confirmar o arquivo (não importa se você o copiou ou usou a versão local) como este

git commit -a -m "Fix merge conflict in test.foo"

O Git normalmente se confirma automaticamente após a mesclagem, mas quando detecta conflitos que não pode resolver por si só, aplica todos os patches descobertos e deixa o resto para você resolver e confirmar manualmente. A página de manual do Git Merge , o curso de falha do Git-SVN ou esta entrada de blog pode lançar alguma luz sobre como deve funcionar.

Editar: veja a postagem abaixo, você não precisa copiar os arquivos, mas pode usar

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

para selecionar a versão do arquivo que você deseja. A cópia / edição do arquivo será necessária apenas se você desejar uma mistura das duas versões.

Por favor, marque a resposta mipadis como a correta.

VolkA
fonte
1
Obrigado por isso. Eu não tinha certeza se havia algum tipo de build-in para marcar um arquivo como o 'correto'. Explica por que eu não consegui encontrar o comando inexistente!
214 Kevin Kevin Wilson
Yep, isso é um pouco unintuitive - algo como resolver git seria bom, mas também seria um passo extra ...
VolkA
120

Você também pode superar esse problema com

git mergetool

o que causa gita criação de cópias locais do binário em conflito e gera seu editor padrão neles:

  • {conflicted}.HEAD
  • {conflicted}
  • {conflicted}.REMOTE

Obviamente, você não pode editar arquivos de binários em um editor de texto. Em vez disso, você copia o novo {conflicted}.REMOTEarquivo {conflicted}sem fechar o editor. Então, quando você fechar, o editor gitverá que a cópia de trabalho não decorada foi alterada e seu conflito de mesclagem é resolvido da maneira usual.

RobM
fonte
8
Se os arquivos forem grandes ou você não quiser correr o risco de abrir o binário em um editor de texto, pressione ctrl + c no prompt mergetool (" Hit return to start merge resolution tool") e o git deixará os arquivos extras no lugar. Em seguida, você pode modificá-los ou mesclá-los em uma ferramenta externa (útil para formatos de documentos binários como LibreOffice / OpenOffice / MSWord) e salvar o resultado novamente no nome do arquivo original. Para informar ao git que o conflito foi resolvido, git addo nome do arquivo original e você pode concluir a confirmação de mesclagem.
Felix
18

Para resolver mantendo a versão em sua ramificação atual (ignore a versão da ramificação na qual você está mesclando), basta adicionar e confirmar o arquivo:

git commit -a

Para resolver substituindo a versão em sua ramificação atual pela versão da ramificação em que você está mesclando, é necessário recuperar essa versão primeiro em seu diretório de trabalho e, em seguida, adicionar / confirmar:

git checkout otherbranch theconflictedfile
git commit -a

Explicado em mais detalhes

Joshua Flanagan
fonte
1
Prefiro essa variante à resposta aceita, porque é mais intuitiva, especialmente considerando que o significado desses "- nossos" e "- deles" é trocado em caso de rebaseamento.
Antony Hatchkins
11

A resposta de mipadi não funcionou muito bem para mim, eu precisava fazer o seguinte:

git checkout - o nosso caminho / para / file.bin

ou, para manter a versão sendo mesclada:

git checkout - seu caminho / para / file.bin

então

git add caminho / para / file.bin

E então eu pude fazer o "git mergetool" novamente e continuar no próximo conflito.

kris
fonte
6

Dos git checkoutdocumentos

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
Ao verificar caminhos a partir do índice, verifique o estágio # 2 ( ours) ou # 3 ( theirs) quanto a caminhos não imersos.

O índice pode conter entradas não mescladas devido a uma falha na mesclagem anterior. Por padrão, se você tentar fazer check-out dessa entrada no índice, a operação de check-out falhará e nada será retirado. O uso -fignorará essas entradas não imersas. O conteúdo de um lado específico da mesclagem pode ser retirado do índice usando --oursou --theirs. Com -m, as alterações feitas no arquivo da árvore de trabalho podem ser descartadas para recriar o resultado da mesclagem em conflito original.

user456814
fonte
4

Me deparei com um problema semelhante (querer extrair uma confirmação que incluía alguns arquivos binários que causavam conflitos quando mesclados), mas me deparei com uma solução diferente que pode ser feita inteiramente usando o git (ou seja, não é necessário copiar manualmente os arquivos). Pensei em incluí-lo aqui para que, pelo menos, eu me lembre da próxima vez que precisar. :) As etapas são assim:

% git fetch

Isso busca as confirmações mais recentes do repositório remoto (pode ser necessário especificar um nome de filial remota, dependendo da configuração), mas não tenta mesclá-las. Ele registra a confirmação em FETCH_HEAD

% git checkout FETCH_HEAD stuff/to/update

Isso pega a cópia dos arquivos binários que eu quero e substitui o que está na árvore de trabalho com a versão obtida na ramificação remota. O git não tenta fazer nenhuma fusão, então você acaba com uma cópia exata do arquivo binário da ramificação remota. Feito isso, você pode adicionar / confirmar a nova cópia como normalmente.

Brian Webster
fonte
4

Este procedimento é para resolver conflitos de arquivos binários após o envio de uma solicitação pull ao Github:

  1. Portanto, no Github, você encontrou sua solicitação de recebimento em conflito com um arquivo binário.
  2. Agora volte para a mesma ramificação git no seu computador local.
  3. Você (a) refaz / reconstrói esse arquivo binário novamente e (b) confirma o arquivo binário resultante nesse mesmo ramo git.
  4. Em seguida, você envia esse mesmo ramo git novamente para o Github.

No Github, em sua solicitação de recebimento, o conflito deve desaparecer.

david m lee
fonte
Este é exatamente o procedimento que eu preciso #
Huifang Feng 06/04/19
2

Se o binário for algo além de uma dll ou algo que possa ser editado diretamente como uma imagem ou um arquivo de mesclagem (e você não precisar lixeira / selecionar um arquivo ou outro), uma mesclagem real seria algo como:

Sugiro procurar uma ferramenta diff orientada para o que você é arquivo binário, por exemplo, existem alguns gratuitos para arquivos de imagem, por exemplo

e compare-os.

Se não houver uma ferramenta diff disponível para comparar seus arquivos, se você tiver o gerador original do arquivo bin (ou seja, existe um editor para ele ... como o blender 3d, você poderá inspecionar manualmente esses arquivos, também consulte os logs e pergunte à outra pessoa o que você deve incluir) e faça uma saída dos arquivos com https://git-scm.com/book/es/v2/Git-Tools-Advanced-Merging#_manual_remerge

$ git show :1:hello.blend > hello.common.blend $ git show :2:hello.blend > hello.ours.blend $ git show :3:hello.blend > hello.theirs.blend

tyoc213
fonte
1

Eu me deparei com duas estratégias para gerenciar a difusão / mesclagem de arquivos binários com o Git no Windows.

  1. O Tortoise git permite configurar ferramentas de difusão / mesclagem para diferentes tipos de arquivos, com base em suas extensões. Veja 2.35.4.3. Configurações avançadas de difusão / mesclagem http://tortoisegit.org/docs/tortoisegit/tgit-dug-settings.html . É claro que esta estratégia depende de ferramentas adequadas de difusão / mesclagem disponíveis.

  2. Usando atributos git, você pode especificar uma ferramenta / comando para converter seu arquivo binário em texto e, em seguida, deixar sua ferramenta diff / merge padrão fazer isso. Consulte http://git-scm.com/book/it/v2/Customizing-Git-Git-Attributes . O artigo ainda dá um exemplo do uso de metadados para imagens diff.

Eu tenho as duas estratégias para trabalhar com arquivos binários de modelos de software, mas seguimos com o tartartoise git, pois a configuração era fácil.

BoJohDoh
fonte
0

Uso o aplicativo Git Workflow for Excel - https://www.xltrail.com/blog/git-workflow-for-excel para resolver a maioria dos meus problemas de mesclagem de arquivos binários. Este aplicativo de código aberto me ajuda a resolver problemas de forma produtiva sem gastar muito tempo e permite escolher a versão correta do arquivo sem qualquer confusão.

Siddhartha Thota
fonte
0

meu caso parece um bug .... usando git 2.21.0

Eu fiz um puxão ... queixou-se de arquivos binários:

warning: Cannot merge binary files: <path>
Auto-merging <path>
CONFLICT (content): Merge conflict in <path>
Automatic merge failed; fix conflicts and then commit the result.

E então, nenhuma das respostas aqui resultou em qualquer resultado que fizesse sentido.

Se eu olhar para qual arquivo tenho agora ... é o que editei. Se eu fizer:

git checkout --theirs -- <path>
git checkout --ours -- <path>

Eu recebo saída:

Updated 0 paths from the index

e ainda tenho minha versão do arquivo. Se eu confirmar e, em seguida, efetuar o check-out, ele digitará 1, mas ainda me fornecerá minha versão do arquivo.

git mergetool diz

No files need merging

e status git diz

    All conflicts fixed but you are still merging.
    (use "git commit" to conclude merge)

Uma opção é desfazer o commit ... mas eu tive azar e tive muitos commits, e esse ruim foi o primeiro. Não quero perder tempo repetindo isso.

Então, para resolver essa loucura:

Eu apenas corri

git commit

que perde a versão remota e provavelmente desperdiça algum espaço armazenando um arquivo binário extra ...

git checkout <commit where the remote version exists> <path>

o que me devolve a versão remota

depois editou o arquivo novamente ... e, em seguida, confirma e empurra, o que provavelmente significa perda de espaço com outra cópia do arquivo binário.

Pedro
fonte
No meu caso, depois de tentar git checkout --ours <path>recebi Updated 0 paths from the index . Eu consertei isso com o git add <path>comando, que faz o mesmo.
Andriy