<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Guilherme Garcia's blog]]></title><description><![CDATA[Guilherme Garcia's blog]]></description><link>https://hashnode.guilhermegarcia.dev</link><generator>RSS for Node</generator><lastBuildDate>Fri, 17 Apr 2026 20:02:15 GMT</lastBuildDate><atom:link href="https://hashnode.guilhermegarcia.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Remova os gifs do medium]]></title><description><![CDATA[A plataforma medium tem muito conteúdo bom, mas infelizmente muitas postagens ótimas são permeadas de gifs super coloridos, que eu considero distrativos.
Quando eu tô procurando direcionamento sobre um tópico, e finalmente acho um post sobre o assunt...]]></description><link>https://hashnode.guilhermegarcia.dev/remova-os-gifs-do-medium</link><guid isPermaLink="true">https://hashnode.guilhermegarcia.dev/remova-os-gifs-do-medium</guid><category><![CDATA[bookmarklet]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[medium]]></category><dc:creator><![CDATA[Guilherme Garcia]]></dc:creator><pubDate>Thu, 15 Dec 2022 23:33:12 GMT</pubDate><content:encoded><![CDATA[<p>A plataforma medium tem muito conteúdo bom, mas infelizmente muitas postagens ótimas são permeadas de gifs super coloridos, que eu considero distrativos.</p>
<p>Quando eu tô procurando direcionamento sobre um tópico, e finalmente acho um post sobre o assunto, eu não gosto muito da mudança de tom que os gifs trazem, inseridos a cada parágrafo, tipo um comic relief desnecessário (<a target="_blank" href="https://www.google.com/search?channel=fs&amp;client=ubuntu&amp;q=jar+jar+binks">ahem</a>).</p>
<p>Daí esse snippet esconde todos os gifs e põe um botãozinho pra mostrar/esconder, aí você pode dar uma olhada e desligar a coisa.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1671147059773/cww4to3FK.png" alt class="image--center mx-auto" /></p>
<p>Você pode ir "Add Bookmarks" e adicionar o seguinte, com um nome tipo "hide-medium-gifs":</p>
<pre><code class="lang-javascript">javascript:(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{<span class="hljs-keyword">const</span> doc_imgs=<span class="hljs-built_in">document</span>.querySelectorAll(<span class="hljs-string">'img'</span>);<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toggleImgVisibility</span>(<span class="hljs-params">e</span>)</span>{<span class="hljs-keyword">let</span> prevSibling=e.target.previousElementSibling;<span class="hljs-keyword">while</span>(prevSibling){<span class="hljs-keyword">if</span>(prevSibling.classList.contains(<span class="hljs-string">'hidden-g0f'</span>)){<span class="hljs-keyword">if</span>(prevSibling.style.visibility==<span class="hljs-string">'hidden'</span>){prevSibling.style.visibility=<span class="hljs-string">'visible'</span>;}<span class="hljs-keyword">else</span>{prevSibling.style.visibility=<span class="hljs-string">'hidden'</span>;}<span class="hljs-keyword">break</span>;}prevSibling=prevSibling.previousElementSibling;}}<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createToggleBtn</span>(<span class="hljs-params"></span>)</span>{<span class="hljs-keyword">const</span> button=<span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"BUTTON"</span>);button.innerText=<span class="hljs-string">"Toggle gif visibility"</span>;button.addEventListener(<span class="hljs-string">"click"</span>,toggleImgVisibility);<span class="hljs-keyword">return</span> button;}doc_imgs.forEach(<span class="hljs-function">(<span class="hljs-params">img</span>) =&gt;</span> {<span class="hljs-keyword">if</span> (!img.src.includes(<span class="hljs-string">'.gif'</span>)) <span class="hljs-keyword">return</span>;img.classList.add(<span class="hljs-string">"hidden-g0f"</span>);img.style.visibility = <span class="hljs-string">"hidden"</span>;img.parentElement.appendChild(createToggleBtn());});}())
</code></pre>
<p>Daí, em qualquer página do medium (por <a target="_blank" href="https://medium.com/perry-street-software-engineering/clean-api-architecture-2b57074084d5">exemplo...</a>), basta clicar no favorito criado, e pronto: gifs pausáveis.</p>
<p>Você pode ver ele funcionando <a target="_blank" href="https://guilhermegarcia.dev/blog/imgs/remova-os-gifs-do-medium/hide-g0fs.mp4">clicando aqui</a>.</p>
<p>Abaixo eu explico melhor a função.</p>
<hr />
<p>O código é o seguinte:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> doc_imgs = <span class="hljs-built_in">document</span>.querySelectorAll(<span class="hljs-string">'img'</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toggleImgVisibility</span>(<span class="hljs-params">e</span>) </span>{ <span class="hljs-keyword">let</span> prevSibling = e.target.previousElementSibling; <span class="hljs-keyword">while</span> (prevSibling) { <span class="hljs-keyword">if</span> (prevSibling.classList.contains(<span class="hljs-string">'hidden-g0f'</span>)) { <span class="hljs-keyword">if</span> (prevSibling.style.visibility == <span class="hljs-string">'hidden'</span>) { prevSibling.style.visibility = <span class="hljs-string">'visible'</span>; } <span class="hljs-keyword">else</span> { prevSibling.style.visibility = <span class="hljs-string">'hidden'</span>; } <span class="hljs-keyword">break</span>; } prevSibling = prevSibling.previousElementSibling; } }

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createToggleBtn</span>(<span class="hljs-params"></span>) </span>{ <span class="hljs-keyword">const</span> button = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">"BUTTON"</span>); button.innerText = <span class="hljs-string">"Toggle gif visibility"</span>; button.addEventListener(<span class="hljs-string">"click"</span>, toggleImgVisibility); <span class="hljs-keyword">return</span> button; }

doc_imgs.forEach(<span class="hljs-function">(<span class="hljs-params">img</span>) =&gt;</span> { <span class="hljs-keyword">if</span> (!img.src.includes(<span class="hljs-string">'.gif'</span>)) <span class="hljs-keyword">return</span>; img.classList.add(<span class="hljs-string">"hidden-g0f"</span>); img.style.visibility = <span class="hljs-string">"hidden"</span>; img.parentElement.appendChild(createToggleBtn()); });
</code></pre>
<p>Eu pego todas as imagens da página na variável <code>doc_imgs</code>, e itero sobre elas, verificando se o <code>src</code> da imagem tem <code>.gif</code> nele.</p>
<p>Se tiver, eu adiciono uma classe (hidden-g0f :P), e altero a propriedade <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/visibility">visibility</a> pra 'hidden'. Isso esconde o gif, mas ele continua ocupando espaço na página.</p>
<p>Depois, pego o elemento pai e adiciono um botão, pela função <code>createToggleBtn</code>.</p>
<p>Esse botão tem um <code>eventListener</code>, que é chamado no clique, a função <code>toggleImgVisibility</code>.</p>
<p>Quando ela é chamada, ela itera pelos elementos irmãos do botão, e busca aquele que tiver a classe adicionada no passo anterior.</p>
<p>Se tiver a classe, eu alterno a propriedade <code>visibility</code> entre <code>hidden</code> e <code>visible</code>.</p>
<p>Daí fica fácil esconder/mostrar os gifs um por um.</p>
<p>Fica a dica, medium ヽ(￣～￣　)ノ.</p>
<p>Tags: bookmarklet</p>
]]></content:encoded></item><item><title><![CDATA[Sempre pode suas redes]]></title><description><![CDATA[Sério, sempre pode suas redes. Docker networks abandonadas, desligadas de qualquer container podem destruir sua internet.
Eu fiquei duas semanas com problema na internet da minha máquina: por algum motivo, na rede de casa, a conexão do ubuntu ficava ...]]></description><link>https://hashnode.guilhermegarcia.dev/sempre-pode-suas-redes</link><guid isPermaLink="true">https://hashnode.guilhermegarcia.dev/sempre-pode-suas-redes</guid><category><![CDATA[docker-network]]></category><category><![CDATA[dns]]></category><category><![CDATA[computer networking]]></category><category><![CDATA[pt-br]]></category><dc:creator><![CDATA[Guilherme Garcia]]></dc:creator><pubDate>Wed, 23 Nov 2022 20:03:30 GMT</pubDate><content:encoded><![CDATA[<p>Sério, sempre pode suas redes. Docker networks abandonadas, desligadas de qualquer container podem destruir sua internet.</p>
<p>Eu fiquei duas semanas com problema na internet da minha máquina: por algum motivo, na rede de casa, a conexão do ubuntu ficava falhando.</p>
<p>Hora penava pra resolver DNSs, hora parava de funcionar completamente. Mas às vezes (geralmente quando eu pedia ajuda) ela funcionava.</p>
<p>Tentei desabilitar o IPV6 nas configurações de rede, desinstalar o systemd-resolved, mexer com o network manager, editar o /etc/resolv.conf diretamente.</p>
<p>Nada.</p>
<p>Em outras redes, na casa de amigos, na cafeteria, a internet funcionava. Eu cheguei a achar que meu provedor estava de sacanagem.</p>
<p>Até que tive que ficar num airBnb, e o problema voltou.</p>
<p>Olhei pro roteador, e era o mesmo d-link que eu tinha em casa. Já comecei a desenvolver uma crendice.</p>
<p>Acabou que não pude ir até o fim, pois um dia rodei um docker network ls e notei que tinha muita coisa na listagem.</p>
<pre><code>docker network prune
 &gt;Yes
