Thursday, 19 April 2018

Git fusionam a estratégia recursiva deles


7.8 Ferramentas Git - Fusão Avançada.
Fusão Avançada.
Fusionar no Git geralmente é bastante fácil. Uma vez que o Git facilita a mesclagem de outro ramo várias vezes, isso significa que você pode ter um ramo de vida muito longa, mas você pode mantê-lo atualizado à medida que vai, resolvendo pequenos conflitos com freqüência, em vez de se surpreender com um enorme conflito na fim da série.
No entanto, às vezes ocorrem conflitos difíceis. Ao contrário de alguns outros sistemas de controle de versão, o Git não tenta ser excessivamente inteligente sobre a resolução de conflitos de mesclagem. A filosofia de Git é ser inteligente para determinar quando uma resolução de mesclagem é inequívoca, mas, se houver um conflito, não tenta ser inteligente em resolvê-la automaticamente. Portanto, se você esperar muito para unir dois ramos que divergem rapidamente, você pode encontrar alguns problemas.
Nesta seção, examinaremos o que alguns desses problemas podem ser e quais ferramentas o Git lhe dá para ajudar a lidar com essas situações mais difíceis. Também abordaremos alguns dos diferentes tipos de fusões não padronizados que você pode fazer, além de ver como remover as fusões que você fez.
Combinar Conflitos.
Embora tenhamos abordado alguns conceitos básicos sobre a resolução de conflitos de mesclagem nos Conflitos de mesclagem básicos, para conflitos mais complexos, o Git fornece algumas ferramentas para ajudá-lo a descobrir o que está acontecendo e a como lidar melhor com o conflito.
Em primeiro lugar, se for possível, tente certificar-se de que seu diretório de trabalho esteja limpo antes de fazer uma fusão que possa ter conflitos. Se você tiver trabalho em andamento, comprometa-o a uma ramificação temporária ou esconda-o. Isso faz com que você possa desfazer tudo o que você tentar aqui. Se você tiver mudanças não salvas no seu diretório de trabalho quando você tentar uma mesclagem, algumas dessas dicas podem ajudá-lo a perder esse trabalho.
Vamos passar por um exemplo muito simples. Temos um arquivo Ruby super simples que imprime o mundo do Olá.
Em nosso repositório, criamos um novo ramo chamado espaço em branco e procedemos a mudar todos os terminais de linha do Unix para os terminais de linha do DOS, mudando essencialmente cada linha do arquivo, mas apenas com espaços em branco. Então mudamos a linha "hello world" para "hello mundo".
Agora, voltamos para nosso ramo principal e adicionamos alguma documentação para a função.
Agora, tentamos fundir em nosso ramo de espaço em branco e obteremos conflitos por causa das mudanças de espaço em branco.
Abortando uma mesclagem.
Agora temos algumas opções. Primeiro, vamos abordar como sair dessa situação. Se você talvez não estivesse esperando conflitos e não querendo lidar com a situação ainda, você pode simplesmente sair da mesclagem com git merge - abortar.
A opção git merge --abort tenta retornar ao seu estado antes de executar a mesclagem. Os únicos casos em que talvez não seja capaz de fazer isso perfeitamente seriam se você tivesse mudanças não comprometidas e não confirmadas em seu diretório de trabalho quando você o executou, caso contrário, ele deveria funcionar bem.
Se, por algum motivo, você quiser começar novamente, você também pode executar o git reset - HEAD HEAD, e seu repositório voltará para o último estado comprometido. Lembre-se de que qualquer trabalho não comprometido será perdido, então tenha certeza de que não deseja nenhuma das suas alterações.
Ignorando Whitespace.
Neste caso específico, os conflitos estão relacionados ao espaço em branco. Nós sabemos disso porque o caso é simples, mas também é muito fácil de dizer em casos reais quando se olha para o conflito porque cada linha é removida de um lado e adicionada novamente no outro. Por padrão, o Git vê todas essas linhas como sendo alteradas, portanto, não pode mesclar os arquivos.
A estratégia de mesclagem padrão pode levar argumentos, e alguns deles são sobre como ignorar adequadamente as mudanças no espaço em branco. Se você ver que você tem muitos problemas de espaço em branco em uma mesclagem, você pode simplesmente abortá-lo e fazê-lo novamente, desta vez com - Xignore-all-space ou - Xignore-space-change. A primeira opção ignora o espaço em branco completamente ao comparar linhas, o segundo trata as seqüências de um ou mais caracteres de espaço em branco como equivalentes.
Uma vez que neste caso, as alterações reais do arquivo não eram conflitantes, uma vez que ignoramos as mudanças de espaços em branco, tudo se funde bem.
Este é um salva-vidas se você tem alguém em sua equipe que gosta de reformatar ocasionalmente tudo, desde espaços a guias ou vice-versa.
Arquivo manual de re-fusão.
Embora o Git manipule bem o processamento de espaços brancos, existem outros tipos de mudanças que talvez o Git não possa lidar de forma automática, mas são correções para scripts. Como exemplo, vamos fingir que a Git não conseguiu lidar com a mudança de espaço em branco e precisávamos fazê-lo à mão.
O que realmente precisamos fazer é executar o arquivo que estamos tentando mesclar através de um programa dos2unix antes de tentar a fusão de arquivos real. Então, como faremos isso?
Primeiro, entramos no estado de conflito de fusão. Então, queremos obter cópias da minha versão do arquivo, sua versão (do ramo em que estamos mesclando) e a versão comum (de onde ambos os lados se ramificaram). Então queremos consertar seu lado ou nosso lado e voltar a tentar a fusão novamente por apenas esse arquivo único.
Obter as três versões de arquivos é realmente muito fácil. O Git armazena todas essas versões no índice em "estágios", que cada um tem números associados a eles. Etapa 1 é o antepassado comum, o estágio 2 é sua versão eo estágio 3 é do MERGE_HEAD, a versão em que você está mesclando ("deles").
Você pode extrair uma cópia de cada uma dessas versões do arquivo em conflito com o comando git show e uma sintaxe especial.
Se você quiser obter um núcleo um pouco mais difícil, você também pode usar o comando ls-files - u plumbing para obter os SHA-1 reais dos blobs Git para cada um desses arquivos.
O: 1: hello. rb é apenas uma abreviatura para procurar aquele blob SHA-1.
Agora que temos o conteúdo de todos os três estágios em nosso diretório de trabalho, podemos consertar manualmente o deles para corrigir o problema de espaço em branco e re-mesclar o arquivo com o comando pouco conhecido git merge-file que faz exatamente isso.
Nesse ponto, combinamos o arquivo com bastante facilidade. Na verdade, isso realmente funciona melhor do que a opção ignore-space-change porque isso realmente corrige as mudanças de espaço em branco antes da mesclagem em vez de simplesmente ignorá-las. Na fusão de ignorar-espaço-mudança, na verdade, terminamos com algumas linhas com finais de linha do DOS, fazendo com que as coisas fossem misturadas.
Se você quiser ter uma idéia antes de finalizar este commit sobre o que realmente foi alterado entre um lado ou o outro, você pode pedir o git diff para comparar o que está em seu diretório de trabalho que você está prestes a comprometer como resultado da mesclagem para qualquer uma dessas etapas. Vamos passar por todos eles.
Para comparar o seu resultado com o que você teve no seu ramo antes da fusão, em outras palavras, para ver o que a incorporação introduziu, você pode executar as diferenças.
Então, aqui, podemos ver facilmente que o que aconteceu no nosso ramo, o que realmente estamos apresentando a este arquivo com essa fusão, está mudando essa única linha.
Se quisermos ver como o resultado da fusão diferiu do que era do lado deles, você pode executar o diff do git. Neste e no exemplo a seguir, temos que usar - b para retirar o espaço em branco, porque estamos comparando isso com o que está no Git, e não com o nosso arquivo de limpar hello. theirs. rb.
Finalmente, você pode ver como o arquivo mudou de ambos os lados com o GIT diff - base.
Neste ponto, podemos usar o comando git clean para limpar os arquivos extra que criamos para fazer a mesclagem manual, mas não precisamos mais.
Verificando Conflitos.
Talvez não estivéssemos felizes com a resolução neste ponto por algum motivo, ou talvez a edição manual de um ou de ambos os lados ainda não funcionou bem e precisamos de mais contexto.
Vamos mudar o exemplo um pouco. Para este exemplo, temos dois ramos mais vivos que cada um tem alguns cometidos neles, mas criam um conflito de conteúdo legítimo quando mesclado.
Agora temos três compromissos únicos que vivem apenas no ramo principal e outros três que vivem no ramo mundo. Se tentarmos fundir a ramificação do mundo, obtemos um conflito.
Gostaríamos de ver qual é o conflito de mesclagem. Se abrimos o arquivo, veremos algo assim:
Ambos os lados da mesclagem adicionaram conteúdo a este arquivo, mas alguns dos compromissos modificaram o arquivo no mesmo local que causou esse conflito.
Vamos explorar algumas ferramentas que você agora tem à sua disposição para determinar como esse conflito veio a ser. Talvez não seja óbvio como exatamente você deve consertar esse conflito. Você precisa de mais contexto.
Uma ferramenta útil é git checkout com a opção '--conflict'. Isso re-checkout o arquivo novamente e substituir os marcadores de conflito de mesclagem. Isso pode ser útil se você quiser redefinir os marcadores e tentar resolvê-los novamente.
Você pode passar --conflict diff3 ou fusion (que é o padrão). Se você passar diff3, o Git usará uma versão ligeiramente diferente de marcadores de conflito, não só lhe dando as versões "nosso" e "deles", mas também a versão "base" em linha para lhe dar mais contexto.
Uma vez que executamos isso, o arquivo ficará assim:
Se você gosta deste formato, você pode configurá-lo como padrão para futuros conflitos de mesclagem configurando a configuração merge. conflictstyle para diff3.
O comando git checkout também pode levar --ours e - suas opções, que podem ser uma maneira muito rápida de escolher apenas um lado ou outro sem fundir nada.
Isso pode ser particularmente útil para conflitos de arquivos binários onde você pode simplesmente escolher um lado ou onde você deseja apenas mesclar determinados arquivos de outro ramo - você pode fazer a mesclagem e, em seguida, efetuar o checkout de determinados arquivos de um lado ou outro antes de cometer .
Outra ferramenta útil ao resolver conflitos de mesclagem é git log. Isso pode ajudá-lo a contextualizar o que pode ter contribuído para os conflitos. Revisar um pouco de história para lembrar por que duas linhas de desenvolvimento estavam tocando a mesma área de código pode ser realmente útil às vezes.
Para obter uma lista completa de todos os compromissos exclusivos que foram incluídos em qualquer ramo envolvido nesta mesclagem, podemos usar a sintaxe de "ponto triplo" que aprendemos em Triple Dot.
Essa é uma boa lista dos seis compromissos totais envolvidos, bem como a cada linha de desenvolvimento em que cada um cometeu.
Podemos ainda simplificar isso para nos dar um contexto muito mais específico. Se adicionarmos a opção --merge para git log, isso só mostrará os compromissos em ambos os lados da mesclagem que tocam um arquivo que está atualmente em conflito.
Se você executar isso com a opção - p em vez disso, você obtém apenas os diffs para o arquivo que acabou em conflito. Isso pode ser realmente útil para lhe dar rapidamente o contexto que você precisa para ajudar a entender por que algo conflita e como resolvê-lo de forma mais inteligente.
Formato Diff Combinado.
Uma vez que o Git desenrola todos os resultados de mesclagem que são bem-sucedidos, quando você executa o Git diff enquanto estiver em um estado de mesclagem em conflito, você só obtém o que ainda está em conflito. Isso pode ser útil para ver o que você ainda precisa resolver.
Quando você executa git diff diretamente após um conflito de mesclagem, isso lhe dará informações em um formato de saída de DVD bastante exclusivo.
O formato é chamado de "Difusão combinada" e fornece duas colunas de dados ao lado de cada linha. A primeira coluna mostra se essa linha é diferente (adicionada ou removida) entre o ramo "nosso" e o arquivo em seu diretório de trabalho e a segunda coluna faz o mesmo entre o ramo "deles" e sua cópia do diretório de trabalho.
Então, nesse exemplo, você pode ver que o & lt; & lt; & lt; & lt; & lt; & lt; & lt; e & gt; & gt; & gt; & gt; & gt; & gt; & gt; & gt; & gt; & gt; & gt; & gt; as linhas estão na cópia de trabalho, mas não estavam em ambos os lados da mesclagem. Isso faz sentido porque a ferramenta de fusão os colocou no contexto, mas esperamos que os remova.
Se resolvêssemos o conflito e executemos o GIT diff novamente, veremos o mesmo, mas é um pouco mais útil.
Isso nos mostra que "mundo hola" estava ao nosso lado, mas não na cópia de trabalho, que "hello mundo" estava no seu lado, mas não na cópia de trabalho e, finalmente, que "hola mundo" não estava em nenhum dos lados, mas agora está em a cópia de trabalho. Isso pode ser útil para rever antes de cometer a resolução.
Você também pode obter isso no log git para qualquer mesclagem para ver como algo foi resolvido após o fato. O Git emitirá este formato se você executar o show git em um commit de mesclagem, ou se você adicionar uma opção --cc a git log - p (o que, por padrão, mostra apenas patches para compromissos de não-mesclagem).
Desfazer Fusões.
Agora que você sabe como criar um compromisso de mesclagem, você provavelmente fará algum erro. Uma das ótimas coisas sobre trabalhar com o Git é que é bom cometer erros, porque é possível (e, em muitos casos, fácil) consertá-los.
Os compromissos de fusão não são diferentes. Digamos que você começou a trabalhar em um ramo tópico, fundou-o acidentalmente em mestre e agora o seu histórico de confirmação se parece com isto:
Existem duas maneiras de abordar esse problema, dependendo do resultado desejado.
Corrija as referências.
Se o commit de mesclagem indesejável existe apenas no seu repositório local, a solução mais fácil e melhor é mover os ramos para que eles apontem para onde você deseja. Na maioria dos casos, se você seguir a junção git errante com git reset - HEAD HEAD.
, isso irá redefinir os ponteiros de ramificação para que eles pareçam assim:
Nós cobrimos o reset novamente no Reset Desmistificado, então não deve ser muito difícil descobrir o que está acontecendo aqui. Aqui está uma atualização rápida: redefinir - difícil geralmente passa por três etapas:
Mova os pontos HEAD de ramificação para. Nesse caso, queremos mover o mestre para onde estava antes do compromisso de mesclagem (C6).
Faça com que o índice pareça HEAD.
Faça com que o diretório de trabalho se pareça com o índice.
A desvantagem dessa abordagem é que está reescrevendo o histórico, o que pode ser problemático com um repositório compartilhado. Confira The Perils of Rebasing para saber mais sobre o que pode acontecer; A versão curta é que, se outras pessoas tiverem os compromissos que você está reescrevendo, provavelmente você deve evitar a reinicialização. Esta abordagem também não funcionará se outros compromissos tiverem sido criados desde a fusão; mover as referências efetivamente perderia essas mudanças.
Inverta o commit.
Se mover os ponteiros do ramo ao redor não vai funcionar para você, o Git oferece a opção de fazer um novo commit que desfaz todas as mudanças de uma existente. Git chama essa operação de um "retorno", e neste cenário particular, você invocaria assim:
O sinalizador - m 1 indica qual pai é o "mainline" e deve ser mantido. Quando você invoca uma mesclagem em HEAD (git merge topic), o novo commit tem dois pais: o primeiro é HEAD (C6) e o segundo é a ponta do ramo sendo mesclado em (C4). Neste caso, queremos desfazer todas as alterações introduzidas pela mesclagem no pai 2 (C4), enquanto mantém todo o conteúdo do pai # 1 (C6).
O histórico com o commit de rever se parece com isto:
O novo commit ^ M tem exatamente o mesmo conteúdo que o C6, então, a partir daqui, é como se a fusão nunca acontecesse, exceto que os compromissos agora não combinados ainda estão no histórico da HEAD. Git ficará confuso se você tentar mesclar tópico no mestre novamente:
Não há nada no tópico que já não é alcançável pelo mestre. O que é pior, se você adicionar trabalho ao tópico e fundir novamente, o Git somente trará as mudanças desde a fusão revertida:
A melhor maneira de evitar isso é desativar a união original, já que você deseja trazer as alterações que foram revertidas e, em seguida, criar um novo commit de mesclagem:
Neste exemplo, M e ^ M cancelam. ^^ M efetivamente mescla nas mudanças de C3 e C4, e C8 se funde nas mudanças de C7, então agora o tópico é totalmente mesclado.
Outros tipos de fusões.
Até agora, cobrimos a fusão normal de dois ramos, normalmente manuseados com o que chamamos de estratégia "recursiva" de fusão. Existem outras maneiras de juntar sucursais entretanto. Vamos cobrir alguns deles rapidamente.
Nossa preferência ou a nossa.
Antes de tudo, há outra coisa útil que podemos fazer com o modo "recursivo" normal de fusão. Já vimos as opções ignorar-tudo-espaço e ignorar-espaço-mudança que são passadas com um - X, mas também podemos dizer ao Git que favorece um lado ou outro quando vê um conflito.
Por padrão, quando o Git vê um conflito entre dois ramos sendo mesclados, ele adicionará marcadores de conflito de mesclagem ao seu código e marcará o arquivo como conflitante e permitirá que você o resolva. Se você preferir que o Git simplesmente escolha um lado específico e ignore o outro lado, em vez de permitir que você resolva manualmente o conflito, você pode passar o comando de mesclagem, a - X ou ou - X.
Se Git vê isso, não irá adicionar marcadores de conflito. Quaisquer diferenças que sejam mergeáveis, ela irá fundir. Qualquer diferença que entre em conflito, ele simplesmente escolherá o lado que você especifica no todo, incluindo arquivos binários.
Se voltarmos para o exemplo do "mundo do Olá", estávamos usando antes, podemos ver que a fusão em nosso ramo causa conflitos.
No entanto, se o executemos com - Xours ou - Xtheirs não.
Nesse caso, em vez de obter marcadores de conflito no arquivo com "hello mundo" de um lado e "mundo hola", por outro, ele simplesmente escolherá "mundo hola". No entanto, todas as outras alterações não conflitantes nesse ramo são mescladas com sucesso.
Esta opção também pode ser passada para o comando git merge-file que vimos anteriormente executando algo como git merge-file --ours para fusões individuais de arquivos.
Se você quer fazer algo assim, mas não tem o Git mesmo tentando mesclar as mudanças do outro lado, há uma opção mais draconiana, que é a nossa estratégia de fusão "nós". Isso é diferente da opção de mesclagem recursiva "nosso".
Isso basicamente fará uma fusão falsa. Ele gravará uma nova combinação de mesclagem com os dois ramos como pais, mas nem sequer olhará para o ramo em que você está mesclando. Ele simplesmente registrará como resultado da mesclagem do código exato em seu ramo atual.
Você pode ver que não há diferença entre o ramo em que estávamos e o resultado da fusão.
Isso muitas vezes pode ser útil para basicamente enganar o Git para pensar que um ramo já foi mesclado ao fazer uma fusão mais tarde. Por exemplo, digamos que você ramificou um ramo de liberação e fez algum trabalho sobre isso que você quer se fundir novamente em seu ramo mestre em algum momento. Enquanto isso, alguns erros no mestre precisam ser enviados para o seu ramo de lançamento. Você pode mesclar o ramo do bugfix no ramo de lançamento e também mesclar - s somos o mesmo ramo em seu ramo principal (mesmo que a correção já esteja aí), então, quando você mesclar mais o ramo de lançamento novamente, não há conflitos do bugfix.
Fusão de sub-árvore.
A idéia da mesclagem de subárvore é que você tem dois projetos e um dos projetos mapeia para um subdiretório do outro. Quando você especifica uma mesclagem de subárvore, Git geralmente é inteligente o suficiente para descobrir que uma é uma subárvore da outra e mesclar adequadamente.
Passaremos por um exemplo de adicionar um projeto separado em um projeto existente e depois mesclar o código do segundo em um subdiretório do primeiro.
Primeiro, adicionaremos o aplicativo Rack ao nosso projeto. Vamos adicionar o projeto Rack como uma referência remota em nosso próprio projeto e depois verificá-lo em seu próprio ramo:
Agora, temos a raiz do projeto Rack em nosso ramo rack_branch e nosso próprio projeto no ramo principal. Se você verificar um e depois o outro, você pode ver que eles têm raízes de projetos diferentes:
Esta é uma espécie de conceito estranho. Nem todos os ramos em seu repositório realmente precisam ser ramos do mesmo projeto. Não é comum, porque raramente é útil, mas é bastante fácil ter ramificações com histórias completamente diferentes.
Neste caso, queremos puxar o projeto Rack para o nosso projeto mestre como um subdiretório. Podemos fazer isso em Git com git read-tree. Você aprenderá mais sobre a lição e seus amigos no Git Internals, mas por agora sabe que lê a árvore de raiz de um ramo em sua área de teste atual e no diretório de trabalho. Acabamos de trocar de volta para o seu ramo mestre e puxamos o ramo rack_branch para o subdiretório de rack do nosso ramal principal do nosso projeto principal:
Quando nos comprometemos, parece que temos todos os arquivos do Rack nesse subdiretório - como se os copiássemos de um tarball. O que fica interessante é que podemos facilmente cruzar as mudanças de um dos ramos para o outro. Então, se o projeto Rack atualizar, podemos puxar as mudanças a montante mudando para esse ramo e puxando:
Então, podemos juntar essas mudanças de volta ao nosso ramo principal. Para puxar as alterações e prepopular a mensagem de confirmação, use a opção --squash, bem como a opção - Xsubtree da estratégia de mesclagem recursiva. (A estratégia recursiva é o padrão aqui, mas nós o incluímos para maior clareza.)
Todas as mudanças do projeto do Rack são incorporadas e prontas para serem cometidas localmente. Você também pode fazer o contrário - faça alterações no subdiretório de rack do seu ramo principal e, em seguida, junte-os em seu ramo rack_branch mais tarde para enviá-los aos mantenedores ou empurrá-los para o rio.
Isso nos dá uma maneira de ter um fluxo de trabalho um pouco semelhante ao fluxo de trabalho do submódulo sem usar os submódulos (o que cobriremos em Submodules). Nós podemos manter filiais com outros projetos relacionados em nosso repositório e sub-árvore, mesclando-os em nosso projeto de vez em quando. É legal em alguns aspectos, por exemplo, todo o código está comprometido com um único lugar. No entanto, tem outras desvantagens na medida em que é um pouco mais complexo e mais fácil cometer erros na reintegração de mudanças ou acidentalmente empurrando um ramo para um repositório não relacionado.
Outro aspecto um pouco estranho é o de obter uma diferença entre o que você tem no subdiretório do rack e o código em seu ramo rack_branch - para ver se você precisa mesclar-los - você não pode usar o comando normal diff. Em vez disso, você deve executar o Git diff-tree com o ramo que deseja comparar com:
Ou, para comparar o que está em seu subdiretório de rack com o que o ramo mestre no servidor foi a última vez que você buscou, você pode executar.

