xref: /linux/Documentation/translations/pt_BR/process/backporting.rst (revision 72fdff1416e280e2baaa3cca69574defb998437e)
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