Como mesclar alterações em um único arquivo, em vez de mesclar confirmações?

383

Tenho duas ramificações (A e B) e quero mesclar um único arquivo da ramificação A com um arquivo único correspondente da ramificação B.

Isuru
fonte
2
Já discutido aqui stackoverflow.com/questions/449541/…
positron
27
A maioria das respostas a essa outra postagem é sobre como mesclar seletivamente confirmações , não arquivos . Isso torna a resposta selecionada incorreta. A questão permanece sem resposta.
Esta resposta é o caminho a seguir, IMO. git diff branch_name > patch git apply patch. stackoverflow.com/a/9473543/1091853
blamb

Respostas:

631

Me deparei com o mesmo problema. Para ser mais preciso, tenho duas ramificações Ae Bos mesmos arquivos, mas uma interface de programação diferente em alguns arquivos. Agora, os métodos de arquivo f, que são independentes das diferenças de interface nos dois ramos, foram alterados no ramo B, mas a alteração é importante para os dois ramos. Assim, eu preciso mesclar apenas arquivo fde ramificação Bem arquivo fde ramificação A.

Um comando simples já resolveu o problema para mim se eu assumir que todas as alterações foram confirmadas nos dois ramos Ae B:

git checkout A

git checkout --patch B f

O primeiro comando muda para ramificação A, para onde eu quero mesclar Ba versão do arquivo f. O segundo comando corrige o arquivo fcom fde HEADde B. Você pode até aceitar / descartar partes únicas do patch. Em vez de Bvocê pode especificar qualquer confirmação aqui, não precisa ser HEAD.

Edição na comunidade : se o arquivo fativado Bainda não existir A, omita a --patchopção. Caso contrário, você receberá uma "Sem alteração". mensagem.

loup
fonte
10
Isso funciona apenas se você deseja atualizar um arquivo. E se eu quiser adicionar um novo arquivo da ramificação B à ramificação A?
Umair A.
25
@UmairAshraf, você poderá adicionar um novo arquivo de B a A removendo a opção --patch.
11264 bbb
9
Hmmm ... quando tento isso, recebo a mensagem "sem alterações", mas claramente há alterações. OK, eu precisava estar na pasta onde estava o arquivo relevante. Edit: Esta poderia ser a minha solução favorita para um problema que eu já vi no stackoverflow :-D
bot_bot
2
Eu tive que usar git checkout --patch B -- fpara fazer isso funcionar.
user545424
8
Apenas é necessário adicionar que, se você tiver várias alterações (blocos) no arquivo e desejar preparar todas elas , poderá pressionar adurante a fase interativa, em vez de pressionar ytodas as vezes. Ou use o git checkout B -- fcomando.
Dmitry Gonchar
17

Aqui está o que eu faço nessas situações. É uma confusão, mas funciona muito bem para mim.

  1. Crie outro ramo com base no seu ramo de trabalho.
  2. O git pull / git mescla a revisão (SHA1) que contém o arquivo que você deseja copiar. Portanto, isso mesclará todas as suas alterações, mas estamos usando apenas esse ramo para obter o único arquivo.
  3. Corrija quaisquer conflitos, etc. investigue seu arquivo.
  4. confira seu ramo de trabalho
  5. Faça o check-out do arquivo confirmado por sua mesclagem.
  6. Comprometa-o.

Tentei aplicar patches e minha situação era muito feia para isso. Então, resumindo, ficaria assim:

Filial de Trabalho: Uma Filial Experimental: B (contém file.txt que possui as alterações que eu quero incluir.)

git checkout A

Crie uma nova ramificação com base em A:

git checkout -b tempAB

Mesclar B no tempAB

git merge B

Copie o hash sha1 da mesclagem:

git log

commit 8dad944210dfb901695975886737dc35614fa94e
Merge: ea3aec1 0f76e61
Author: matthewe <[email protected]>
Date:   Wed Oct 3 15:13:24 2012 -0700

Merge branch 'B' into tempAB

Faça o checkout do seu ramo de trabalho:

git checkout A

Faça o checkout do seu arquivo corrigido:

git checkout 7e65b5a52e5f8b1979d75dffbbe4f7ee7dad5017 file.txt

E aí você deve tê-lo. Confirme seu resultado.

eggmatters
fonte
3
Então, temos que fazer tudo isso apenas para mesclar um único arquivo? Não seria apenas ser mais fácil de copiar e colar o arquivo para o outro ramo
Robin
11
@ Robin provavelmente não, porque a mesclagem mantém as alterações no arquivo, que diferem entre as ramificações A e B. A cópia do arquivo substituirá quaisquer diferenças adicionais entre a ramificação de trabalho A e o que você deseja trazer de B, que pode não conter essas entradas / edições. por exemplo, o suspeito Adesviou-se de Boutras maneiras. A cópia substituirá essas diferenças.
blamb
14