estratégia de fusão Git recursiva deles
Obter através da App Store Leia esta publicação em nosso aplicativo!
git merge recursive theirs, como isso funciona?
Estou tendo um pouco de problema. Nós temos o nosso próprio CMS que está usando git para colaboração e versões e outras coisas.
Agora eu tenho dois repositórios git A e B, A que é um projeto e B que é o próprio CMS. Agora eu quero obter B em A, mas quando eu faço isso, eu tenho muitos conflitos de mesclagem e a solução para os conflitos é sempre usar o material de B.
Agora, o que eu acho que eu preciso é.
porque eu quero fundir e quando há um conflito de fusão, ele deve ser forçado a usar a solução de B. Mas eu não consigo fazer isso funcionar. Sempre me diz que é fatal: 'deles' não aponta para um commit.
Os recursivos deles, eu encontrei aqui.
Alguém sabe o que eu faço de errado?
Você deve usar esse formulário para passar opções de estratégia de mesclagem:
Certifique-se também de que a sua versão seja suprimida. É a característica bastante recente (?)
Eu acho que o motivo pelo qual está falhando é que você está especificando "recursive theirs" como a estratégia. "recursivo" é uma estratégia, e quando você coloca um espaço depois, "os seus" são interpretados como algo que git precisa mesclar sua cópia de trabalho com (por exemplo, outro ramo ou refspec).
Eu acho que você não poderá especificar uma estratégia exatamente como o que você deseja. Existe uma estratégia chamada "nossa", que é o oposto do que você está querendo.
O padrão usual usado nesta situação é combinar ou rebase no repositório "B". Dentro da cópia de trabalho do repositório "A", você faria um rebase, se possível (talvez não seja possível, se você já está compartilhando o repo git com outros desenvolvedores). Um rebase seria essencialmente rotear o repositório A de volta para um commit comum em ambos os repositórios, aplicar "B" comete, então "A" comete no topo. Você resolveria todos os conflitos de mesclagem ao longo do caminho.
Uma vez que você atravessa a dor de fusão ou rebaixamento no repositório "B", o futuro mescla será menos doloroso.

