Resolver conflitos de mesclagem do Git em favor de suas alterações durante um pull

1226

Como resolvo um conflito de mesclagem do git em favor de alterações puxadas?

Basicamente, preciso remover todas as alterações conflitantes de uma árvore de trabalho sem ter que passar por todos os conflitos por um git mergetooltempo mantendo todas as alterações sem conflitos. De preferência, fazendo isso enquanto puxa, não depois.

sanmai
fonte
3
possível duplicação da mesclagem
2
Duplicar o git pull do controle remoto .. posso forçá-lo a substituir, em vez de relatar conflitos? Você pode ver a mesma solução lá.
Dan Dascalescu
3
@DanDascalescu A resposta aceita não responde a essas perguntas, portanto, claramente, não é uma duplicata. Além disso, essa outra pergunta é bastante ambígua: é muito difícil dizer o que é solicitado. Apesar de tudo, não posso concordar com você. O que você aponta nisso?
sanmai
2
@smamai Você tem duas respostas - e você aceitou uma delas. Você pode explicar melhor o que você está esperando em uma resposta e quanto mais detalhes você deseja aqui?
Edward Thomson
2
@EdwardThomson bem, na verdade eu estava pensando em dar a esta reputação para a primeira resposta, mas se você perguntar, eu poderia esperar e ver se uma resposta melhor vem à tona
sanmai

Respostas:

1219
git pull -s recursive -X theirs <remoterepo or other repo>

Ou, simplesmente, para o repositório padrão:

git pull -X theirs

Se você já está em estado de conflito ...

git checkout --theirs path/to/file
Pascal Fares
fonte
40
Observe que -s recursiveaqui é redundante, pois essa é a estratégia de mesclagem padrão. Então você pode simplificá-lo git pull -X theirs, o que é basicamente equivalente a git pull --strategy-option theirs.
5
Se eu fizer isso, volto ao MERGINGestado. Posso então git merge --aborttentar novamente, mas cada vez que acabo com uma mesclagem. … Eu sei que uma rebase foi enviada para o meu upstream, então talvez isso esteja causando isso?
Benjohn 14/07/16
22
Tenha cuidado com git checkout --theirs path/to/file. Usou-o durante o rebase e obteve resultados inesperados. Explicação encontrada no doc: Observe que durante o git rebase e o git pull --rebase, o nosso e o deles podem aparecer trocados; --ours fornece a versão do ramo em que as alterações são reformuladas, enquanto --theirs fornece a versão do ramo que mantém o seu trabalho que está sendo reformulado.
Vuk Djapic
10
Observe que a git checkout --theirs/--ours pathpágina de manual afirma que funciona para caminhos não mesclados . Portanto, se não houver conflito no caminho, ele já estará mesclado. Este comando não fará nada. Isso pode ocorrer quando você deseja, por exemplo, a versão 'deles' de uma subpasta inteira. Portanto, nesse caso, seria mais seguro fazer git checkout MERGE_HEAD pathou usar o hash de confirmação.
fsw
4
git pull -X theirscria uma confirmação de mesclagem se houver conflitos (por exemplo, se outro commit for executado git push -fno controle remoto). Se você não deseja consolidação de mesclagem, execute git fetch && git reset --hard origin/master.
Dan Dascalescu 23/01
985

Você pode usar a opção de estratégia "deles" recursiva :

git merge --strategy-option theirs

Do homem :

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

Nota: como a página de manual diz, a opção de estratégia de mesclagem "nossa" é muito diferente da estratégia de mesclagem "nossa" .

Ikke
fonte
Aqui está uma explicação mais detalhada: lostechies.com/joshuaflanagan/2010/01/29/…
mPrinC
227
Também git checkout --theirspara operar em um único arquivo conflitante
dvd
48
Isso não funciona se você já estiver no estado de resolução de conflitos. Nesse caso, acredito que a melhor maneira de resolver é git checkout <ref to theirs> -- the/conflicted.file; e depois git addas mudanças deles.
ThorSummoner
54
@ThorSummoner Nesse caso, existe o git checkout - seu caminho / do / arquivo. Dessa forma, você não precisa procurar manualmente o hash correto.
Ikke
8
@ Ikke Essa deve ser basicamente a sua própria resposta (e a resposta aceita) se você me perguntar.
ThorSummoner
473

