1.. SPDX-License-Identifier: GPL-2.0 2 3==================================== 4Backporting e resolução de conflitos 5==================================== 6 7:Autor: Vegard Nossum <vegard.nossum@oracle.com> 8 9.. contents:: 10 :local: 11 :depth: 3 12 :backlinks: none 13 14Introdução 15========== 16 17Alguns desenvolvedores podem nunca precisar lidar de fato com backporting de 18patches, mesclagem de ramificações (branches) ou resolução de conflitos em seu 19trabalho diário, portanto, quando um conflito de mesclagem aparece, pode ser 20assustador. Felizmente, resolver conflitos é uma habilidade como qualquer outra, 21e existem muitas técnicas úteis que você pode usar para tornar o processo mais 22suave e aumentar sua confiança no resultado. 23 24Este documento tem como objetivo ser um guia abrangente e passo a passo para 25backporting e resolução de conflitos. 26 27Aplicando o patch a uma árvore 28============================== 29 30Às vezes, o patch que você está fazendo backport já existe como um commit do 31git, caso em que você apenas faz o cherry-pick dele diretamente usando 32``git cherry-pick``. No entanto, se o patch vier de um e-mail, como costuma 33acontecer no caso do kernel Linux, você precisará aplicá-lo a uma árvore usando 34``git am``. 35 36Se você já usou o ``git am``, provavelmente já sabe que ele é bastante exigente 37sobre o patch ser aplicado perfeitamente à sua árvore de código-fonte. Na 38verdade, você provavelmente já teve pesadelos com arquivos ``.rej`` e tentando 39editar o patch para fazê-lo ser aplicado. 40 41Recomenda-se fortemente, em vez disso, encontrar uma versão base apropriada onde 42o patch se aplique de forma limpa e *então* fazer o cherry-pick dele para a sua 43árvore de destino, pois isso fará com que o git exiba marcadores de conflito e 44permitirá que você resolva os conflitos com a ajuda do git e de quaisquer outras 45ferramentas de resolução de conflitos que preferir usar. Por exemplo, se você 46quiser aplicar um patch que acabou de chegar na LKML a um kernel estável mais 47antigo, você pode aplicá-lo ao kernel principal (mainline) mais recente e, em 48seguida, fazer o cherry-pick dele para a sua ramificação estável mais antiga. 49 50Geralmente é melhor usar exatamente a mesma base a partir da qual o patch foi 51gerado, mas isso não importa tanto, desde que ele se aplique de forma limpa e 52não esteja muito longe da base original. O único problema ao aplicar o patch na 53base "errada" é que isso pode trazer mais alterações não relacionadas no 54contexto do diff ao fazer o cherry-pick dele para a ramificação mais antiga. 55 56Um bom motivo para preferir o ``git cherry-pick`` em vez do ``git am`` é que o 57git conhece o histórico preciso de um commit existente, de modo que ele saberá 58quando o código foi movido de lugar e teve seus números de linha alterados; isso, 59por sua vez, torna menos provável que o patch seja aplicado no lugar errado (o 60que pode resultar em erros silenciosos ou conflitos confusos). 61 62Se você estiver usando o `b4`_. e estiver aplicando o patch diretamente de um 63e-mail, você pode usar o ``b4 am`` com as opções ``-g``/``--guess-base`` e 64``-3``/``--prep-3way`` para fazer parte disso automaticamente (veja a 65`apresentação do b4`_ para mais informações). No entanto, o restante deste 66artigo assumirá que você está fazendo um ``git cherry-pick`` simples. 67 68.. _b4: https://people.kernel.org/monsieuricon/introducing-b4-and-patch-attestation 69.. _apresentação do b4: https://youtu.be/mF10hgVIx9o?t=2996 70 71Assim que tiver o patch no git, você pode prosseguir e fazer o cherry-pick dele 72em sua árvore de código-fonte. Não se esqueça de fazer o cherry-pick com ``-x`` 73se quiser um registro por escrito de onde o patch veio! 74 75Note que, se você estiver enviando um patch para a ramificação estável (stable), 76o formato é ligeiramente diferente; a primeira linha após a linha de assunto 77precisa ser:: 78 79 commit <upstream commit> upstream 80 81ou:: 82 83 [ Upstream commit <upstream commit> ] 84 85Resolvendo conflitos 86==================== 87 88Ih, rapaz; o cherry-pick falhou com uma mensagem vagamente ameaçadora:: 89 90 CONFLICT (content): Merge conflict 91 92O que fazer agora? 93 94Em geral, os conflitos aparecem quando o contexto do patch (ou seja, as linhas 95que estão sendo alteradas e/ou as linhas que cercam as alterações) não 96corresponde ao que está na árvore à qual você está tentando aplicar o patch. 97 98No caso de backports, o que provavelmente aconteceu foi que a ramificação 99(branch) a partir da qual você está fazendo o backport contém patches que não 100estão na ramificação para a qual você está fazendo o backport. No entanto, o 101inverso também é possível. Em qualquer caso, o resultado é um conflito que 102precisa ser resolvido. 103 104Se a sua tentativa de cherry-pick falhar com um conflito, o git edita os 105arquivos automaticamente para incluir os chamados marcadores de conflito, 106mostrando onde está o conflito e como as duas ramificações divergiram. Resolver 107o conflito normalmente significa editar o resultado final de forma que ele leve 108em consideração esses outros commits. 109 110A resolução do conflito pode ser feita manualmente em um editor de texto comum 111ou usando uma ferramenta dedicada de resolução de conflitos. 112 113Muitas pessoas preferem usar seu editor de texto comum e editar o conflito 114diretamente, pois pode ser mais fácil entender o que você está fazendo e 115controlar o resultado final. Definitivamente, existem prós e contras em cada 116método, e às vezes há valor em usar ambos. 117 118Não abordaremos o uso de ferramentas de mesclagem (merge tools) dedicadas aqui, 119além de fornecer algumas indicações de várias ferramentas que você poderia usar: 120 121- `Modo Emacs Ediff <https://www.emacswiki.org/emacs/EdiffMode>`__ 122- `vimdiff/gvimdiff <https://linux.die.net/man/1/vimdiff>`__ 123- `KDiff3 <http://kdiff3.sourceforge.net/>`__ 124- `TortoiseMerge <https://tortoisesvn.net/TortoiseMerge.html>`__ 125- `Meld <https://meldmerge.org/help/>`__ 126- `P4Merge <https://www.perforce.com/products/helix-core-apps/merge-diff-tool-p4merge>`__ 127- `Beyond Compare <https://www.scootersoftware.com/>`__ 128- `IntelliJ <https://www.jetbrains.com/help/idea/resolve-conflicts.html>`__ 129- `VSCode <https://code.visualstudio.com/docs/editor/versioncontrol>`__ 130 131Para configurar o git para funcionar com elas, veja ``git mergetool --help`` ou 132a `documentação oficial do git-mergetool`_. 133 134.. _documentação oficial do git-mergetool: https://git-scm.com/docs/git-mergetool 135 136Patches pré-requisitos 137---------------------- 138 139A maioria dos conflitos acontece porque a ramificação para a qual você está 140fazendo o backport não possui alguns patches em comparação com a ramificação a 141partir da qual você está fazendo o backport. No caso mais geral (como a 142mesclagem de duas ramificações independentes), o desenvolvimento poderia ter 143ocorrido em qualquer uma das ramificações, ou as ramificações simplesmente 144divergiram -- talvez a sua ramificação mais antiga tenha recebido alguns outros 145backports que, por si só, precisaram de resoluções de conflitos, causando uma 146divergência. 147 148É importante sempre identificar o commit ou os commits que causaram o conflito, 149pois, caso contrário, você não poderá ter confiança na correção da sua 150resolução. Como um bônus adicional, especialmente se o patch for em uma área com 151a qual você não está muito familiarizado, os registros de alterações (changelogs) 152desses commits frequentemente lhe darão o contexto para entender o código e os 153problemas ou armadilhas potenciais com a sua resolução de conflito. 154 155git log 156~~~~~~~ 157 158Um bom primeiro passo é olhar o ``git log`` para o arquivo que possui o 159conflito -- isso geralmente é suficiente quando não há muitos patches no 160arquivo, mas pode ficar confuso se o arquivo for grande e frequentemente 161modificado por patches. Você deve executar o ``git log`` no intervalo de commits 162entre a sua ramificação atualmente ativa (``HEAD``) e o pai do patch que você está 163escolhendo (``<commit>``), ou seja:: 164 165 git log HEAD..<commit>^ -- <path> 166 167Melhor ainda, se você quiser restringir essa saída a uma única função (porque é 168onde o conflito aparece), você pode usar a seguinte sintaxe:: 169 170 git log -L:'\<function\>':<path> HEAD..<commit>^ 171 172.. note:: 173 O ``\<`` e o ``\>`` ao redor do nome da função garantem que as 174 correspondências fiquem ancoradas em um limite de palavra. Isso é 175 importante, pois essa parte é na verdade uma regex e o git segue apenas a 176 primeira correspondência; portanto, se você usar 177 ``-L:thread_stack:kernel/fork.c``, ele poderá fornecer apenas resultados 178 para a função ``try_release_thread_stack_to_cache``, embora existam muitas 179 outras funções naquele arquivo contendo a string ``thread_stack`` em seus 180 nomes. 181 182Outra opção útil para o ``git log`` é a ``-G``, que permite filtrar por certas 183strings que aparecem nos diffs dos commits que você está listando:: 184 185 git log -G'regex' HEAD..<commit>^ -- <path> 186 187Esta também pode ser uma maneira prática de encontrar rapidamente quando algo 188(por exemplo, uma chamada de função ou uma variável) foi alterado, adicionado 189ou removido. A string de busca é uma expressão regular, o que significa que você 190pode potencialmente buscar por coisas mais específicas, como atribuições a um 191membro específico de uma struct:: 192 193 git log -G'\->index\>.*=' 194 195git blame 196~~~~~~~~~ 197 198Outra maneira de encontrar commits pré-requisitos (embora apenas o mais recente 199para um determinado conflito) é executar o ``git blame``. Neste caso, você 200precisa executá-lo no commit pai do patch para o qual está fazendo o 201cherry-pick e no arquivo onde o conflito apareceu, ou seja:: 202 203 git blame <commit>^ -- <path> 204 205Este comando também aceita o argumento ``-L`` (para restringir a saída a uma 206única função), mas, neste caso, você especifica o nome do arquivo no final do 207comando, como de costume:: 208 209 git blame -L:'\<function\>' <commit>^ -- <path> 210 211Navegue até o local onde o conflito ocorreu. A primeira coluna da saída do 212blame é o ID do commit do patch que adicionou uma determinada linha de código. 213 214Pode ser uma boa ideia dar um ``git show`` nesses commits e ver se eles se 215parecem com a possível origem do conflito. Às vezes, haverá mais de um desses 216commits, seja porque múltiplos commits alteraram linhas diferentes da mesma área 217de conflito *ou* porque múltiplos patches subsequentes alteraram a mesma linha 218(ou linhas) várias vezes. Neste último caso, você pode ter que executar o 219``git blame`` novamente e especificar a versão mais antiga do arquivo para 220analisar, a fim de cavar mais fundo no histórico do arquivo. 221 222Patches pré-requisitos vs. incidentais 223~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 224 225Tendo encontrado o patch que causou o conflito, você precisa determinar se ele 226é um pré-requisito para o patch que você está fazendo o backport ou se é apenas 227incidental e pode ser pulado. Um patch incidental seria aquele que toca no mesmo 228código que o patch para o qual você está fazendo o backport, mas não altera a 229semântica do código de nenhuma forma relevante. Por exemplo, um patch de limpeza 230de espaços em branco é completamente incidental -- da mesma forma, um patch que 231simplesmente renomeia uma função ou uma variável também seria incidental. Por 232outro lado, se a função que está sendo alterada sequer existe na sua ramificação 233atual, então isso não seria nada incidental e você precisa considerar com 234cuidado se o patch que adiciona a função deve ser aplicado via cherry-pick 235primeiro. 236 237Se você descobrir que há um patch pré-requisito necessário, então você precisa 238parar e fazer o cherry-pick dele em vez disso. Se você já resolveu alguns 239conflitos em um arquivo diferente e não quer fazer isso de novo, você pode 240criar uma cópia temporária daquele arquivo. 241 242Para abortar o cherry-pick atual, vá em frente e execute 243``git cherry-pick --abort`` e, em seguida, reinicie o processo de cherry-pick 244com o ID do commit do patch pré-requisito. 245 246Entendendo os marcadores de conflito 247------------------------------------ 248 249Diffs combinados 250~~~~~~~~~~~~~~~~ 251 252Digamos que você tenha decidido não fazer o cherry-pick (ou o revert) de patches 253adicionais e quer apenas resolver o conflito. O Git terá inserido marcadores de 254conflito no seu arquivo. Por padrão, isso se parecerá com algo como:: 255 256 <<<<<<< HEAD 257 this is what's in your current tree before cherry-picking 258 ======= 259 this is what the patch wants it to be after cherry-picking 260 >>>>>>> <commit>... title 261 262Isso é o que você veria se abrisse o arquivo no seu editor. No entanto, se você 263executasse o ``git diff`` sem nenhum argumento, a saída seria algo assim:: 264 265 $ git diff 266 [...] 267 ++<<<<<<<< HEAD 268 +this is what's in your current tree before cherry-picking 269 ++======== 270 + this is what the patch wants it to be after cherry-picking 271 ++>>>>>>>> <commit>... title 272 273Quando você está resolvendo um conflito, o comportamento do ``git diff`` difere 274do seu comportamento normal. Note as duas colunas de marcadores de diff em vez 275da coluna única usual; este é o chamado "`diff combinado`_", aqui mostrando o 276diff de 3 vias (ou diff-de-diffs) entre: 277 278#. a ramificação atual (antes do cherry-pick) e o diretório de trabalho atual, e 279#. a ramificação atual (antes do cherry-pick) e o arquivo como ele fica após o 280 patch original ter sido aplicado. 281 282.. _diff combinado: https://git-scm.com/docs/diff-format#_combined_diff_format 283 284Diffs melhores 285~~~~~~~~~~~~~~ 286 287Diffs combinados de 3 vias incluem todas as outras alterações que aconteceram 288no arquivo entre a sua ramificação atual e a ramificação a partir da qual você 289está fazendo o cherry-pick. Embora isso seja útil para detectar outras 290alterações que você precisa levar em consideração, também torna a saída do 291``git diff`` um tanto intimidadora e difícil de ler. Em vez disso, você pode 292preferir executar ``git diff HEAD`` (ou ``git diff --ours``), que mostra apenas 293o diff entre a ramificação atual antes do cherry-pick e o diretório de trabalho 294atual. Ele se parece com isso:: 295 296 $ git diff HEAD 297 [...] 298 +<<<<<<<< HEAD 299 this is what's in your current tree before cherry-picking 300 +======== 301 +this is what the patch wants it to be after cherry-picking 302 +>>>>>>>> <commit>... title 303 304Como você pode ver, isso é lido exatamente como qualquer outro diff e deixa claro 305quais linhas estão na ramificação atual e quais linhas estão sendo adicionadas 306porque fazem parte do conflito de mesclagem ou do patch que está sendo aplicado 307via cherry-pick. 308 309Estilos de mesclagem e diff3 310~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 311 312O estilo padrão de marcador de conflito mostrado acima é conhecido como o estilo 313``merge``. Também está disponível um outro estilo, conhecido como o estilo 314``diff3``, que se parece com isso:: 315 316 <<<<<<< HEAD 317 this is what is in your current tree before cherry-picking 318 ||||||| parent of <commit> (title) 319 this is what the patch expected to find there 320 ======= 321 this is what the patch wants it to be after being applied 322 >>>>>>> <commit> (title) 323 324Como você pode ver, isso tem 3 partes em vez de 2, e inclui o que o git 325esperava encontrar lá, mas não encontrou. É *altamente recomendável* usar este 326estilo de conflito, pois deixa muito mais claro o que o patch realmente alterou; 327ou seja, ele permite que você compare as versões de antes e depois do arquivo 328para o commit do qual está fazendo o cherry-pick. Isso permite que você tome 329melhores decisões sobre como resolver o conflito. 330 331Para alterar os estilos de marcadores de conflito, você pode usar o seguinte 332comando:: 333 334 git config merge.conflictStyle diff3 335 336Existe uma terceira opção, ``zdiff3``, introduzida no `Git 2.35`_, que possui as 337mesmas 3 seções do ``diff3``, mas onde as linhas comuns foram cortadas, tornando 338a área de conflito menor em alguns casos. 339 340.. _Git 2.35: https://github.blog/2022-01-24-highlights-from-git-2-35/ 341 342Iterando em resoluções de conflito 343---------------------------------- 344 345O primeiro passo em qualquer processo de resolução de conflito é entender o 346patch para o qual você está fazendo o backport. Para o kernel Linux, isso é 347especialmente importante, pois uma alteração incorreta pode levar ao travamento 348de todo o sistema -- ou pior, a uma vulnerabilidade de segurança não detectada. 349 350Entender o patch pode ser fácil ou difícil, dependendo do próprio patch, do 351registro de alterações (changelog) e da sua familiaridade com o código que está 352sendo alterado. No entanto, uma boa pergunta para cada alteração (ou cada bloco/ 353hunk do patch) seria: "Por que este hunk está no patch?" As respostas a essas 354perguntas orientarão a sua resolução de conflito. 355 356Processo de resolução 357~~~~~~~~~~~~~~~~~~~~~ 358 359Às vezes, a coisa mais fácil a fazer é apenas remover tudo, exceto a primeira 360parteda do conflito, deixando o arquivo essencialmente inalterado, e aplicar 361as alterações manualmente. Talvez o patch esteja alterando um argumento de 362chamada de função de ``0`` para ``1``, enquanto uma alteração conflitante 363adicionou um parâmetro totalmente novo (e insignificante) ao final da lista de 364parâmetros; nesse caso, é bastante fácil alterar o argumento de ``0`` para ``1`` 365manualmente e deixar o restante dos argumentos como estão. Esta técnica de 366aplicar alterações manualmente é mais útil se o conflito tiver trazido muito 367contexto não relacionado com o qual você não precisa realmente se preocupar. 368 369Para conflitos particularmente difíceis com muitos marcadores de conflito, você 370pode usar ``git add`` ou ``git add -i`` para indexar (stage) seletivamente as 371suas resoluções para tirá-las do caminho; isso também permite que você use 372``git diff HEAD`` para ver sempre o que ainda resta a ser resolvido ou 373``git diff --cached`` para ver como está o seu patch até o momento. 374 375Lidando com arquivos renomeados 376~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 377 378Uma das coisas mais irritantes que podem acontecer ao fazer o backport de um 379patch é descobrir que um dos arquivos modificados foi renomeado, pois isso 380geralmente significa que o git sequer colocará marcadores de conflito, mas 381apenas lavará as mãos e dirá (parafraseando): "Caminho não mesclado! Faça você o 382trabalho..." 383 384Geralmente existem algumas maneiras de lidar com isso. Se o patch para o 385arquivo renomeado for pequeno, como uma alteração de uma única linha, a coisa 386mais fácil é prosseguir, aplicar a alteração manualmente e dar o caso por 387encerrado. Por outro lado, se a alteração for grande ou complicada, você 388definitivamente não vai querer fazê-la manualmente. 389 390Como uma primeira tentativa, você pode tentar algo assim, que reduzirá o limite 391(threshold) de detecção de renomeação para 30% (por padrão, o git usa 50%, o que 392significa que dois arquivos precisam ter pelo menos 50% em comum para que ele 393considere um par de adição/remoção como uma renomeação potencial):: 394 395 git cherry-pick -strategy=recursive -Xrename-threshold=30 396 397Às vezes, a coisa certa a fazer será fazer o backport também do patch que 398realizou a renomeação, mas esse definitivamente não é o caso mais comum. Em vez 399disso, o que você pode fazer é renomear temporariamente o arquivo na 400ramificação para a qual está fazendo o backport (usando ``git mv`` e commitando 401o resultado), reiniciar a tentativa de cherry-pick do patch, renomear o arquivo 402de volta (``git mv`` e commitando novamente) e, finalmente, esmagar (squash) o 403resultado usando ``git rebase -i`` (veja o `tutorial de rebase`_) para que ele 404apareça como um único commit quando você terminar. 405 406.. _tutorial de rebase: [https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec](https://medium.com/@slamflipstrom/a-beginners-guide-to-squashing-commits-with-git-rebase-8185cf6e62ec) 407 408Pegadinhas 409---------- 410 411Argumentos de função 412~~~~~~~~~~~~~~~~~~~~ 413 414Preste atenção às alterações em argumentos de função! É fácil deixar passar 415detalhes e pensar que duas linhas são iguais quando, na verdade, elas diferem em 416algum pequeno detalhe, como qual variável foi passada como argumento 417(especialmente se as duas variáveis forem de apenas um caractere e parecerem 418iguais, como i e j). 419 420Tratamento de erros 421~~~~~~~~~~~~~~~~~~~ 422 423Se você fizer o cherry-pick de um patch que inclua uma instrução ``goto`` 424(geralmente para tratamento de erros), é absolutamente imperativo verificar em 425dobro se o rótulo (label) de destino ainda está correto na ramificação para a 426qual você está fazendo o backport. O mesmo vale para instruções ``return``, 427``break`` e ``continue`` adicionadas. 428 429O tratamento de erros geralmente fica localizado no final da função, portanto, 430pode não fazer parte do conflito, mesmo que possa ter sido alterado por outros 431patches. 432 433Uma boa maneira de garantir que você revise os caminhos de erro é sempre usar 434``git diff -W`` e ``git show -W`` (também conhecido como ``--function-context``) 435ao inspecionar suas alterações. Para código em C, isso mostrará toda a função 436que está sendo alterada em um patch. Uma das coisas que frequentemente dão 437errado durante backports é que algo mais na função mudou em qualquer uma das 438ramificações a partir da qual ou para a qual você está fazendo o backport. Ao 439incluir a função inteira no diff, você obtém mais contexto e pode identificar 440mais facilmente problemas que de outra forma poderiam passar despercebidos. 441 442Código refatorado 443~~~~~~~~~~~~~~~~~ 444 445Algo que acontece com bastante frequência é o código ser refatorado ao "isolar" 446uma sequência ou padrão de código comum em uma função auxiliar. Ao fazer o 447backport de patches para uma área onde tal refatoração ocorreu, você efetivamente 448precisa fazer o inverso ao realizar o backport: um patch para um único local pode 449precisar ser aplicado a múltiplos locais na versão que recebeu o backport. (Um 450indicativo para este cenário é que uma função foi renomeada -- mas nem sempre é o 451caso.) 452 453Para evitar backports incompletos, vale a pena tentar descobrir se o patch 454corrige um bug que aparece em mais de um lugar. Uma maneira de fazer isso seria 455usar o ``git grep``. (Isso, na verdade, é uma boa ideia de se fazer em geral, não 456apenas para backports.) Se você descobrir que o mesmo tipo de correção se 457aplicaria a outros lugares, também vale a pena ver se esses lugares existem no 458upstream -- se não existirem, é provável que o patch precise ser ajustado. O 459``git log`` é seu amigo para descobrir o que aconteceu com essas áreas, já que o 460``git blame`` não mostrará código que foi removido. 461 462Se você encontrar outras instâncias do mesmo padrão na árvore do upstream e não 463tiver certeza se isso também é um bug, pode valer a pena perguntar ao autor do 464patch. Não é incomum encontrar novos bugs durante o processo de backport! 465 466Verificando o resultado 467======================= 468 469colordiff 470--------- 471 472Tendo commitado um novo patch sem conflitos, você pode agora comparar o seu 473patch com o patch original. É altamente recomendável que você use uma 474ferramenta como o `colordiff`_ que possa mostrar dois arquivos lado a lado e 475colori-los de acordo com as alterações entre eles:: 476 477 colordiff -yw -W 200 <(git diff -W <upstream commit>^-) <(git diff -W HEAD^-) | less -SR 478 479.. _colordiff: https://www.colordiff.org/ 480 481Aqui, ``-y`` significa fazer uma comparação lado a lado; ``-w`` ignora 482espaços em branco e ``-W 200`` define a largura da saída (caso contrário, ele 483usará 130 por padrão, o que costuma ser um pouco pouco). 484 485A sintaxe ``rev^-`` é um atalho prático para ``rev^..rev``, essencialmente 486fornecendo apenas o diff para aquele único commit; veja também a 487`documentação oficial do git rev-parse`_. 488 489.. _documentação oficial do git rev-parse: https://git-scm.com/docs/git-rev-parse#_other_rev_parent_shorthand_notations 490 491Novamente, note a inclusão de ``-W`` para o ``git diff``; isso garante que você 492verá a função completa para qualquer função que tenha mudado. 493 494Uma coisa incrivelmente importante que o colordiff faz é destacar as linhas que 495são diferentes. Por exemplo, se um ``goto`` de tratamento de erros teve seus 496rótulos alterados entre o patch original e o que sofreu o backport, o colordiff 497irá mostrá-los lado a lado, mas destacados em uma cor diferente. Assim, é fácil 498ver que as duas instruções ``goto`` estão saltando para rótulos diferentes. Da 499mesma forma, linhas que não foram modificadas por nenhum dos patches, mas que 500diferem no contexto, também serão destacadas e, portanto, se destacarão durante 501uma inspeção manual. 502 503Claro, esta é apenas uma inspeção visual; o teste real é compilar e executar o 504kernel (ou programa) com o patch aplicado. 505 506Testes de compilação (Build testing) 507------------------------------------ 508 509Não abordaremos os testes em tempo de execução aqui, mas pode ser uma boa ideia 510compilar apenas os arquivos tocados pelo patch como uma verificação rápida de 511sanidade. Para o kernel Linux, você pode compilar arquivos únicos assim, 512assumindo que você tenha o ``.config`` e o ambiente de compilação configurados 513corretamente:: 514 515 make caminho/para/o/arquivo.o 516 517Note que isso não descobrirá erros de ligação (linker errors), então você ainda 518deve fazer uma compilação completa após verificar que o arquivo único compila. 519Ao compilar o arquivo único primeiro, você pode evitar ter que esperar por uma 520compilação completa *caso* haja erros de compilador em qualquer um dos arquivos 521que você alterou. 522 523Testes em tempo de execução 524--------------------------- 525 526Mesmo um teste de compilação ou de boot bem-sucedido não é necessariamente o 527suficiente para descartar uma dependência ausente em algum lugar. Embora as 528chances sejam pequenas, pode haver alterações de código onde duas modificações 529independentes no mesmo arquivo resultem em nenhum conflito, nenhum erro em tempo 530de compilação e erros em tempo de execução apenas em casos excepcionais. 531 532Um exemplo concreto disso foi um par de patches para o código de entrada de 533chamada de sistema (system call entry code), onde o primeiro patch salvava/ 534restaurava um registrador e um patch posterior fazia uso do mesmo registrador 535em algum lugar no meio dessa sequência. Como não havia sobreposição entre as 536alterações, era possível fazer o cherry-pick do segundo patch, não ter conflitos 537e acreditar que tudo estava bem, quando na verdade o código estava agora 538sobrescrevendo (scribbling over) um registrador não salvo. 539 540Embora a vasta maioria dos erros seja capturada durante a compilação ou ao 541exercitar o código superficialmente, a única maneira de *realmente* verificar um 542backport é revisar o patch final com o mesmo nível de escrutínio que você daria 543(ou deveria dar) a qualquer outro patch. Ter testes unitários e testes de 544regressão ou outros tipos de testes automáticos pode ajudar a aumentar a 545confiança na correção de um backport. 546 547Enviando backports para a árvore estável (stable) 548================================================= 549 550À medida que os mantenedores da árvore estável tentam aplicar correções da linha 551principal (mainline) em seus kernels estáveis via cherry-pick, eles podem enviar 552e-mails solicitando backports quando encontram conflitos; veja, por exemplo, 553<https://lore.kernel.org/stable/2023101528-jawed-shelving-071a@gregkh/>. 554Esses e-mails normalmente incluem os passos exatos que você precisa seguir para 555fazer o cherry-pick do patch para a árvore correta e enviá-lo. 556 557Uma coisa a se certificar é que o seu registro de alterações (changelog) esteja 558em conformidade com o formato esperado:: 559 560 <original patch title> 561 562 [ Upstream commit <mainline rev> ] 563 564 <rest of the original changelog> 565 [ <summary of the conflicts and their resolutions> ] 566 Signed-off-by: <your name and email> 567 568A linha "Upstream commit" às vezes é ligeiramente diferente dependendo da versão 569estável. Versões mais antigas usavam este formato:: 570 571 commit <mainline rev> upstream. 572 573O mais comum é indicar a versão do kernel à qual o patch se aplica na linha de 574assunto do e-mail (usando, por exemplo, 575``git send-email --subject-prefix='PATCH 6.1.y'``), mas você também pode 576colocá-la na área do Signed-off-by: ou abaixo da linha ``---``. 577 578Os mantenedores da árvore estável esperam envios separados para cada versão 579estável ativa, e cada envio também deve ser testado separadamente. 580 581Algumas palavras finais de conselho 582=================================== 583 5841) Aborde o processo de backport com humildade. 5852) Entenda o patch para o qual você está fazendo o backport; isso significa ler 586 tanto o registro de alterações (changelog) quanto o código. 5873) Seja honesto sobre a sua confiança no resultado ao enviar o patch. 5884) Peça aprovações explícitas (acks) aos mantenedores relevantes. 589 590Exemplos 591======== 592 593O texto acima mostra, de forma geral, o processo idealizado de backport de um 594patch. Para um exemplo mais concreto, veja este tutorial em vídeo onde dois 595patches são portados da linha principal (mainline) para a estável (stable): 596`Backporting Linux Kernel Patches`_. 597 598.. _Backporting Linux Kernel Patches: https://youtu.be/sBR7R1V2FeA