Isso usa o difftool interno do git. Talvez um pouco de trabalho para fazer, mas para a frente.

#First checkout the branch you want to merge into
git checkout <branch_to_merge_into>

#Then checkout the file from the branch you want to merge from
git checkout <branch_to_merge_from> -- <file> 

#Then you have to unstage that file to be able to use difftool
git reset HEAD <file> 

#Now use difftool to chose which lines to keep. Click on the mergebutton in difftool
git difftool

#Save the file in difftool and you should be done.
Mikael Kellgren
fonte
11
Para esclarecer o uso de --(rótulo de argumento vazio), git checkout docs: ARGUMENT DISAMBIGUATION diga: "use git checkout -- <pathspec>se você quiser fazer checkout desses caminhos fora do índice". Isso ocorre porque você pode ter uma ramificação e um arquivo / caminho com o mesmo nome. Nesses casos, em vez de pedir para você desambiguar se o ramo ou o caminho deve ser retirado quando ambos existirem, o git optará por fazer o checkout do ramo por padrão. No entanto, se --preceder, o git fará o checkout do arquivo / caminho.
precisa saber é o seguinte
8

Achei essa abordagem simples e útil: Como "mesclar" arquivos específicos de outro ramo

Como se vê, estamos tentando demais. Nosso bom amigo check-out git é a ferramenta certa para o trabalho.

git checkout source_branch <paths>...

Podemos simplesmente fornecer ao git checkout o nome do ramo de recursos A e os caminhos para os arquivos específicos que queremos adicionar ao nosso ramo mestre.

Por favor, leia o artigo inteiro para mais compreensão

Pawel Cioch
fonte
2
Isso substitui os arquivos, ele não fundi-los
Alex G
Para você, depende do que você está fazendo e do que está tentando alcançar. A idéia aqui é o ramo B é o fork de A, você modifica 4 arquivos em B, mas deseja mesclar apenas 2 de B a A. A mesclagem regular mesclaria todos os 4, aqui você pode selecionar. Pode parecer que eles foram substituídos porque B contém arquivos essencialmente mais novos. Você precisa apoiar sua experiência com algumas evidências.
Pawel Cioch
Concordo que substitui. Eu acho que você quis dizer usando a -popção nesse comando. Que, então, substitui todas as partes do arquivo da sua árvore de trabalho que anteriormente foram desviadas da ramificação da qual você efetuou o check-out, antes das alterações do patch, infelizmente.
blamb
Bem, a ideia foi a partir de 2009, as chances de uma nova versão do git se comportar de maneira diferente e precisar de -p ou qualquer outra coisa, mas quando eu estava postando, estavam funcionando para mim, mas, novamente, talvez eu não ligasse para a substituição dos arquivos, pois versão mais recente era o que eu precisava
Pawel Cioch
3

O comando a seguir irá (1) comparar o arquivo da ramificação correta, para dominar (2) interativamente, perguntar quais modificações aplicar.

git checkout - mestre de patches

user1854182
fonte
0

Minha edição foi rejeitada, por isso estou anexando como lidar com a fusão de alterações de uma ramificação remota aqui.

Se você precisar fazer isso após uma mesclagem incorreta, poderá fazer algo assim:

# If you did a git pull and it broke something, do this first
# Find the one before the merge, copy the SHA1
git reflog
git reset --hard <sha1>

# Get remote updates but DONT auto merge it
git fetch github 

# Checkout to your mainline so your branch is correct.
git checkout develop 

# Make a new branch where you'll be applying matches
git checkout -b manual-merge-github-develop

# Apply your patches
git checkout --patch github/develop path/to/file
...

# Merge changes back in
git checkout develop
git merge manual-merge-github-develop # optionally add --no-ff

# You'll probably have to
git push -f # make sure you know what you're doing.
Sopa
fonte
0

Supondo que B é o ramo atual:

$ git diff A <file-path> > patch.tmp
$ git apply patch.tmp -R

Observe que isso aplica apenas alterações ao arquivo local. Você precisará confirmar depois.

jbirkel
fonte
Para mim, isso gera umerror: <file-path>: already exists in working directory
kontur
Você deve especificar um arquivo ou caminho de arquivo no diretório atual. Estou usandogit diff Branch_A <file-path, filename> -- hash_commit > file_name.temp
R.Chatsiri 04/04
0

Você pode fazer o check-out da versão antiga do arquivo para mesclar, salvando-o com um nome diferente e executar a ferramenta de mesclagem nos dois arquivos.

por exemplo.

git show B:src/common/store.ts > /tmp/store.ts (onde B é o nome da filial / confirmação / tag)

meld src/common/store.ts /tmp/store.ts

Salame
fonte
0

Vou fazer isso como

git format-patch branch_old..branch_new file

isso produzirá um patch para o arquivo.

Aplicar patch no alvo branch_old

git am blahblah.patch

Novato
fonte
Você pode procurar facilmente o patch por segurança extra?
XavierStuvw