Se você já está em estado de conflito e deseja apenas aceitar todos :

git checkout --theirs .
git add .

Se você quiser fazer o oposto:

git checkout --ours .
git add .

Isso é bastante drástico, por isso, certifique-se de que realmente deseja limpar tudo dessa maneira antes de fazê-lo.

muito a aprender
fonte
47
ou, não use .e especifique o (s) arquivo (s) no lugar do ponto que você deseja fazer o checkout. menos "drástico" e exatamente o que você quer fazer, presumivelmente.
manroe
10
isso não funciona se o arquivo foi removido do outro ramo: '<arquivo>' não tem sua versão
Japster24
3
Gostaria de votar mais se pudesse, continuando voltando a esta resposta de vez em quando.
tarikki
6
Use git add -upara ignorar arquivos que não estão sob controle de versão.
Sudipta Basak 27/10
3
Caso hipotético, três alterações em um arquivo, uma conflitante, duas sem conflito, essa solução aplicaria alterações não conflitantes e resolveria a alteração conflitante à nossa? Ou seria necessária apenas a nossa versão, ignorando as alterações não conflitantes?
28817 pedromarce
222

OK, imagine o cenário em que eu estava:

Você tenta um merge, ou talvez um cherry-pick, e é interrompido com

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

Agora, você visualiza o arquivo em conflito e não deseja realmente manter suas alterações. No meu caso acima, o arquivo estava em conflito com apenas uma nova linha que meu IDE havia adicionado automaticamente. Para desfazer suas alterações e aceitar as delas, a maneira mais fácil é:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

O inverso disso (para substituir a versão recebida pela sua versão) é

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Surpreendentemente, não consegui encontrar essa resposta com muita facilidade na Internet.

Theodore R. Smith
fonte
15
Observe que, se alguém executa um git statusentre checkoute add, o arquivo ainda é exibido como "ambos modificados".
bispo
Você sabe se existe uma maneira de fazer isso para todos os arquivos que estão em estado de conflito? Nesse caso, seria uma boa extensão para sua resposta.
de Drew Noakes
2
Eu faço isso: git reset --hard e então git pull [remote server name] [branch name] -Xtheirs(desfaz a mesclagem, em seguida, coloca as novas coisas em cima das minhas) - não tenho certeza se é isso que você deseja.
Ssaltman # 22/18
38

As git pull -X theirsrespostas podem criar uma confirmação de mesclagem feia ou emitir um

erro: suas alterações locais nos seguintes arquivos seriam substituídas por mesclagem:

Se você deseja simplesmente ignorar quaisquer modificações locais nos arquivos do repositório, por exemplo, em um cliente que sempre deve ser um espelho de uma origem, execute isso (substitua masterpela ramificação desejada):

git fetch && git reset --hard origin/master

Como funciona? git fetchfaz git pullmas sem mesclar . Em seguida, git reset --hardfaz sua árvore de trabalho corresponder ao último commit. Todas as alterações locais nos arquivos no repositório serão descartadas , mas os novos arquivos locais serão deixados em paz.

Dan Dascalescu
fonte
1
+1 - git fetch && git reset --hard {remote}/{branch}foi o que resolveu meu problema. Eu precisava abandonar completamente minhas próprias alterações em favor do estado "deles" de uma ramificação, mas o git pull -X theirssufoquei em alguns arquivos movidos / renomeados. Obrigado!
Ivaylo Slavov
23

Após a fusão do git, se você tiver conflitos e quiser o seu

git checkout --theirs .
git checkout --ours .
Mohit Kanojia
fonte
Como eu faria isso em uma base por bloco conflitante? O procedimento acima funciona no nível do arquivo, descartando quaisquer pedaços não conflitantes que um arquivo conflitante possa ter.
Jani
21

Para resolver todos os conflitos com a versão em uma ramificação específica:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

Portanto, se você já está no estado de mesclagem e deseja manter a versão principal dos arquivos conflitantes:

git diff --name-only --diff-filter=U | xargs git checkout master
Ariel Alvarez
fonte
E para pessoas no Windows sem acesso ao pipe xargs, como isso se traduz?
tsemer
Não ignoraria suas alterações completamente? Mesmo aqueles que não estão em estado de conflito?
Valentin Heinitz 15/01/2019
Foi isso que acabei fazendo. Infelizmente, subsequentemente, é necessário um comando git cherry-pick --continue ou um git commit --allow-emptycomando para confirmar essas alterações, e parece não haver um sistema por trás do qual o comando seja necessário, o que torna a automação um problema. Atualmente, estou resolvendo isso testando a existência de um .git/COMMIT_EDITMSGarquivo, mas isso parece hacky e quebradiço, e ainda não estou convencido de que ele sempre funcione.
Konrad Rudolph
Isso é bom, significa que, se você resolver alguns (e faz git add) manualmente , poderá resolver o restante em massa por isso. git checkout --ours/ git checkout --theirsÉ útil também.
rcoup 25/03
18

Por favor, não que às vezes isso não funcione :

git checkout - o nosso caminho / para / arquivo

ou

git checkout - seu caminho / para / arquivo

Eu fiz isso, assumindo que HEAD é nosso e MERGE_HEAD é deles

git checkout HEAD -- path/to/file

ou:

git checkout MERGE_HEAD -- path/to/file

Depois que fazemos isso e somos bons:

git add .

Se você quiser entender mais, consulte o maravilhoso post do torek aqui: git checkout --ours não remove arquivos da lista de arquivos não imersos

Nicolas D
fonte
12

Usuários do IDE do código VS (Git integrado):

Se você deseja aceitar todas as alterações recebidas no arquivo de conflito , execute as seguintes etapas.

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

Da mesma forma, você pode fazer outras opções, como Aceitar todos os dois, Aceitar todos os atuais etc.,

SridharKritha
fonte
2
Isso parece funcionar apenas para um único arquivo, embora nem todos os arquivos com conflitos.
Yoryo 18/07/19
1

Eu tinha uma next-versionramificação de longa duração com toneladas de exclusões em arquivos que foram alteradosdevelop , arquivos que foram adicionados em locais diferentes nos dois ramos etc.

Eu queria levar todo o conteúdo do next-versionramo paradevelop , tudo em um imenso commit de mesclagem.

A combinação dos comandos acima que funcionou para mim foi:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

Não é uma resposta nova, apenas combina bits de muitas respostas, em parte para garantir que você pode precisar de todas essas respostas.

Gordon
fonte
1

Se você já está em estado de conflito e não deseja fazer o checkout do caminho um por um. Você pode tentar

git merge --abort
git pull -X theirs
Lee Chee Kiam
fonte
-1

from https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging

Isso basicamente fará uma fusão falsa. Ele gravará um novo commit de mesclagem com os dois ramos como pais, mas nem olhará para o ramo no qual você está mesclando. Ele simplesmente registrará como resultado da mesclagem do código exato no seu ramo atual.

$ git merge -s ours mundo

Mesclagem feita pela estratégia 'nossa'.

$ git diff HEAD HEAD~

Você pode ver que não há diferença entre o ramo em que estávamos e o resultado da mesclagem.

Geralmente, isso pode ser útil para convencer o Git a pensar que um ramo já foi mesclado ao fazer uma mesclagem posteriormente. Por exemplo, digamos que você ramificou um ramo de lançamento e fez algum trabalho nele que desejará mesclar de volta ao seu ramo mestre em algum momento. Enquanto isso, algumas correções de bugs no mestre precisam ser portadas para o seu ramo de lançamento. Você pode mesclar o ramo de correções de erros no ramo de lançamento e também mesclar o mesmo ramo em seu ramo mestre (mesmo que a correção já esteja lá); portanto, quando você mesclar o ramo de lançamento mais tarde, não haverá conflitos com o ramo de correção.

Uma situação que considero útil se quiser que o mestre reflita as alterações de um novo ramo de tópico. Notei que -Xtheirs não se fundem sem conflitos em algumas circunstâncias ... por exemplo

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

Nesse caso, a solução que encontrei foi

$ git checkout topicFoo

do topicFoo, primeiro mescle no master usando a estratégia -s our, isso criará o commit falso que é apenas o estado do topicFoo. $ git merge -s nosso mestre

verifique a consolidação de mesclagem criada

$ git log

agora faça o checkout do ramo principal

$ git checkout master

mesclar o ramo do tópico de volta, mas desta vez usar a estratégia recursiva -Xtheirs, agora você apresentará um ramo mestre com o estado do topicFoo.

$ git merge -X theirs topicFoo
Amos Folarin
fonte