</code></pre><p>E problema resolvido.</p>
<p>Se alguém souber mais sobre isso, ou como reproduzir o problema, por favor, entre em <a target="_blank" href="mailto:gui.garcia67@gmail.com">contato</a>.</p>
<p>Mas lembre-se: sempre pode suas redes.</p>
<p>Tags: docker, dns, networking</p>
]]></content:encoded></item><item><title><![CDATA[Making home of the WSL 2]]></title><description><![CDATA[Having recently migrated from Ubuntu to Windows as my work machine, many of the features that made my system feel like home were missing.
This post serves as a collection of solutions I found (and some I've adapted) from the web. Cheers!


Correctly ...]]></description><link>https://hashnode.guilhermegarcia.dev/making-home-of-the-wsl-2</link><guid isPermaLink="true">https://hashnode.guilhermegarcia.dev/making-home-of-the-wsl-2</guid><category><![CDATA[Windows]]></category><category><![CDATA[Windows 10]]></category><category><![CDATA[WSL]]></category><dc:creator><![CDATA[Guilherme Garcia]]></dc:creator><pubDate>Tue, 22 Nov 2022 11:37:25 GMT</pubDate><content:encoded><![CDATA[<p>Having recently migrated from Ubuntu to Windows as my work machine, many of the features that made my system feel like home were missing.</p>
<p>This post serves as a collection of solutions I found (and some I've adapted) from the web. Cheers!</p>
<hr />

<h2 id="heading-correctly-installing-docker-under-wsl">Correctly installing Docker under WSL</h2>
<p>You do not (and should not) install anything Docker related inside your WSL instances. Instead, you can use the Docker Desktop WSL 2 Backend, which will take care of integrating both systems, and running Docker both in your Windows and in your WSL instances.</p>
<p>Make sure you have WSL 2 installed. You can check, in PowerShell, running</p>
<pre><code>    wsl -l -v
</code></pre><p>If you see output like this</p>
<pre><code>    PS C:\Users\guites&gt; wsl -l -v
      NAME                   STATE           VERSION
    * Ubuntu<span class="hljs-number">-22.04</span>           Running         <span class="hljs-number">2</span>
</code></pre><p>It means you are all set. If your <code>version</code> column shows only version 1, you can <a target="_blank" href="https://learn.microsoft.com/en-us/windows/wsl/install#upgrade-version-from-wsl-1-to-wsl-2">follow the official documentation</a> to upgrade your wsl from version 1 to 2.</p>
<p>Then, you need to change the version used by your distro (in powershell):</p>
<pre><code>    wsl --set-version Ubuntu<span class="hljs-number">-22.04</span> <span class="hljs-number">2</span>
</code></pre><p>Now, if you have previously installed docker directly from inside wsl, using for example the <a target="_blank" href="https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository">docker engine for ubuntu documentation</a>, I strongly recommend uninstalling it completely.</p>
<p><a target="_blank" href="https://docs.docker.com/desktop/windows/wsl/">This post</a> goes into great detail about how you can completely remove old docker versions from wsl.</p>
<p>I found the following commands to be the only ones necessary (inside WSL):</p>
<pre><code>    sudo apt-get remove docker docker-engine docker.io containerd runc
    sudo rm -rf /<span class="hljs-keyword">var</span>/lib/docker /etc/docker /etc/apparmor.d/docker /<span class="hljs-keyword">var</span>/run/docker.sock /usr/local/bin/docker-compose /etc/docker
    sudo groupdel docker
</code></pre><p>After removing Docker from WSL (or in case you didn't have it installed in the first place), make sure to uninstall Docker from your Windows also.</p>
<p>After that, proceed with the instalation of <a target="_blank" href="https://docs.docker.com/desktop/windows/wsl/">Docker Desktop WSL 2 backend on Windows</a>.</p>
<p>Docker will create two distinct WSL containers, that can be seems running the following command from PowerShell:</p>
<pre><code>    wsl -l -v


    PS C:\Users\guites&gt; wsl -l -v
      NAME                   STATE           VERSION
    * Ubuntu<span class="hljs-number">-22.04</span>           Running         <span class="hljs-number">2</span>
      docker-desktop         Running         <span class="hljs-number">2</span>
      docker-desktop-data    Running         <span class="hljs-number">2</span>
</code></pre><p>They will be responsible for managing the communication between windows and wsl. You do not need to install anything Docker related inside of WSL.</p>
<h2 id="heading-acessing-localhost-from-within-a-docker-container">Acessing localhost from within a docker container</h2>
<p>If you have a docker container inside WSL running some application on localhost, and want to access it from another docker container inside WSL, you won't be able to reach it from <code>http://localhost</code>.</p>
<p>You will have to use your machine IP. You can find it by running</p>
<pre><code>ip addr | grep eth0

: eth0: <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BROADCAST,MULTICAST,UP,LOWER_UP</span>&gt;</span> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 174.86.26.335/20 brd 174.86.25.255 scope global eth0
    ^-------------^ ====&gt; use this IP instead of localhost</span>
</code></pre><p>Inside wsl. (<a target="_blank" href="https://superuser.com/a/1642352">source</a>)</p>
<h2 id="heading-copying-files-to-the-clipboard">Copying files to the clipboard</h2>
<p>You will not be able to run <code>xclip</code> or <code>xsel</code>, as you would in regular ubuntu.</p>
<p>Instead, you can access the <code>.exe</code> file responsible for copying in windows directly.</p>
<p>To copy the contents of a file <code>list-of-things.txt</code></p>
<pre><code>    cat list-<span class="hljs-keyword">of</span>-things.txt | clip.exe
</code></pre><p>In this situations I like to create an alias so that I can call the same command name on both my linux and windows machine.</p>
<pre><code>    echo <span class="hljs-string">"alias ,copy='clip.exe'"</span> &gt;&gt; ~/.bash_aliases
    source ~/.bash_aliases
</code></pre><p>Now, you can copy the output of any command by running, for example</p>
<pre><code>    ls -l | ,copy
</code></pre><p>And hit <kbd>ctrl + v</kbd> where you need it.</p>
<h2 id="heading-opening-files-and-the-browser-from-wsl-terminal">Opening files and the browser from WSL terminal</h2>
<p>There are many possible solutions, but the most straightforward seems to be creating an alias pointing to your browser and explorer executables.</p>
<p><strong>For the browser</strong>, you first need to find where the application binary lives in your Windows machine.</p>
<p>For firefox, you can do this by opening a new page, going to <code>about:support</code> and scrolling down to <code>Application binary</code> (right below <code>Operational System</code>).</p>
<p>Mine is <code>C:\Program Files\Mozilla Firefox\firefox.exe</code>. But you must make a few changes to that path.</p>
<ol>
<li>Change backslashes into forward slashes: <code>C:/Program Files/Mozilla Firefox/firefox.exe</code></li>
<li>Remove the <code>:</code> from the path: <code>C/Program Files/Mozilla Firefox/firefox.exe</code></li>
<li>Escape the spaces: <code>C/Program\ Files/Mozilla\ Firefox/firefox.exe</code></li>
<li>Lowercase that C: <code>c/Program\ Files/Mozilla\ Firefox/firefox.exe</code></li>
<li>(First check if you need it) append /mnt to the path: <code>/mnt/c/Program\ Files/Mozilla\ Firefox/firefox.exe</code></li>
</ol>
<p>Check that you can open it by running it in the WSL terminal:</p>
<pre><code>    /mnt/c/Program\ Files/Mozilla\ Firefox/firefox.exe<span class="hljs-string">`</span>
</code></pre><p>If everything goes well, create an alias</p>
<pre><code>    echo <span class="hljs-string">"alias ,firefox='/mnt/c/Program\ Files/Mozilla\ Firefox/firefox.exe'"</span> &gt;&gt; ~/.bash_aliases
    source ~/.bash_aliases
</code></pre><p>Test it by opening up an URL</p>
<pre><code>    ,firefox https:<span class="hljs-comment">//guilhermegarcia.dev/blog</span>
</code></pre><p><strong>For the files</strong>, you can simply use <code>explorer.exe</code>. In regular Ubuntu, you would use something like <code>xdg-open</code> or simply <code>open</code>, but the environment is not fully configured on the default WSL installation. Instead, lets create an alias!</p>
<pre><code>    echo <span class="hljs-string">"alias ,open='explorer.exe'"</span> &gt;&gt; ~/.bash_aliases
    source ~/.bash_aliases
</code></pre><p>And test it by opening some file</p>
<pre><code>    echo <span class="hljs-string">"Contents"</span> &gt; file.txt
    ,open file
</code></pre><p>You should see your friendly neighborhood notepad pop up :P.</p>
<p><a target="_blank" href="https://stackoverflow.com/questions/52691835/wsl-ubuntu-how-to-open-localhost-in-browser-from-bash-terminal">source</a></p>
<h2 id="heading-disable-the-beep">Disable the beep</h2>
<p>That goddamn beep ( ` ω ´ ).</p>
<p>You can disable it <strong>from inside WSL</strong> by adding a <code>set bell-style none</code> in the <code>/etc/inputrc</code> file. (<a target="_blank" href="https://stackoverflow.com/a/36726662">source</a>)</p>
<p>Note that if you use vim, you will also have to add the following to your ~/.vimrc</p>
<pre><code>    set visualbell
    set t_vb=
</code></pre><p>You can also disable it <strong>from outside WSL</strong> (as a brute force solution) by openning the Volme Mixer in Windows and muting each WSL terminal window.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>These are the adjustments I've made to my WSL so far. If you have any additional tips or comments, please send them to my <a target="_blank" href="mailto:gui.garcia67@gmail.com">email address</a>. Thanks!</p>
<p>Tags: windows, wsl</p>
]]></content:encoded></item><item><title><![CDATA[House cleaning com git]]></title><description><![CDATA[Nesse post eu quero compartilhar com vocês algumas operações que eu tive que realizar em uns repositórios antigos, que estavam mal gerenciados e abandonados, pra que eu pudesse voltar a desenvolver neles.
As coisas que eu precisei aprender a fazer fo...]]></description><link>https://hashnode.guilhermegarcia.dev/house-cleaning-com-git</link><guid isPermaLink="true">https://hashnode.guilhermegarcia.dev/house-cleaning-com-git</guid><category><![CDATA[Git]]></category><category><![CDATA[pt-br]]></category><dc:creator><![CDATA[Guilherme Garcia]]></dc:creator><pubDate>Mon, 14 Nov 2022 12:28:25 GMT</pubDate><content:encoded><![CDATA[<p>Nesse post eu quero compartilhar com vocês algumas operações que eu tive que realizar em uns repositórios antigos, que estavam mal gerenciados e abandonados, pra que eu pudesse voltar a desenvolver neles.</p>
<p>As coisas que eu precisei aprender a fazer foram as seguintes:</p>
<ul>
<li>Listar autores de um repositório</li>
<li>Filtrar os commits do repositório por autor, pra ver o que cada um contribuiu</li>
<li>Relacionar combinações de autores/email diferentes de um mesmo usuário (usando o arquivo <code>.mailmap</code>)</li>
<li>Em um commit, ver quais arquivos foram alterados</li>
<li>Ver o que foi alterado em um arquivo específico dentro de um commit</li>
<li>Verificar o histórico de alteração de um arquivo no repositório (git log arquivo.js)</li>
<li>Alterar o nome e autor de alguns commits, utilizando o <a target="_blank" href="https://github.com/newren/git-filter-repo">git-filter-repo</a></li>
</ul>
<p>Essas tarefas são ótimas pra se familiarizar (ou relembrar) com o andamento de um projeto, ver o ritmo das alterações, quantas mudanças costumam ser embaladas num mesmo commit, e criar um feeling sobre o perfil dos desenvolvedores de um projeto.</p>
<p>Também servem pra organizar e arrumar o histórico e os meta dados dos commits passados, e por isso eu chamo de "House cleaning".</p>
<hr />

