Pergunta

Ao mesclar o ramo de tópico "B" em "A" usando git merge, recebo alguns conflitos.Eu sei que todos os conflitos podem ser resolvidos usando a versão em “B”.

Estou ciente git merge -s ours.Mas o que eu quero é algo como git merge -s theirs.

Por que isso não existe?Como posso obter o mesmo resultado após a fusão conflitante com o existente git comandos?(git checkout cada arquivo não mesclado de B)

ATUALIZAR:A "solução" de simplesmente descartar qualquer coisa do ramo A (o ponto de confirmação de mesclagem para a versão B da árvore) não é o que estou procurando.

Foi útil?

Solução

Adicione o -X opção para theirs. Por exemplo:

git checkout branchA
git merge -X theirs branchB

Tudo vai se fundir da maneira desejada.

A única coisa que vi causar problemas é se os arquivos foram excluídos do Branchb. Eles aparecem como conflitos se algo diferente do Git fez a remoção.

A correção é fácil. Apenas corra git rm com o nome de quaisquer arquivos que foram excluídos:

git rm {DELETED-FILE-NAME}

Depois disso, o -X theirs deve funcionar como esperado.

Claro, fazendo a remoção real com o git rm O comando impedirá que o conflito aconteça em primeiro lugar.


Observação: Uma opção de formulário mais longa também existe. Para usá -lo, substitua:

-X theirs

com:

--strategy-option=theirs

Outras dicas

Uma solução possível e testada para mesclar o ramo em nossa filial de check-out:

# in case branchA is not our current branch
git checkout branchA

# make merge commit but without conflicts!!
# the contents of 'ours' will be discarded later
git merge -s ours branchB    

# make temporary branch to merged commit
git branch branchTEMP         

# get contents of working tree and index to the one of branchB
git reset --hard branchB

# reset to our merged commit but 
# keep contents of working tree and index
git reset --soft branchTEMP

# change the contents of the merged commit
# with the contents of branchB
git commit --amend

# get rid off our temporary branch
git branch -D branchTEMP

# verify that the merge commit contains only contents of branchB
git diff HEAD branchB

Para automatizá -lo, você pode embrulhá -lo em um script usando BranchA e Branchb como argumentos.

Esta solução preserva o primeiro e o segundo pai do comprometimento da mesclagem, assim como seria de esperar git merge -s theirs branchB.

Versões mais antigas do git permitiam que você usasse a estratégia de mesclagem "deles":

git pull --strategy=theirs remote_branch

Mas isso já foi removido, conforme explicado nesta mensagem por Júnio Hamano (o mantenedor do Git).Conforme observado no link, em vez disso você faria o seguinte:

git fetch origin
git reset --hard origin

Tenha cuidado, porém, pois isso é diferente de uma mesclagem real.Sua solução é provavelmente a opção que você realmente procura.

Eu usei a resposta de Paul Pladijs desde agora. Eu descobri, você pode fazer uma mesclagem "normal", conflitos ocorrem, então você faz

git checkout --theirs <file>

Para resolver o conflito usando a revisão do outro ramo. Se você fizer isso para cada arquivo, você terá o mesmo comportamento que seria de esperar de

git merge <branch> -s theirs

De qualquer forma, o esforço é mais do que seria com a estratégia de mesclagem! (Isso foi testado com o Git versão 1.8.0)

Não está totalmente claro qual é o resultado desejado, então há alguma confusão sobre a maneira "correta" de fazê -lo nas respostas e nos comentários deles. Eu tento dar uma visão geral e ver as três opções a seguir:

Tente mesclar e usar B para conflitos

Isto é não a "versão deles para git merge -s ours"Mas a versão deles para git merge -X ours"(o que é abrevido para git merge -s recursive -X ours):

git checkout branchA
# also uses -s recursive implicitly
git merge -X theirs branchB

Isso é o que por exemplo ALAN W. Smith Resposta faz.

Use o conteúdo de B apenas

Isso cria um comprometimento de mesclagem para ambos os ramos, mas descarta todas as mudanças de branchA e apenas mantém o conteúdo de branchB.

# Get the content you want to keep.
# If you want to keep branchB at the current commit, you can add --detached,
# else it will be advanced to the merge commit in the next step.
git checkout branchB

# Do the merge an keep current (our) content from branchB we just checked out.
git merge -s ours branchA

# Set branchA to current commit and check it out.
git checkout -B branchA

Observe que a mesclagem compromete o primeiro pai agora é o de branchB e apenas o segundo é de branchA. Isso é o que por exemplo Resposta de Gandalf458 faz.

Use o conteúdo apenas de B e mantenha a ordem dos pais correta

