From f2893662015bc191b26c29068251e52a6c306188 Mon Sep 17 00:00:00 2001 From: Marco Paganini Date: Sat, 2 Nov 2024 13:24:52 -0700 Subject: [PATCH] Adiciona artigo sobre git reset. --- content/blog/git-reset.md | 164 ++++++++++++++++++++++++++++++++++++ static/img/banners/git.webp | Bin 0 -> 11990 bytes 2 files changed, 164 insertions(+) create mode 100644 content/blog/git-reset.md create mode 100644 static/img/banners/git.webp diff --git a/content/blog/git-reset.md b/content/blog/git-reset.md new file mode 100644 index 00000000..32e550c2 --- /dev/null +++ b/content/blog/git-reset.md @@ -0,0 +1,164 @@ ++++ +title = "Help! Múltiplos desafios no meu PR!" +date = "2024-11-02T13:00:00-07:00" +tags = ["programação", "git"] +categories = ["git"] +banner = "img/banners/git.webp" ++++ + +## Help! Múltiplos desafios no meu PR! + +Este artigo contem uma explicação para uma pergunta frequente: "Por que o meu +PR tem múltiplos desafios se eu já enviei os anteriores?" + +TL;DR: Este problema acontece quando o usuário começa um novo desafio sem +sincronizar o repositório local com o conteúdo do repositório _upstream_ +(nesse caso, osprogramadores). + +## Conceitos importantes + +1. **upstream** se refere ao repositório principal do os-programadores. + Usuários não tem acesso a push a esse repositório. +1. **origin** Aponta para o seu _fork_. O usuário dono do repositório tem + acesso completo a esse repositório e pode usar `git push` para enviar + modificações. +1. **Pull Request (PR)** é uma requisição de modificação do repositório + upstream a partir de modificações no seu fork. O PR é aprovado pelos + administradores do os-programadores, que então passa a conter as suas + modificações. + +## Explicação detalhada + +Imagine uma situação inicial onde você faça o clone do +`osprogramadores/op-desafios` (upstream), e que existam apenas dois commits lá. +Usaremos números simples ao invés de hashes para facilitar a compreensão: + +``` +002 Desafio de outro alguém +001 Desafio de alguém +``` + +Depois do `git clone`, o repositório local fica igual ao upstream (dica: +use `git log --oneline --all` para verificar): + +``` +002 Desafio de outro alguém +001 Desafio de alguém +``` + +Nesse momento, você começa a trabalhar em um novo desafio (não importa qual o +branch, vamos supor que seja `master`, para efeito de simplicidade). Depois de +um commit inicial e uma correção, o repositório local agora contém os seguintes +commits: + +``` +301 Correção do meu novo desafio. +300 Meu novo desafio +002 Desafio de outro alguém +001 Desafio de alguém +``` + +Novamente, observe que os números de commit acima são uma simplificação. Usamos +300 em diante para commits feitos a partir de uma modificação local. Na prática +são hashes. Use `git log --oneline --all` para ver a lista de commits no +repositório. + +Com tudo confirmado, é hora de fazer um push para o seu fork e criar um PR. O +comando `git push origin/master --force` envia as modificações para o seu fork +no github. A partir daí, cria-se um PR, que basicamente é um diff entre o seu +fork e o upstream. + +O PR é então analisado pelos administradores do repositório. Se tudo estiver +certo, os administradores aprovarão e farão o "merge" do repositório. + +No caso do os-programadores, os administradores optaram por usar +**rebase/squash**, para manter o repositório linear. Em termos simples, isso +quer dizer que o commit 300 e 301 (vindos do seu fork) vão ser reescritos +como apenas *um* commit antes do merge. Após o rebase/squash, o upstream fica +da seguinte forma: + +``` +003 Desafio do Gabriel <-- Nome do commit mudado. Inclui 300 e 301! +002 Desafio de outro alguém +001 Desafio de alguém +``` + +Repare que o commit 003 agora no upstream é a combinação de dois commits seus +(300 e 301). O upstream não tem a mínima ideia do que sejam 300 e 301, já que +eles não existem lá. + +Nesse momento, você começa OUTRO desafio, e se esquece de fazer o _reset_ +do repositório! No seu segundo desafio, cria mais um commit (400). O seu +repositório local agora tem a seguinte estrutura de commits: + +``` +400 Mais um desafio novinho! <-- Novo desafio +301 Correção do meu novo desafio. +300 Meu novo desafio +002 Desafio de outro alguém +001 Desafio de alguém +``` + +Um novo `git push origin/master --force` faz o upload do repositório local +para o seu fork (que naturalmente fica idêntico ao repositório local). Quando +o novo PR request é criado, algo interessante acontece: O upstream só tem os +commits 001, 002 e 003, logo ele ignora o 001 e 002 no seu fork (ele já sabe +que tem esses, eles não criam um diff), mas dessa vez o seu repositório também +contem os commits 300, 301, e 400. O resultado? **No PR aparecem os três +commits e os dois arquivos**, mostrando dois desafios no PR quando apenas um +foi adicionado. + +## Evitando o problema + +Lembre-se que usamos rebase+squash no merge dos PRs para manter o repositório +principal linear. O efeito colateral disso é que essa operação **sempre cria +um commit novo a partir dos seus commits**. Logo, **sempre use `git reset +upstream master` antes de começar a trabalhar em um novo desafio**, e sempre +use um `git pull upstream master -r` para fazer um rebase das suas +modificações antes de enviar o PR. + +Complicado? Vamos por partes: + +Antes de começar um novo desafio (ou qualquer outra modificação), tenha +certeza de que o seu repositório está idêntico ao upstream/master: + +```bash +git remote update +git reset upstream/master --hard +``` + +Trabalhe normalmente. Antes de enviar o push, execute: + +```bash +git pull -r upstream master +``` + +Isso fará um *rebase* das suas mudanças em cima do upstream. Basicamente ele +lê o upstream para dentro do seu repositório e reaplica suas mudanças no topo +do upstream. + +É importante nunca usar merge (`git pull` sem `-r` ou `git merge`), já que ele +cria um merge commit que vai complicar a visualização do seu repositório. + +## Como resolver o problema em um PR já existente? + +Se um PR problemático já foi criado, a solução é relativamente simples: + +1. Use `git remote update` para atualizar as cópias locais dos repositórios + remotos. +1. Use `git reset upstream/master`. Esse comando joga o HEAD do seu repositório + para o HEAD do upstream/master (atenção: **não use `--hard` aqui**). +1. Use o comando `git status`. É provável que várias alterações não + relacionadas com as suas modificações existam (arquivos deletados, criados, + etc). Use `git restore` em todos os arquivos que não rejam relacionados com + o seu PR. +1. Adicione as suas modificações novamente com `git add` (elas estão intactas, + mas precisam ser adicionadas após o `git reset`) +1. Faça o commit novamente com `git commit`. +1. Faça o upload para o seu fork com `git push origin master --force`. +1. Deixe um comentário no PR (github) informando que o problema foi corrigido. + **Não é necessário fechar o PR e/ou criar outro.** + +## Se tudo falhar? + +Pergunte a um dos admins no grupo [os-programadores](http://t.me/os-programadores). diff --git a/static/img/banners/git.webp b/static/img/banners/git.webp new file mode 100644 index 0000000000000000000000000000000000000000..dca05632c105e533eb384103974f5972b752f056 GIT binary patch literal 11990 zcmV;{E-BGcNk&G_E&u>mMM6+kP&iD%E&u>8|G|F{jX-E5$&sYW%6m7@pYYC(VGz;( z3CLzg+}&u$xY7b#=!|1k=7(B!#*r4)kp~A_K$G}jt7V!b3b4_#fakvaVVMn6zwG&6uFJY*mx^;1DDUKLE17gC3|!+J67gst1~kwxtsfEI(Z6e{9Q^ zFKrXLK63^n{2pFjJ)xH}wkD7xNm3-aEyFQA&qjZ#Mua+M z?CPFg4IoFd?W$?Khe3X&dLbzPpj3a2D@ctbNs=7O@JBNMW_L}cP-&if0qFk(&_oWO zh<|iQl!gNc6+kzyp~|zCipBDVC_w|?BLJwj*qI%8iBm@YQoI$NYHjGp3_G5*Z9@L)AoXvJb zGuy1kARy3GF`#6N;4#%mE*v5b)S?CN7xdg0rq=;fw@LY?%>UkkS-& z&`n}sH38**)guCU!2BW35jd-y)>E8&+(o>#EjhC7YRA3c+z|MH0gV~JnE^0?sgS4& zKVS+(=zv5%XJ?P`?>Si!u_GfR-%}t*lB7uTIEJy)U%dUD3fu{ykt9b_$>&@z0ke$*OJJwxw2j>x-G0 zdC1DaO2kU}n)840T3>5z-h)T0Ey8nb+pcX(lGOS_|ywrv}4+gPIpvS{0?+G@)li`=y7@dS+lHIMrT z2Aq0$)BSIC$aR6MRXVGntSnA>Bg=u66F^dvN~2i<@?*Sx5BntXx(+@9MS6PqC*`QU z{QGcqUPDXgX;wN4WC4&cp}@r3zlrBbXFiVif8l?QgY<%|w_bm5m}pU%p6bX609I!| zm+YlNMI_b?=w z2H{4dQp%$4S-C>1l2`ve>x&Aaf-r^>>6*^cL9!$!5oHu2iK2pXlqE7|TO=2(s%>en zdvVoE|0REUbXS(kSj8kxb05v6iOvogb_JwRDgCCuGtemL>mqcyE3kO8GMvtImHCvzkL4iW5%5}LEIrTPH-^bBS zdq>~aaQbuAGSbvK+8-dVd_(hDuz*UP&+Jf6AY;>v&!fFDLvj)UsFc=@7Jy2&nGY**$jSad z!0L7GqTaMhF5cC`+`a?>{Lim*dGSB)CsE*1g<3~&AY8%_SJ~FMa{;l$$G{pSJ_h7M zk1F#Piy-cA2Ly>q3A@?>-L!y9n5&!)2@71Wkg)FQhARsT#dP3;6+a5cUG_QUZC5Dw zb~=J@$C0QrZneufEM?jIbf*K6Cvj~OAMFU-l_nJhR^HV-4HEMfkRa|V*(93_A}VoL z+He+}wNfaTwXczwH2weR+J$)&>~vpEO|8HcJ&M6+xZ)%^2Wb%)mw7gtLJZ&<;+?-< z_c?7RHWv}35=v^+_cGl=a;0(R(aB}?K7}hzT8Uc-%#(>J77_S}OoC?k(`E23&q}w@ z3TQ4#y~~Qz{Yt6h6%?V>K|7A92bi^hrvG;j*Z0L;YN!>U+`)TF)UG&%9edm~uX1Nj zS##=gmh>-Nid2yYjy$is&edh-=8<69_c6`)-%N+G5gO4u7aUefYllZsPRVvL~z;7c%H1QG>1Cy4RRv;ifh zkm=nIzWMMZrJ#9V48avgDHs3d~5`dhBybtn0`32(d?|PPm3l5lf6oKw|ur zjHXG?aXh0z;{S)iBo-Y1JG>4!V`fAYYMU5MQ(sy;Q#;3&!c8Sh}Qkj1P*Rg}lY0OwZ(avafUL=E~)QVMv?;Yb~1}j}6zSJFZWM z2HSjUk4`Y6!pu=3S;+az^2y~7D&Y|unN8Q@U-!4ql+22gRv4H;ni`+L*B&2!eZ86| z-r@b>dhwl?CtogiC4M%H7Qd z62wf*OEwPgQKhds^7EaWPUe?T^Is`T=fe$;QxeMv7dbf(IJ@O=d~>Y7Bk#w}^Wm&L zuKTx;$k{D*I%Q@;v8uvIdlB%3&ei)8IeCy!h{MP>HXM7j;}y=@msv(Mm#4;Z≷| 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

b)`9 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 oTh(ZvO62mx@++4EAWMV(r`>