<h2 id="heading-listar-autores-de-um-repositorio">Listar autores de um repositório</h2>
<p>Vamos filtrar o <code>git log</code> em combinação com o comando <code>sort</code>, listando apenas as resultados não duplicados.</p>
<pre><code>    git log | grep Author: | sort -u
</code></pre><p>Você vai ter um resultado nesse formato:</p>
<pre><code>    Author: Guilherme Garcia &lt;guilherme67@gmail.com&gt;
    Author: Guilherme &lt;guilherme@empresa.com&gt;
    Author: guites &lt;<span class="hljs-number">6653499</span>+guites@users.noreply.github.com&gt;
    Author: guites &lt;guilherme67@gmail.com&gt;
    Author: gustavo &lt;gustavo@empresa.com&gt;
    Author: gustavo2112 &lt;gustavo2112@gmail.com&gt;
</code></pre><p>No github, nem todo autor representa uma conta separada. Isso porque a pessoa pode utilizar um <code>git config user.name</code> e <code>git config user.email</code> diferente em diferentes máquinas, conectadas a mesma conta do github.</p>
<p>Como o identificador, no github, é o email, sabemos que o <code>guites &lt;guilherme67@gmail.com&gt;</code> e <code>Guilherme Garcia &lt;guilherme67@gmail.com&gt;</code> são a mesma conta.</p>
<h2 id="heading-filtrar-os-commits-do-repositorio-por-autor">Filtrar os commits do repositório por autor</h2>
<p>Agora que temos os autores, podemos ver as contribuições de cada um usando</p>
<pre><code>    git log --author=nome_ou_email
</code></pre><p>Aqui você não precisa digitar o nome ou email completo, pois ele funciona como um filtro. Usando o exemplo anterior, as seguintes combinações funcionariam:</p>
<pre><code>    git log --author=gustavo #mostra resultados tanto de gustavo@empresa.com quanto gustavo2112@gmail.com
    git log --author=guites #mostra resultados tanto de guites quanto <span class="hljs-number">6653499</span>+guites@users.noreply.github.com