Esta é a verdadeira "versão deles para git merge -s ours". Tem o mesmo conteúdo da opção antes (ou seja, apenas isso de branchB) Mas a ordem dos pais está correta, ou seja, o primeiro pai vem de branchA e o segundo de branchB.

git checkout branchA

# Do a merge commit. The content of this commit does not matter,
# so use a strategy that never fails.
# Note: This advances branchA.
git merge -s ours branchB

# Change working tree and index to desired content.
# --detach ensures branchB will not move when doing the reset in the next step.
git checkout --detach branchB

# Move HEAD to branchA without changing contents of working tree and index.
git reset --soft branchA

# 'attach' HEAD to branchA.
# This ensures branchA will move when doing 'commit --amend'.
git checkout branchA

# Change content of merge commit to current index (i.e. content of branchB).
git commit --amend -C HEAD

Isso é o que Resposta de Paul Pladijs faz (sem exigir um ramo temporário).

Eu resolvi meu problema usando

git checkout -m old
git checkout -b new B
git merge -s ours old

Se você estiver no ramo A:

git merge -s recursive -X theirs B

Testado no Git versão 1.7.8

Ao mesclar a ramificação do tópico "B" em "A" usando a mesclagem Git, recebo alguns conflitos. Eu sei que todos os conflitos podem ser resolvidos usando a versão em "B".

Estou ciente da mesclagem do git. Mas o que eu quero é algo como o Git mescle> -s deles.

Estou assumindo que você criou um ramo do mestre e agora quero voltar ao mestre, substituindo qualquer uma das coisas antigas do mestre. Foi exatamente isso que eu queria fazer quando me deparei com este post.

Faça exatamente o que você deseja fazer, exceto mesclar um ramo no outro primeiro. Eu apenas fiz isso, e funcionou muito bem.

git checkout Branch
git merge master -s ours

Em seguida, check -out mestre e mescle seu ramo nela (vai correr bem agora):

git checkout master
git merge Branch

Para realmente fazer uma mesclagem que leva Entrada do ramo que você está se fundindo, você pode fazer

git merge --strategy=ours ref-to-be-merged

git diff --binary ref-to-be-merged | git apply --reverse --index

git commit --amend

Não haverá conflitos em nenhum cenário que eu conheça, você não precisa fazer ramos adicionais e age como um comprometimento normal de mesclagem.

Isso não é bom com submódulos, no entanto.

Ver Resposta amplamente citada de Junio ​​Hamano:se você for descartar o conteúdo confirmado, apenas descarte os commits ou, de qualquer forma, mantenha-o fora do histórico principal.Por que incomodar todos no futuro lendo mensagens de commits que não têm nada a oferecer?

Mas às vezes existem requisitos administrativos, ou talvez por algum outro motivo.Para aquelas situações em que você realmente precisa registrar commits que não contribuem em nada, você deseja:

(editar:uau, eu consegui errar antes.Este funciona.)

git update-ref HEAD $(
        git commit-tree -m 'completely superseding with branchB content' \
                        -p HEAD -p branchB    branchB:
)
git reset --hard

Por que isso não existe?

Embora eu mencione em "Comando git para fazer um branch igual a outro"como simular git merge -s theirs, observe que o Git 2.15 (quarto trimestre de 2017) agora está mais claro:

A documentação para '-X<option>'Pois fusão foi enganosamente escrito para sugerir que "-s theirs" existe, o que não é o caso.

Ver confirmar c25d98b (25 de setembro de 2017) por Júnio C Hamano (gitster).
(Mesclado por Júnio C Hamano-- gitster -- em confirmar 4da3e23, 28 de setembro de 2017)

estratégias de mesclagem:evite insinuar que "-s theirs" existe

A descrição de -Xours a opção de mesclagem tem uma nota entre parênteses que diz aos leitores que é muito diferente de -s ours, que é correto, mas a descrição de -Xtheirs que segue -o descuidadamente diz "este é o oposto de ours", dando uma falsa impressão de que os leitores também precisam ser avisados ​​de que é muito diferente de -s theirs, que na realidade nem existe.

-Xtheirs é um opção de estratégia aplicado à estratégia recursiva.Isso significa que a estratégia recursiva ainda mesclará tudo o que puder e retornará apenas para "theirs"lógica em caso de conflitos.

Esse debate sobre a pertinência ou não de uma theirs estratégia de fusão foi trazida de volta recentemente neste setembro.Tópico de 2017.
Ele reconhece tópicos mais antigos (2008)

Em suma, a discussão anterior pode ser resumida em "não queremos"-s theirs', pois incentiva o fluxo de trabalho errado".

Ele menciona o apelido:

mtheirs = !sh -c 'git merge -s ours --no-commit $1 && git read-tree -m -u $1' -

Yaroslav Halchenko tenta defender mais uma vez essa estratégia, mas Júnio C.Hamano acrescenta:

A razão pela qual a nossa e a deles não são simétricas é porque você é você e não eles – o controle e a propriedade de nossa história e da história deles não são simétricos.

Depois de decidir que a história deles é a linha principal, você prefere tratar sua linha de desenvolvimento como um ramo secundário e fazer uma fusão nessa direção, ou seja,o primeiro pai da mesclagem resultante é um commit em seu histórico e o segundo pai é o último pai ruim do seu histórico.Então você acabaria usando "checkout their-history && merge -s ours your-history"Para manter a primeira parentidade sensata.

E nesse ponto, o uso de "-s ours"não é mais uma solução alternativa por falta de"-s theirs".
É uma parte adequada da semântica desejada, ou seja,do ponto de vista da linha histórica canônica sobrevivente, você quer preservar o que ela fez, anulando o que a outra linha da história fez.

Este usa uma leitura de comando de encanamento Git, mas cria um fluxo de trabalho geral mais curto.

git checkout <base-branch>

git merge --no-commit -s ours <their-branch>
git read-tree -u --reset <their-branch>
git commit

# Check your work!
git diff <their-branch>

Isso vai mesclar seu newbranch no BaseBranch existente

git checkout <baseBranch> // this will checkout baseBranch
git merge -s ours <newBranch> // this will simple merge newBranch in baseBranch
git rm -rf . // this will remove all non references files from baseBranch (deleted in newBranch)
git checkout newBranch -- . //this will replace all conflicted files in baseBranch

Eu acho que o que você realmente quer é:

git checkout -B mergeBranch branchB
git merge -s ours branchA
git checkout branchA
git merge mergeBranch
git branch -D mergeBranch

Isso parece desajeitado, mas deve funcionar. O único pensamento que eu realmente não gosto dessa solução é que o histórico do Git será confuso ... mas pelo menos a história será completamente preservada e você não precisará fazer algo especial para arquivos excluídos.

O equivalente (que mantém a ordem dos pais) para 'Git mesclar -s deles Branchb'

Antes da mesclagem:enter image description here

!!! Certifique -se de que você está em estado limpo !!!

Faça a mesclagem:

git commit-tree -m "take theirs" -p HEAD -p branchB 'branchB^{tree}'
git reset --hard 36daf519952 # is the output of the prev command

O que fizemos ? Criamos um novo compromisso que dois pais nossos e deles e o contador da confirmação são Branchb - deles

Após a mesclagem:enter image description here

Mais precisamente:

git commit-tree -m "take theirs" -p HEAD -p 'SOURCE^{commit}' 'SOURCE^{tree}'

Esta resposta foi dada por Paul Pladijs. Acabei de receber seus comandos e fiz um pseudônimo de git por conveniência.

Edite seu .GitConfig e adicione o seguinte:

[alias]
    mergetheirs = "!git merge -s ours \"$1\" && git branch temp_THEIRS && git reset --hard \"$1\" && git reset --soft temp_THEIRS && git commit --amend && git branch -D temp_THEIRS"

Então você pode "Git mescle -s deles a" executando:

git checkout B (optional, just making sure we're on branch B)
git mergetheirs A

Recentemente, eu precisava fazer isso para dois repositórios separados que compartilham uma história comum. Comecei com:

  • Org/repository1 master
  • Org/repository2 master

Eu queria todas as mudanças de repository2 master a ser aplicado a repository1 master, aceitar todas as mudanças que o repositório2 faria. Em termos de Git, este deve ser uma estratégia chamada -s theirs Mas não existe. Tenha cuidado porque -X theirs é nomeado como seria o que você quer, mas é NÃO o mesmo (até diz isso na página do homem).

A maneira como eu resolvi isso era ir para repository2 e fazer um novo ramo repo1-merge. Naquele ramo, eu corri git pull git@gitlab.com:Org/repository1 -s ours E se funde bem sem problemas. Eu então empurro para o controle remoto.

Então eu volto para repository1 e fazer um novo ramo repo2-merge. Nesse ramo, eu corro git pull git@gitlab.com:Org/repository2 repo1-merge que será concluído com problemas.

Finalmente, você precisaria emitir uma solicitação de mesclagem em repository1 Para torná -lo o novo mestre, ou apenas mantê -lo como um ramo.

Uma maneira simples e intuitiva (na minha opinião) de duas etapas é

git checkout branchB .
git commit -m "Picked up the content from branchB"

Seguido por

git merge -s ours branchB

(que marca os dois ramos como mesclados)

A única desvantagem é que ele não remove arquivos que foram excluídos no Branchb da sua ramificação atual. Uma diferença simples entre as duas ramificações depois mostrará se houver desses arquivos.

Essa abordagem também deixa claro o registro de revisão depois do que foi feito - e o que se destinava.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top