ILoggable.
Um lugar para manter meus pensamentos sobre a programação.
fingindo git merge & # 8211; estratégia = deles.
Eu tentei descobrir um fluxo de trabalho em git para reiniciar o meu clone de um ramo upstream para o estado ativo atual, mas sem descartar meu histórico. A razão para não deixar cair a história é que a) é antitético para mim descartar qualquer coisa do controle de revisão, e b) eu empurre minhas mudanças locais para um repo público, o que significa que outros podem ter clonado e estão seguindo minhas mudanças, então um reset git ou git rebase é uma coisa ruim.
Claro, a fusão costuma ser bem, mas no caso de eu trabalhar em algo que não é aceito a montante ou foi irrelevante por uma mudança a montante, a fusão não se livraria das minhas mudanças de sem-fim.
Uma opção é deixar meus clones de ramos upstream sozinhos e sempre criar filiais funcionais que eu descarto uma vez que a tarefa está concluída e cada novo ramo de trabalho é um novo ramo do mestre a montante.
Depois de cavar ao redor de um tempo, eu encontrei quase o que eu queria:
que traz história de & lt; branch & gt; mas adiciona mais uma confirmação de gravação das mudanças necessárias para manter o ramo atual em seu estado de pré-mesclagem. Exceto que eu quero fazer o contrário.
que traria a história de & lt; upstream / branch & gt; e registre um commit com as mudanças necessárias para tornar o ramo atual uma réplica do & lt; upststream / branch & gt; . Embora haja algo que pareça fazer isso, ou seja,
mas isso não descartará mudanças locais que não entrarão em conflito com as mudanças a montante.
Um fluxo de trabalho para falsificar git merge & # 8211; strategy = theirs.
Supondo que eu apenas deva ignorar um comando ou mudança, perguntei no stackoverflow e com a ajuda dos usuários kelloti e jefromi (atualização: o VonC atualizou sua resposta para refletir mais precisamente este fluxo de trabalho) foi capaz de reunir um fluxo de trabalho que falsifica - estratégia = deles:
obtenha uma cópia temporária do ramo a montante.
git co - b temp & lt; upstream / branch & gt;
Junte a nossa versão do ramo no rio acima com a nossa estratégia.
git merge --strategy = nosso & lt; branch & gt;
cometer se necessário (ou seja, auto-commit ou fast forward didn & # 39; t acontecer)
Confira nossa versão do ramo.
Temp de fusão (que será um avanço rápido)
empurre as alterações para o nosso repo de origem.
Se livrar do ramo temporário.
git branch - D temp.
É um pouco complicado, mas nos deixa com a nossa história e uma cópia local re-freshed do mestre a montante.
Atualização: por que eu quero isso de novo?
Eu estou configurando o worflow para MindTouch DReAM agora mesmo. Até agora, estamos colobrando via SVN sem ramos de desenvolvimento. Eu tinha mantido o meu próprio repo de git privado, porque eu sou bastante especial em cometer com freqüência e querendo aqueles commits de backup remotamente.
Enquanto meu repo não tivesse nada a ver com a versão pública, isso estava tudo bem, mas agora eu quero a capacidade de coloquem no WIP com outros membros da equipe e contribuintes externos, eu quero ter certeza de que meu público os ramos são confiáveis ​​para que outros se ramifiquem e puxem, ou seja, não há mais rebase e redefinir sobre as coisas que eu pressionei para o backup remoto, já que agora está no github e no público.
Então, isso me deixa com a maneira de proceder. 99% do tempo em que minha cópia entrará no mestre a montante, então eu quero trabalhar meu mestre e empurrar para o rio a maior parte do tempo. Mas, de vez em quando, o que eu tenho no wip será invalidado pelo que entra no rio e eu vou abandonar parte do meu wip. Nesse ponto, quero trazer meu mesão de volta em sincronia com o upstream, mas não destruir quaisquer pontos de confirmação no meu mestre publicamente empurrado. Isto é, Eu quero uma fusão com o upstream que acaba com o changeset que faz minha cópia idêntica à montante. E isso é o que git merge --strategy = o deles deveria fazer.
7 to & # 8220; fingir git merge & # 8211; strategy = theirs & # 8221;
bjorg diz.
Por um momento, fiquei preocupado que seria complicado # 8230;
Obrigado por compilar esta informação preciosa. Provavelmente a dica mais útil I & # 039; usará a partir de não ativado. Mas penso, eu posso ver como gerenciarei a sanidade no ramo na seguinte situação ou se é exatamente a sua situação. Mas eu entendo que tudo isso agora é possível com suas dicas.
Cenário: um garfo público (um garfo github conhecido), um forcado my-colab (meu github repo) e meu outro garfo (um clone local que eu gostaria de fazer novo repo novo, mas ter uma relação pareantage).
Atualmente, eu apenas empurro para o meu-colab-fork se eu for lançar-pedir no github. O que significa que até agora todos os meus SHAs são idênticos ao público-bifurcação. Até agora eu aguardo a minha integração pública de solicitação de tração para além de "FF" mesclar o fork público no my-colab-fork, escolhendo assim o novo comando public-merge-commit (o integrador tem uma regra para sempre criar uma mesclagem - commit).
Por causa disso, se a solicitação de puxo for negada, eu rapidamente restaurei & # 8211; duro e empurre my-colab-repo. Mau, eu sei. Com você post, espero que tudo desapareça, já que agora é mais fácil combinar entre filiais com freqüência e a montante.
Você poderia me dizer no seguinte cenário:
O meu repo local (my-future-repo) é de 5 compromissos à frente do upstream / my-colab-fork, enquanto isso o my-colab-fork é 2 comete atrás do público-bifurcação.
Significa o tempo de sincronização entre as 3 garfos. Áreas problemáticas que arize:
Eu quero as últimas mudanças públicas (2 compromissos) fundidas em upstream / my-colab-fork (fácil! A fundação usual - ff)
Eu quero as últimas mudanças públicas (2 compromissos) mescladas no meu futuro-repo (talvez seja necessário editar & # 8211; o nosso?)
Ao mesmo tempo, estou interessado em algumas mudanças desses 5 compromissos do meu futuro-repo, e gostaria de cirurgicamente juntá-los no meu colab-fork, para posteriormente solicitar o pull-request. Digamos que eu preciso de uma confirmação de meio e meio de minha corrente de futuro-repo, o que significa que eu preciso editar compromissos (e SHAS)
Aqueles escolhidos mudanças eu quero-os empurrados para o meu-colab-fork para que eu possa github pull-request e ser mesclado em público-bifurcação (fácil! Etapa)
Mais tarde, depois do pedido de envio aceito e mais desenvolvimento público, eu precisarei juntar novas mudanças públicas no meu futuro-repo. Mas nessas mudanças haverá os compromissos 1 e 1/2 (com um novo SHA) a partir do ponto número 3.
Você estratégia, acho que irá responder a maioria das áreas problemáticas, embora eu ainda não saiba como lidar com os compromissos externos. Se eu temporariamente esconder ou reativá-los de forma interativa, os compromissos vão gritar quando mesclar novas mudanças a montante (devido às mudanças provenientes de uma temperatura SHA & # 8211; ou eu estou confuso?).
Eu acho que só preciso definir entre os 3 garfos, que estratégia será aplicada (a nossa ou a sua) de uma forma que eu possa ter um ciclo de desenvolvimento entre 3 sem muita alocação e # 8230; primeiro primeiro tem que compreender melhor a estratégia de mesclagem.
Se você tiver alguma apreciação para adicionar, obrigado, ou algum link para algo relacionado, U poderia dar uma olhada.
Uma vez que eu envio WIP para o Github com freqüência, é minha política evitar rescursos e rebases difíceis, então não altero o histórico em coisas que já empurrei. Minha estratégia atual para lidar com res valioso é que eu espelho seu mestre para eu usar, mas nunca cometer alterações. Se eu tiver mudanças, criei um novo ramo específico do recurso upstream / master. Dessa forma, eu ainda consigo capturar mudanças no mestre e empurre apenas alterações específicas a montante com um ramo dedicado que, se não for aceito a montante, é facilmente excluído.
Nick Coghlan diz.
Tenho certeza de que encontrei uma maneira mais simples de fazer isso:
git diff other-branch | patch - R # Faz com que nosso check-out local corresponda ao remoto.
git merge - s our other-branch # Adiciona todas as alterações remotas ao nosso histórico.
Nick Coghlan says.
One slight correction, using "-s ours" will cause problems with failing to copy *new* files from the remote branch. The default merge strategy is a better option.
Nick Coghlan says.
Never mind, you have to use "-s ours" or it will complain about the uncommited changes. Just be aware that it may need an additional couple of commands to get any new files cloned correctly.
Philip Oakley says.
A set of commit diagrams would also be useful to complement the text. It’s easy to miss some of the nuances, and they are worth a thousand words, apparently 😉

Git merge strategy recursive theirs


The merge mechanism ( git merge and git pull commands) allows the backend 'merge strategies' to be chosen with - s option. Some strategies can also take their own options, which can be passed by giving - X<option> arguments to git merge and/or git pull .
This can only resolve two heads (i. e. the current branch and another branch you pulled from) using a 3-way merge algorithm. It tries to carefully detect criss-cross merge ambiguities and is considered generally safe and fast.
This can only resolve two heads using a 3-way merge algorithm. When there is more than one common ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without causing mismerges by tests done on actual merge commits taken from Linux 2.6 kernel development history. Additionally this can detect and handle merges involving renames. This is the default merge strategy when pulling or merging one branch.
The 'recursive' strategy can take the following options:
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. For a binary file, the entire contents are taken from our side.
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.
This is the opposite of 'ours'; note that, unlike 'ours', there is no 'theirs' merge stragegy to confuse this merge option with.
With this option, 'merge-recursive' spends a little extra time to avoid mismerges that sometimes occur due to unimportant matching lines (e. g., braces from distinct functions). Use this when the branches to be merged have diverged wildly. See also git-diff[1] --patience .
Tells 'merge-recursive' to use a different diff algorithm, which can help avoid mismerges that occur due to unimportant matching lines (such as braces from distinct functions). See also git-diff[1] --diff-algorithm .
ignore-space-change ignore-all-space ignore-space-at-eol ignore-cr-at-eol.
Treats lines with the indicated type of whitespace change as unchanged for the sake of a three-way merge. Whitespace changes mixed with other changes to a line are not ignored. See also git-diff[1] - b , - w , --ignore-space-at-eol , and --ignore-cr-at-eol .
If 'their' version only introduces whitespace changes to a line, 'our' version is used;
If 'our' version introduces whitespace changes but 'their' version includes a substantial change, 'their' version is used;
Otherwise, the merge proceeds in the usual way.
This runs a virtual check-out and check-in of all three stages of a file when resolving a three-way merge. This option is meant to be used when merging branches with different clean filters or end-of-line normalization rules. See "Merging branches with differing checkin/checkout attributes" in gitattributes[5] for details.
Disables the renormalize option. This overrides the merge. renormalize configuration variable.
Turn off rename detection. See also git-diff[1] --no-renames .
Turn on rename detection, optionally setting the similarity threshold. This is the default. See also git-diff[1] --find-renames .
Deprecated synonym for find-renames=<n> .
This option is a more advanced form of 'subtree' strategy, where the strategy makes a guess on how two trees must be shifted to match with each other when merging. Instead, the specified path is prefixed (or stripped from the beginning) to make the shape of two trees to match.
This resolves cases with more than two heads, but refuses to do a complex merge that needs manual resolution. It is primarily meant to be used for bundling topic branch heads together. This is the default merge strategy when pulling or merging more than one branch.
This resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. It is meant to be used to supersede old development history of side branches. Note that this is different from the - Xours option to the 'recursive' merge strategy.
This is a modified recursive strategy. When merging trees A and B, if B corresponds to a subtree of A, B is first adjusted to match the tree structure of A, instead of reading the trees at the same level. This adjustment is also done to the common ancestor tree.
With the strategies that use 3-way merge (including the default, 'recursive'), if a change is made on both branches, but later reverted on one of the branches, that change will be present in the merged result; some people find this behavior confusing. It occurs because only the heads and the merge base are considered when performing a merge, not the individual commits. The merge algorithm therefore considers the reverted change as no change at all, and substitutes the changed version instead.

git rebase --strategy with - Xours.
-Xours tells Git to protect the new base. By bringing in only the additions that the incoming commits have made, it protects what is already in the new base.
Recap: A rebase moves a series of commits from one base to another base.
What does the --strategy do? When a rebase hits a conflict, git attempts to resolve it with one of these merge-strategies:
recursive with ours is one of our favorite strategies. To use it, choose --strategy recursive and pass the ours sub-option using the - X<sub-option> syntax.
In the second example, Git takes the last four commits from topic-branch and plays them back onto master . If Git finds a conflicting hunk, it chooses the content of master ; otherwise, Git adds the content of topic-branch . In other words, Git brings in to master only the additions that the topic branch has made.
We used - Xours recently to bring in deployment scripts from a long-lived experimental branch. We were only interested in the deployment scripts that experiemental-branch had added to the code base. If we had done a normal rebase, we would have had to deal with the conflicts that the experimental work had introduced to the existing code. Using - Xours instead told Git, "Just bring in the stuff that experimental-branch added." Those additions turned out to be the deployment scripts. Feito. If there had been other additions, though, we could have easily detected and deleted them.
Shaun Luttin.
Leia mais postagens deste autor.
Share this post.
typescript import and export organization.
This blog post, like most, is for my own edification. Organizing TypeScript modules is hard for me. These notes…
My Firefox Add-Ons: LastPass and Tree Style Tab.
LastPass and Tree Style Tab tend to be the only ones I use. Why did I write this blog…

No comments:

Post a Comment