</code></pre><h2 id="heading-relacionar-combinacoes-de-autoresemail-diferentes-de-um-mesmo-usuario-usando-o-arquivo-mailmap">Relacionar combinações de autores/email diferentes de um mesmo usuário (usando o arquivo <code>.mailmap</code>)</h2>
<p>No exemplo acima, um mesmo usuário tinha configurações locais diferentes, o que pode acabar dificultando a filtragem dos seus commits.</p>
<p>Pra resolver isso, podemos criar um arquivo <code>.mailmap</code> na raíz do repositório (no mesmo diretório onde se encontra o diretório .git).</p>
<p>A estrutura básica do mail map é a seguinte:</p>
<pre><code>    Foo Name &lt;foo@email&gt; commit name &lt;commit@email&gt;
    \--------+---------<span class="hljs-regexp">/ \----------+-------------/</span>
             |                      |
          substituir por          buscar por
</code></pre><p>No nosso exemplo, digamos que os autores</p>
<ul>
<li>Author: Guilherme Garcia <a target="_blank" href="mailto:guilherme67@gmail.com">guilherme67@gmail.com</a></li>
<li>Author: Guilherme <a target="_blank" href="mailto:guilherme@empresa.com">guilherme@empresa.com</a>;</li>
<li>Author: guites <a target="_blank" href="mailto:6653499+guites@users.noreply.github.com">6653499+guites@users.noreply.github.com</a>;</li>
<li>Author: guites <a target="_blank" href="mailto:guilherme67@gmail.com">guilherme67@gmail.com</a>;</li>
</ul>
<p>Sejam a mesma pessoa, configurada em diferentes computadores com nomes e emails diferentes (por ex. usando tanto o email pessoal quanto o empresarial, e em uma outra máquina não configurou o email, daí ficou com um email auto associado do github).</p>
<p>Podemos preencher um <code>.mailmap</code> com as seguintes entradas</p>
<pre><code>   Guilherme Garcia &lt;guilherme67@gmail.com&gt; &lt;guilherme67@gmail.com&gt;
   Guilherme Garcia &lt;guilherme67@gmail.com&gt; &lt;guilherme@empresa.com&gt;
   Guilherme Garcia &lt;guilherme67@gmail.com&gt; &lt;6653499+guites@users.noreply.github.com&gt;
</code></pre><p>Agora, se rodarmos o filtro por autor uma segunda vez</p>
<pre><code>    git log | grep Author: | sort -u
</code></pre><p>Vamos ter a seguinte saída:</p>
<pre><code>    Author: Guilherme Garcia &lt;guilherme67@gmail.com&gt;
    Author: gustavo &lt;gustavo@empresa.com&gt;
    Author: gustavo2112 &lt;gustavo2112@gmail.com&gt;
</code></pre><h2 id="heading-em-um-commit-ver-quais-arquivos-foram-alterados">Em um commit, ver quais arquivos foram alterados</h2>
<p>Se você quiser saber o que foi feito num commit, pode utilizar o <code>git show</code> no formato abaixo</p>
<pre><code>    git show &lt;commit hash&gt;
</code></pre><p>Ele vai mostrar na tela um diff de tudo o que foi alterado naquele commit em relação ao anterior. Para commits grandes, pode ser uma boa ideia verificar quais arquivos foram alterados, ao invés de ver quais alterações foram feitas nos arquivos. Pra isso, podemos alterar o comando</p>
<pre><code>    git show &lt;commit hash&gt; --name-only
</code></pre><p>E vamos receber uma listagem com o nome dos arquivos alterados.</p>
<h2 id="heading-ver-o-que-foi-alterado-em-um-arquivo-especifico-dentro-do-commit">Ver o que foi alterado em um arquivo específico dentro do commit</h2>
<p>Depois de decidir qual arquivo você quer analisar dentro do commit selecionado, você pode ver apenas as alterações feitas nele, passando-o como argumento no <code>git show</code></p>
<pre><code>    git show &lt;commit hash&gt; -- caminho/ate/o/arquivo.extensao
</code></pre><h2 id="heading-verificar-o-historico-de-alteracao-de-um-arquivo-no-repositorio">Verificar o histórico de alteração de um arquivo no repositório</h2>
<p>Se você precisar do caminho contrário, ou seja, quiser saber qual a sequência de alterações pelas quais um arquivo específico passou, você pode usá-lo como argumento diretamente no <code>git log</code></p>
<pre><code>    git log caminho/ate/o/arquivo.extensao
</code></pre><p>E então pode ir usando <code>git show &lt;commit hash&gt; -- caminho/ate/o/arquivo.extensao</code> em cada commit da lista, pra ir acompanhando as alterações realizadas.</p>
<h2 id="heading-alterar-o-nome-e-autor-de-alguns-commits-utilizando-o-git-filter-repo">Alterar o nome e autor de alguns commits, utilizando o git-filter-repo</h2>
<p>Essa é uma forma mais radical de corrigir autores e emails trocados, que envolve reescrever o histórico do repositório.</p>
<p>Se você estiver trabalhando em conjunto nesse repositório, ou se as alterações que você fizer forem envolver commits que já foram enviados pro remote (com o <code>git push</code> por exemplo), essa opção pode dificultar a vida dos outros colaboradores.</p>
<p>O <a target="_blank" href="https://github.com/newren/git-filter-repo">git-filter-repo</a> é um conjunto de scripts escrito em python que permite alterar e reescrever meta dados de um repositório.</p>
<p>Você pode seguir as instruções de instalação no repositório acima, e utilizar o seguinte filtro pra, por exemplo, alterar todos os commits nos quais o autor é <code>guilherme@empresa.com</code> para <code>guilherme67@gmail.com</code>.</p>
<p>Repare que o git possui dois campos de autoria: o autor do commit (commit.author), e a pessoa que registrou o commit (commit.committer).</p>
<p>No caso abaixo, estou alterando ambos os campos.</p>
<p>A flag <code>--force</code> pode ser removida e, nesse caso, o <code>git filter-repo</code> só permite rodar o filtro em um repositório que não possua alterações locais (ou seja, recém clonado).</p>
<pre><code>    git filter-repo --force --commit-callback <span class="hljs-string">'
        if commit.author_email == b"guilherme@empresa.com":
            commit.author_email = b"guilherme67@gmail.com"
            commit.author_name = b"guites"
            commit.committer_email = b"guilherme67@gmail.com"
            commit.committer_name = b"guites"
    '</span>
</code></pre><h2 id="heading-consideracoes-finais">Considerações finais</h2>
<p>Espero que esses comandos te ajudem a navegar em novos repositórios, tentando se familiarizar com o código existente, ou a ajustar repositórios antigos bagunçados.</p>
<p>Abraço!</p>
<h2 id="heading-fontes">Fontes</h2>
<ul>
<li><a target="_blank" href="https://lukasmestan.com/using-mailmap-in-git-repository/">https://lukasmestan.com/using-mailmap-in-git-repository/</a></li>
<li><a target="_blank" href="https://stackoverflow.com/a/750182/14427854">https://stackoverflow.com/a/750182/14427854</a></li>
</ul>
<p>Tags: git</p>
]]></content:encoded></item></channel></rss>