<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Daniel Zanzini on Medium]]></title>
        <description><![CDATA[Stories by Daniel Zanzini on Medium]]></description>
        <link>https://medium.com/@danzanzini?source=rss-a4b7e23341d2------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*wI1S8_rddyPEG9A2-jxMFA.jpeg</url>
            <title>Stories by Daniel Zanzini on Medium</title>
            <link>https://medium.com/@danzanzini?source=rss-a4b7e23341d2------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 12:39:41 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@danzanzini/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Git Tricks: Avoid solving the same rebase conflict multiple times]]></title>
            <link>https://medium.com/goiabada/git-tricks-avoid-solving-the-same-rebase-conflict-multiple-times-9a3afbcf1d22?source=rss-a4b7e23341d2------2</link>
            <guid isPermaLink="false">https://medium.com/p/9a3afbcf1d22</guid>
            <category><![CDATA[conflict]]></category>
            <category><![CDATA[english]]></category>
            <category><![CDATA[rebase]]></category>
            <category><![CDATA[cherry-picking]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[Daniel Zanzini]]></dc:creator>
            <pubDate>Fri, 30 Apr 2021 15:48:28 GMT</pubDate>
            <atom:updated>2021-04-30T15:48:28.435Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*xqaCSCJqkwtFp7DNKHLyUA.gif" /></figure><p>Rebase is one of the main ways to integrate changes from one git branch to another. It consists of placing all commits of a source branch on top of the target branch. Its basic usage is simple:</p><pre>$ git checkout new-branch<br>$ git rebase main</pre><p>As complexity grows, branches will be created from other branches and, when rebasing onto an already rebased branch, <strong>you may be asked to solve the same conflicts you solved in the first rebase</strong>. To understand why this happens, it’s important to know that <strong>using rebase changes the hash of the affected commits</strong>. Because of this, git assumes it’s a different thing and doesn’t know that the conflict has already been solved in the past.</p><pre><strong>Before rebase</strong><br>*--a--b—--d -&gt; A<br>    \<strong>---c---e-----g</strong> -&gt; B<br>             \-f-----h---i -&gt; C</pre><pre><strong>After rebasing B onto A</strong><br>*--a--b—--d -&gt; A<br>    \      \---<strong>c&#39;---e&#39;-----g&#39;</strong> -&gt; B<br>     \---c--e--f---h---i -&gt; C</pre><pre><strong>After merging B onto A</strong><br>*--a--b—--d---<strong>c&#39;---e&#39;-----g&#39;</strong> -&gt; A<br>    \---c--e--f---h---i -&gt; C </pre><p>Note that all commits on Branch B changed to a commit&#39; version. It represents the same change, but with a different hash.</p><p>If when rebasing B to A you solve a conflict on c, when rebasing C to A, git will not recognize that c is already rebased and will try to put it on top of g&#39;, prompting you to solve the conflict again. In complex cases, with a lot of commits and conflicts, this could lead to a lot of extra work.</p><p>To solve this problem, we have two options.</p><h3>Using git rerere functionality</h3><p>“<a href="https://www.git-scm.com/book/en/v2/Git-Tools-Rerere">rerere</a>” stands for “reuse recorded resolution”. It’s a flag that, when active, tells git to record how you solve each conflict to reuse it in case you need to solve it again. Turning it on is super simple:</p><p>$ git config --global rerere.enabled true</p><p>And it’s done. From now on, every time you would be asked to solve a conflict you’ve already handled, you won’t. Git will identify the recorded conflict and solve it for you.</p><p>It’s important to note that git rerere will <strong>record only future conflicts</strong>, but if you landed here while searching for “solving the same conflict multiple times” you probably already have this situation going on. Which leads us into our second option:</p><h3>Using git cherry-pick</h3><p>This is not as simple as using rerere but it’s still simple. With <a href="https://git-scm.com/docs/git-cherry-pick">cherry-pick</a> we can select a range of commits to apply to a given branch. This way, we can make a “manual rebase”, selecting only the commits that were not rebased onto the first one.</p><p>In our example situation, we’ll need to select commits f, h and i from branch C and put them on top of branch A:</p><pre>$ git checkout A<br>$ git cherry-pick f^..i</pre><p>And it’s done.</p><p>Want to learn more about Git and other stuff related to development? Follow our blog <a href="https://goiabada.blog/">Goiabada</a> and enjoy a delicious mix of software development, design, and business.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9a3afbcf1d22" width="1" height="1" alt=""><hr><p><a href="https://medium.com/goiabada/git-tricks-avoid-solving-the-same-rebase-conflict-multiple-times-9a3afbcf1d22">Git Tricks: Avoid solving the same rebase conflict multiple times</a> was originally published in <a href="https://medium.com/goiabada">Goiabada</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Removendo o termo 'Master' de seu projeto no GitHub]]></title>
            <link>https://medium.com/goiabada/removendo-o-termo-master-de-seu-projeto-no-github-c753ea89718e?source=rss-a4b7e23341d2------2</link>
            <guid isPermaLink="false">https://medium.com/p/c753ea89718e</guid>
            <category><![CDATA[github]]></category>
            <category><![CDATA[branch]]></category>
            <category><![CDATA[racismo]]></category>
            <category><![CDATA[inclusão]]></category>
            <category><![CDATA[português]]></category>
            <dc:creator><![CDATA[Daniel Zanzini]]></dc:creator>
            <pubDate>Mon, 06 Jul 2020 20:38:25 GMT</pubDate>
            <atom:updated>2020-07-06T22:04:23.188Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7JFftkz9gkbjG1OO4DBQLg.jpeg" /></figure><h3>Removendo o termo Master de seu projeto no GitHub</h3><p>Devido à onda de protestos nos EUA e em todo mundo contra o racismo, muitas pessoas passaram a se perguntar onde e como ele se manifesta em suas vidas.</p><p>A resposta pra isso é simples: <strong>em todo lugar. </strong>E em nossos projetos digitais não seria diferente.</p><p>O Git, um dos sistemas de controle de versão mais populares do mundo, utiliza como padrão o termo master para identificar a versão principal do projeto. Este termo vem de uma metáfora extremamente opressiva: <em>Master-Slave</em>, que significa <em>Mestre-Escravo.</em></p><p>Existem diversas razões para abolir o uso dessa metáfora de nossos projetos digitais e, em 2018, a <a href="https://www.ietf.org/">Internet Engineering Task Force</a> (IETF) lançou <a href="https://tools.ietf.org/id/draft-knodel-terminology-00.html">um documento</a> que fala sobre os males de terminologias opressoras em projetos digitais, por que elas não devem ser utilizadas e sugere termos para substituir essas terminologias.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*ZRe7E80ad8AufmbrzSV9-A.jpeg" /></figure><p>Além disso, <a href="https://sempreupdate.com.br/github-troca-termo-master-para-evitar-referencias-a-escravidao/">muitas comunidades e empresas vêm abolindo o uso de termos racistas</a> como <em>Master, Slave, Blacklist e Whitelist</em> de seus projetos e os substituindo por termos não opressores e de igual entendimento: <em>Primary, Secondary, DenyList e AllowList.</em> 👏 🎉</p><p>Um pequeno gesto que está em nossas mãos é <strong>remover o termo master de nossos projetos no GitHub</strong>, dessa forma, além de demonstrar apoio, você influencia outras pessoas a seguirem o mesmo caminho.</p><h3><strong>Como fazer isso?</strong></h3><p>Embora a master seja a branch principal de seu projeto, renomeá-la não é complicado. Mas lembre-se: <strong>sincronize essa ação com colegas de trabalho</strong>. Esta branch é utilizada por todos as pessoas participantes do projeto e alterar seu nome sem um aviso prévio pode (e vai) causar problemas.</p><p>Avisou pra todo mundo? Todo mundo de acordo? Então vamos:</p><h4><strong>Escolha um novo nome</strong></h4><p>Existem várias opções possíveis: default<em>, </em>primary<em>, </em>trunk<em>, </em>etc<em>. </em>Eu gosto de main pois, <a href="https://www.hanselman.com/blog/EasilyRenameYourGitDefaultBranchFromMasterToMain.aspx">como citado por Scott Hanselman</a>, utilizando este nome você ainda tem a vantagem de que este termo também começa com ma, então a memória muscular de digitar ma e apertar Tab para auto-completar ainda funciona.</p><h4><strong>Crie uma nova branch</strong></h4><p>Faça isso a partir da master e, depois, faça o push para o repositório:</p><pre>$ git branch --move master main<br>$ git push -u origin main</pre><h4><strong>Modifique a branch padrão no GitHub</strong></h4><p>Fazendo isso, a tela inicial do repositório, todos os novos <em>Pull Requests </em>e qualquer outra ação que aponte para uma branch, serão apontados para a main<em>, </em>a não ser que você especifique o contrário. Para fazer isso, vá até seu repositório no GitHub, em <em>Settings → Branches</em>. Na opção <em>Default branch</em> escolha main e aperte <em>Update.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*hl62iMsFr87oa-wr.png" /></figure><h4><strong>Faça a modificação em serviços que dependem do nome da branch</strong></h4><p>Se você utiliza alguma regra ou action no GitHub, algum serviço de CI/CD, pipelines ou qualquer outro que dependa do nome da branch para funcionar, você deve modificar a branch para a qual o serviço aponta. Não é provável, mas fique de olho em qualquer problema que possa aparecer após a mudança.</p><h4><strong>Peça a todos para sincronizar</strong></h4><p>Todas as pessoas trabalhando no repositório terão que aplicar as modificações em sua cópia local. Para criar uma nova branch referenciando a nova main basta rodar $ git branch -u origin/main.</p><h4><strong>Apague a branch master</strong></h4><p>Se estiver trabalhando com várias pessoas, não tenha pressa para fazer isso. Sincronize com todo mundo e quando estiver pronto para apagar a master, utilize $ git branch -D master se quiser apagá-la apenas localmente. Para apagar a branch remota, você pode fazer pela interface do GitHub ou utilizar $ git push origin --delete master.</p><p>E é isso, a partir de agora seu repositório <strong>possui uma <em>branch</em> principal que não faz referência e nem normaliza a estrutura social de um período sombrio de nossa história</strong>.</p><h3><strong>Não pare por aí</strong></h3><p>Há muito mais a ser feito e isto não é algo que tenha fim. Estamos inseridos em uma sociedade opressora e, mesmo sem perceber, utilizamos termos e expressões que normalizam e reforçam essa condição.</p><p>É necessário prestar atenção constante nos termos utilizados em nossos projetos. No documento proposto pela IETF, há um <a href="https://tools.ietf.org/id/draft-knodel-terminology-00.html#rfc.section.2">sumário de recomendações</a> que ajudam a não utilizar termos opressores, entre elas:</p><ul><li>Reflita antes de usar metáforas;</li><li>Use gênero neutro;</li><li>Leve isso em consideração em processos de revisão.</li></ul><p>E é assim, através de pequenas ações, que podemos fazer nossa parte na construção de um mundo (real e digital) <strong>melhor e mais inclusivo para todas as pessoas</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uIVu7SKyn587rKAbN-zzPg.jpeg" /></figure><h4><strong>Não são somente palavras</strong></h4><p>Ao refletir sobre os termos usados em nossos projetos, aprendemos sobre a origem dessas expressões e os impactos que elas causam nas pessoas e na sociedade. Apenas parar de usá-las não é suficiente: <strong>devemos agir de maneira a não propagar essas opressões</strong>.</p><p>Para nos ajudar a trilhar esse caminho, estamos usando o <a href="https://medium.com/renataarruda/por-que-ler-o-pequeno-manual-antirracista-de-djamila-ribeiro-8a7969595d7e">Pequeno Manual Antirracista</a>, de <a href="https://www.instagram.com/djamilaribeiro1">Djamila Ribeiro</a>, como tema de debate para o nosso próximo clube de leitura aqui na Guava. Leia você também!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c753ea89718e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/goiabada/removendo-o-termo-master-de-seu-projeto-no-github-c753ea89718e">Removendo o termo &#39;Master&#39; de seu projeto no GitHub</a> was originally published in <a href="https://medium.com/goiabada">Goiabada</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Spec-Driven Development to build consistent APIs]]></title>
            <link>https://medium.com/goiabada/using-spec-driven-development-to-build-consistent-apis-e391daafae71?source=rss-a4b7e23341d2------2</link>
            <guid isPermaLink="false">https://medium.com/p/e391daafae71</guid>
            <category><![CDATA[english]]></category>
            <category><![CDATA[testing]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Daniel Zanzini]]></dc:creator>
            <pubDate>Thu, 30 Jan 2020 15:58:16 GMT</pubDate>
            <atom:updated>2020-01-30T15:58:16.979Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GLl-aIZek9OQg6WOS3DNlA.gif" /></figure><p>Spec-Driven Development is a software development process that uses the API specification as a guide to implementation. Inputs and outputs are turned into test cases to ensure that the API does everything it promises.</p><p>There is just one requirement to use this approach:<strong> Write the API documentation first. </strong>The most we can do beforehand the better, but we&#39;re not going <a href="https://en.wikipedia.org/wiki/Waterfall_model">Waterfall</a> here. We can also use the benefits of agile methodologies to increment the documentation in cycles, as we do when coding.</p><p>Writing documentation first has some benefits:</p><ol><li><strong>Parallelize the development process. </strong>With the documentation in hands, both server and client can develop simultaneously. Mocking the API can improve this benefit.</li><li><strong>Improves understanding of the whole. </strong>When writing the docs, you&#39;ll face edge cases, find inconsistencies and notice design problems. This will make the development process a lot easier and decrease the amount of rework.</li><li><strong>Guide Development.</strong> Using the documentation as base for spec-driven development ensures that the API does exactly what it promises and, by delivering a great test coverage, decreases the amount of escaped bugs.</li></ol><h3>How to use Spec-Driven Development</h3><p>With our documentation in hand we can start the development process. It’s very similar to <a href="https://www.agilealliance.org/glossary/bdd/">BDD</a>, with the difference that we rely on our API docs instead of user stories:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gc56YZq8hX6PUi_fviXaxw.jpeg" /></figure><ol><li>Choose a resource to develop;</li><li>Based on the specification, create automated tests to ensure the behaviour of the resource;</li><li>Code until the test passes;</li><li>Refactor until you&#39;re happy :)</li><li>Repeat!</li></ol><h4>Showing by example</h4><p>Now that you already know what to do, I&#39;ll show how I&#39;d do to create automated tests based on the documentation of a given resource. To do this, I&#39;ll use the <a href="https://swagger.io/docs/specification/about/">OpenApi</a> format to define the specification and <a href="https://rspec.info/">RSpec</a> to implement the tests.</p><p>Suppose we have an application that stores information about artworks and a new feature is required: transfer the ownership of a given artwork. The first thing we need to do to use Spec-Driven Development is to write the documentation of this feature.</p><p>After some discussion and review process we ended up with this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e8f320828d9bc06c4247505e2bb7fb10/href">https://medium.com/media/e8f320828d9bc06c4247505e2bb7fb10/href</a></iframe><p>A simple PUT endpoint. Let&#39;s walk through each point of interest.</p><ul><li>parameters: just one, named id, that represents the ID of the artwork;</li><li>requestBody: one integer representing the ID of the new owner;</li><li>Three response cases: 200, 404 and 422.</li></ul><p>These elements are important to build our expectations and create a good test coverage. I&#39;ll show you.</p><p>First of all, let&#39;s describe our endpoint:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3b4d5a1946b47f78478298c2a113b6e4/href">https://medium.com/media/3b4d5a1946b47f78478298c2a113b6e4/href</a></iframe><p>Here we&#39;ve described our endpoint and defined two arguments that will change according to our context: the action (or path) and the params that will be used. We&#39;ve also declared what will be done before each expectation: a put method to our action, using the defined params.</p><p>To ensure our API implements every response case, let&#39;s define one context for each one:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/78d3ce99205f3d3447670f9dbc617637/href">https://medium.com/media/78d3ce99205f3d3447670f9dbc617637/href</a></iframe><p>As said, each context represents one of the response cases and defines the necessary conditions for them to happen. Doing this ensure that every single response case of our API is covered by our specs.</p><p>Finally, we define the expectations for each context:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3629afc5173fd9cb3ca65dcc950ca7f7/href">https://medium.com/media/3629afc5173fd9cb3ca65dcc950ca7f7/href</a></iframe><p>Each context has one or more expectations. When the artwork is transferred we just need to ensure that the response is a 204 status. In the other two contexts, we also check if the error message is correct.</p><p>Now, our tests are ready and we can start our development process. I&#39;ll not cover it here, but remember: <strong>if during the development process you notice that something is wrong with some resource, go back to the documentation and change it first</strong>.</p><p>At the end of the development process you may not have a perfect API, but will have one with a <strong>great test coverage</strong> and that <strong>delivers exactly what it promises</strong>. That&#39;s what an API is about, right?</p><p>Want to learn more about development process and other related stuff? Follow our <a href="https://goiabada.blog/">Goiabada Blog</a> and enjoy a delicious mix of software development, design, and business.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e391daafae71" width="1" height="1" alt=""><hr><p><a href="https://medium.com/goiabada/using-spec-driven-development-to-build-consistent-apis-e391daafae71">Using Spec-Driven Development to build consistent APIs</a> was originally published in <a href="https://medium.com/goiabada">Goiabada</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[GIT Tricks: Avoiding merge when dealing with remote conflicts]]></title>
            <link>https://medium.com/goiabada/git-tricks-avoiding-merge-when-dealing-with-remote-conflicts-52c175e526e6?source=rss-a4b7e23341d2------2</link>
            <guid isPermaLink="false">https://medium.com/p/52c175e526e6</guid>
            <category><![CDATA[development]]></category>
            <category><![CDATA[english]]></category>
            <category><![CDATA[version-control]]></category>
            <category><![CDATA[git]]></category>
            <category><![CDATA[gitflow]]></category>
            <dc:creator><![CDATA[Daniel Zanzini]]></dc:creator>
            <pubDate>Mon, 21 Oct 2019 19:29:44 GMT</pubDate>
            <atom:updated>2019-10-22T00:09:05.021Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*spoNUEph2xW404ENKpcQEQ.gif" /></figure><h3>Git Tricks: Avoiding merge when dealing with remote conflicts</h3><p>TL;DR: git pull --rebase</p><p>The scenario is common: You finish the changes on a codebase, all commits are ready to be pushed. You run git push and an unexpected message appears: &quot;! [rejected]&quot;. The reason: &quot;Updates were rejected because the tip of your current branch is behind its remote counterpart. Integrate the remote changes (e.g. hint: ‘git pull …’) before pushing again.&quot;.</p><p>You follow the message and run git pull. Instead of pulling all changes to your local machine you are asked to confirm a merge commit message…</p><h4>First of all… Why this is happening?</h4><p>This happens because, after you&#39;ve pulled, someone pushed changes to the same branch you&#39;re working on:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MtjWqw4F8Ziyp0Qs6a5W2Q.jpeg" /><figcaption>Your local work conflicts with the commits added to remote-branch</figcaption></figure><p>By confirming the merge commit, all the work on the remote branch will be merged on your local work. After this, you will be able to push your changes, making your-local-work coincide with the tip of remote-branch:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WntNylT2h8R5ylIID0Mz_w.jpeg" /><figcaption>With a merge commit, your local work is now the more up-to-date tip of the branch</figcaption></figure><h4>Is there an alternative to merge commit?</h4><p>Yes, there is. To avoid the merge commit you need to rewrite your local history.</p><p>To do this, instead of just pulling the remote changes, you need to rebase them: git pull --rebase. By doing this, all of the commits from your local branch will be placed after the ones in the remote branch:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MRE0aUpQrl5QAnCZCAq7FQ.jpeg" /><figcaption>All of your local work is placed after all the remote changes</figcaption></figure><p>After this, you just need to push your changes. Your local work will become the tip of the remote branch.</p><p>The advantages of this approach is that you don&#39;t need a merge commit and a fork on the branch history will not be created. Also, notice that nothing on remote was rewritten, so you&#39;ll not need to use--force to push your changes.</p><p>Want to learn more about Git and other stuff related to development? Follow our <a href="https://goiabada.blog/">Goiabada Blog</a> and enjoy a delicious mix of software development, design, and business.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=52c175e526e6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/goiabada/git-tricks-avoiding-merge-when-dealing-with-remote-conflicts-52c175e526e6">GIT Tricks: Avoiding merge when dealing with remote conflicts</a> was originally published in <a href="https://medium.com/goiabada">Goiabada</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[One DateTime, two inputs… Doing it in Rails.]]></title>
            <link>https://medium.com/goiabada/one-datetime-two-inputs-doing-it-in-rails-c538f628ec9e?source=rss-a4b7e23341d2------2</link>
            <guid isPermaLink="false">https://medium.com/p/c538f628ec9e</guid>
            <category><![CDATA[english]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[datetime]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Daniel Zanzini]]></dc:creator>
            <pubDate>Mon, 20 May 2019 16:15:42 GMT</pubDate>
            <atom:updated>2019-05-20T16:15:42.913Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pIJC4dy68ZVWGDiOSHiPxQ.png" /></figure><h3>One DateTime, two inputs… Doing it in Rails</h3><p>Let&#39;s assume you have an Appointment model and want to store the date and time it is scheduled. Since you need both date and time values the obvious choice is to go with a single datetime attribute named starts_at.</p><p>Now, you need to display it in a way the user can enter this value. Rails has a built-in datetime_select helper. It splits the datetime attribute into five smaller parts: year, month, day, hour and minute and creates one picker for each of these parts.</p><p>This would be enough if we wanted our users to select five different inputs, but our application design is different, it requires only two inputs: one for date and another one for time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_VJy2lwbviKdEDA1IP75_g.png" /><figcaption>Our date and time inputs</figcaption></figure><p>This design prevented us of using Rails&#39; built in solution, so we decided to create two virtual attributes to represent both date and time. Let&#39;s dive into this solution.</p><p>First of all, let&#39;s check our view with these two inputs. I&#39;ll skip the date picker part for clarity purposes.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e91852b8117304e4fa2ac0bc19785200/href">https://medium.com/media/e91852b8117304e4fa2ac0bc19785200/href</a></iframe><p>In the snippet above there are two attributes which we’ll need to define: starts_at_time and starts_at_date. We&#39;ll do so in the Appointment model by creating a getter and a setter for each:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/678a14c772dc30136437476ebed3c9e9/href">https://medium.com/media/678a14c772dc30136437476ebed3c9e9/href</a></iframe><p>If we load our view now it should render correctly 🎉. But if you try to create the appointment using the view above you&#39;ll see that the values chosen for starts_at_date and starts_at_time are not being stored in starts_at. This happens because we still need to map the persistentstarts_at to the values stored into the two virtual attributes. The most common way of doing this is defining a before_save callback:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5c116b5fc10e7f85666d58244a2cfafa/href">https://medium.com/media/5c116b5fc10e7f85666d58244a2cfafa/href</a></iframe><p>Now we&#39;ve done it. Our inputs are working and we&#39;re saving the correct value to our starts_at attribute. We could stop right here, but I don&#39;t like this approach very much for a couple os reasons. Firstly, it can create problems with validations. In addition to that, we could see some unexpected behavior on other parts of the system due to the callback. Lastly, the starts_at attribute won&#39;t be set/overwritten until we actually save the appointment.</p><p>For this reason I&#39;ve decided to go with a more straightforward solution that updates the value into starts_at whenever we set one of the values of starts_at_date or starts_at_time:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/75306682723405ba7966c010a402265a/href">https://medium.com/media/75306682723405ba7966c010a402265a/href</a></iframe><p>And that&#39;s it 🎉. A simple and easy solution when dealing with datetime fields with multiple inputs.</p><p>In our full solution we used these virtual attributes in a React component using the <a href="https://github.com/reactjs/react-rails">react-rails gem</a>. In future posts I&#39;ll explain why and how we did it, so make sure to follow Guava&#39;s blog <a href="https://goiabada.blog/">Goiabada</a> and keep track of all our posts :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c538f628ec9e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/goiabada/one-datetime-two-inputs-doing-it-in-rails-c538f628ec9e">One DateTime, two inputs… Doing it in Rails.</a> was originally published in <a href="https://medium.com/goiabada">Goiabada</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Code Quality Challenge — A diary — Part 2]]></title>
            <link>https://medium.com/goiabada/code-quality-challenge-a-diary-part-2-37f69ada821?source=rss-a4b7e23341d2------2</link>
            <guid isPermaLink="false">https://medium.com/p/37f69ada821</guid>
            <category><![CDATA[english]]></category>
            <category><![CDATA[code-quality]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[challenge]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Daniel Zanzini]]></dc:creator>
            <pubDate>Tue, 20 Mar 2018 16:27:13 GMT</pubDate>
            <atom:updated>2018-03-20T16:27:13.249Z</atom:updated>
            <content:encoded><![CDATA[<h3>Code Quality Challenge — A diary — Part 2</h3><p><em>This is the second part of a two-part series. You should read the </em><a href="https://goiabada.blog/code-quality-challenge-a-diary-eda590092820"><em>first part</em></a><em> first.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zmmFkOcVGuNsHvIqD3Nnvw.jpeg" /></figure><h4>Before we restart</h4><p>The <a href="https://www.codequalitychallenge.com/">30-day code quality challenge</a> is language-agnostic, but the project I’m working on is based on the Ruby on Rails framework. All code snippets used in here were gotten from this project. That said, let’s start.</p><h4>Day 12 — Investigate your slowest test(s)</h4><p>I already knew which tests I should look for. They were visibly slower than the rest. I ran rspec spec/ --profile to check how much slower they were:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*04D7kUHps9xI1jQeAaPf8A.png" /><figcaption>My slowest examples</figcaption></figure><p>I got 4 examples taking more than 3 seconds to run. All of them were inside a single context. Let’s take a look at them:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f3802fd7db02fe4813c80af262463196/href">https://medium.com/media/f3802fd7db02fe4813c80af262463196/href</a></iframe><p>I didn’t need to look much to find out the problem was that the setup was creating a lot of forms for each expectation. I took a look at them and noticed that I could create all these forms only once for the entire context.</p><p>I changed this before to abefore(:context) and added DatabaseCleaner to clean my database after the context. Here what my context looked like after the changes:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/630db566389b17ebfa5fc3878c8affd2/href">https://medium.com/media/630db566389b17ebfa5fc3878c8affd2/href</a></iframe><p>I ran it with --profile again and had a nice improvement on the speed, decreasing the time of the lowest spec from 4.23 seconds to 1.45 seconds, almost 3 times faster. 🚅 🚅</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8mbDCvLBboQXyCc1YpclEw.png" /><figcaption>My improved specs</figcaption></figure><h4>Day 15 — Improve one name</h4><p>One of the reasons to change the name of something is: <em>Is the name your customers would use the same as what’s in the code?</em></p><p>For this question I had one attribute that used a different name on my code and another one on the client. I avoided changing this name because it’s used in 7 different models. Changing the name would make me change controllers, representers, specs, validators, etc…</p><p>But the time to change this name had come. I relied on my tests to make sure everything kept working and used find and replace to change the name across all the files I needed to change: 46 files.</p><p>Besides this great number of files, this task took me less than 20 minutes. Totally worth it. :)</p><h4>Day 16 — Audit your dependencies</h4><p>To complete this task I took a look at my Gemfile and made sure that I was using everything in there.</p><p>After this, I installed <a href="https://github.com/rubysec/bundler-audit">bundler-audit</a> and ran bundle audit check --update to check if any gems have any security vulnerability. I got this as a result:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*p2Qd8fPwn1vBnSBQ-GCWrg.png" /><figcaption>Vulnerabilities found!</figcaption></figure><p>To fix this I just ran bundle update nokogiri and no more vulnerabilities were found.</p><p>Since I didn’t use nokogiri on this project I checked the Gemfile.lock to find out what gem used it as a dependency and created an issue there to check if they want the dependencies to be updated.</p><h4>Day 17 — Tidy your open PRs/issues</h4><p>As I do with branches, I always try to keep my PRs updated. Unfortunately, I admit this is not true for Trello cards. 😅 I have the bad habit of forgetting about them. But, this time, I had all of them updated. 🎉</p><p>So, I used the opportunity to poke my coworkers on their trello cards to check if they’re all updated. :)</p><h4>Day 18 — Investigate long parameters list</h4><p>I checked my code for methods that receive more than three parameters and found nothing. I just found one method that has three and most of them received one or no arguments.</p><p>I confess that I didn’t make this on purpose but I’m glad I did. Points to me. 👏 👏</p><p>Oh, Ben also sent <a href="https://robots.thoughtbot.com/types-of-coupling#control-coupling">an article explaining the types of coupling</a>. It’s a good one and totally worth the time to read it. For this task, the <strong><em>Control coupling</em></strong> part deserves special attention.</p><h4>Day 19 — Automate repetitive actions</h4><p>On the last project I worked all the development took place inside containers. I used some aliases to start the environment since it always used two or more commands.</p><p>The current one is pretty simple so I don’t have any script or alias for it. I could create some for Git but I’m not a huge fan of creating aliases just to replace one command, although I know the benefits of it.</p><p>I’m sure when this project gets more complex I’ll have something to automate. For now, I liked one special thing that Ben told us this day and I’d like to share with you:</p><blockquote>I think you’ll find this one quite satisfying. When I automate an annoying task, I get a little burst of dopamine each time I use my new, improved method to accomplish it. One-time effort; continuous payoff.</blockquote><h4>Day 23 — RTFM</h4><p>Or, if you prefer, “Read The frickin’ Manual”.</p><p>During a long time of my experience in development, I skipped the step of reading the manual and jumped right to Stack Overflow questions. Doing this seems ok, but it’s not.</p><p>Using the manual instead of Stack Overflow is better because you have an overview of all features of the library and can learn different ways of doing the same thing.</p><p>For this project I’m using two new libraries and I have their manuals constantly open: <a href="http://dry-rb.org/gems/dry-validation/">dry_validation</a> and <a href="http://trailblazer.to/gems/representable/3.0/function-api.html">Representable</a>.</p><p>But, this task proposes something more uncommon: to read the documentation to check for unused features or anything that can improve what you already know. I confess that this is something that I almost never do.</p><p>Since I’m already trying to learn these two new libraries I’ll use Ben’s advice to get used to new commands:</p><blockquote>Jot it down on a sheet of paper next to your keyboard so you remember to try it later. I do this often to teach myself new Vim commands. Once the new stuff is in my muscle memory, I throw the sheet away.</blockquote><h4>Day 24 — Done</h4><p>And this is it. Day 23 was the last day of the <a href="https://www.codequalitychallenge.com/">Code Quality Challenge</a>. I’d like to thank Ben for taking time to make this happen and all other participants who posted on the forum during the challenge. I’ve learned a lot with you during all these days.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*m_3gDsQnA8lw0OjSkF-kIg.gif" /></figure><h4>Next steps?</h4><p>Yes, of course. :)</p><p>I’ll get some of these daily tasks and schedule them to make it time after time. I think that doing them frequently will keep my code better, cleaner and more efficient.</p><h4>What about you?</h4><p>Do you have any task you do from time to time to increase the quality of your code? Share it with us, it will be nice to add it to my schedule.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=37f69ada821" width="1" height="1" alt=""><hr><p><a href="https://medium.com/goiabada/code-quality-challenge-a-diary-part-2-37f69ada821">Code Quality Challenge — A diary — Part 2</a> was originally published in <a href="https://medium.com/goiabada">Goiabada</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Code Quality Challenge — A diary]]></title>
            <link>https://medium.com/goiabada/code-quality-challenge-a-diary-eda590092820?source=rss-a4b7e23341d2------2</link>
            <guid isPermaLink="false">https://medium.com/p/eda590092820</guid>
            <category><![CDATA[challenge]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[english]]></category>
            <category><![CDATA[code-quality]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Daniel Zanzini]]></dc:creator>
            <pubDate>Mon, 19 Feb 2018 17:31:22 GMT</pubDate>
            <atom:updated>2018-04-12T20:57:01.073Z</atom:updated>
            <content:encoded><![CDATA[<h3>Code Quality Challenge — A diary</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xTC7Fl7riRRKnMX7WdTXzw.jpeg" /></figure><p>I&#39;ve always tried, without success, to finish these X days challenges in doing something: 30 days writing challenge, 365 days photo challenge, 100 days JS programming challenges… And the list goes on. I don&#39;t have an exact reason for not ending, or even not starting, these challenges. I simply didn&#39;t.</p><p>But, a month ago, I started the <a href="https://www.codequalitychallenge.com/">30-day code quality challenge</a>, proposed by <a href="https://twitter.com/r00k">Ben Orenstein</a>. This time, I finished it and want to share my experience with you.</p><h4>Before we start</h4><p>The <a href="https://www.codequalitychallenge.com/">30-day code quality challenge</a> is language-agnostic, but the project I&#39;m working on is based on the Ruby on Rails framework. All code snippets used in here were gotten from this project.</p><p>That said, let&#39;s start.</p><h4>Day 1 — Clean up your README</h4><p>This was simple, but I had never written a README before. I&#39;ve been working on the same project for four months and the README was blank… Until the day I accepted this challenge. In 20 minutes I had a simple but useful README that explains what the project is about and how to start the development for it.</p><h4>Day 2 — Nuke TODO comments</h4><p>I had luck with this one. I ran a search for TODO in my codebase and found only this one:</p><pre>def handle_requisition_error(response)<br>  # TODO: Do something here<br>  context.fail!<br>end</pre><p>Two days before this exercise, we had merged a commit that added Rollbar to our project so, instead of adding the TODO to an issue tracker, I decided to finish it.</p><p>It was fast and straightforward. It took half an hour and when I searched for TODO again, nothing appeared. Nice.</p><h4>Day 3 — Get rid of a warning</h4><p>I thought I would have nothing to do this day. I ran rails console,rails server, and rspec spec/ and no warnings. So I talked to one of my coworkers about it and he reminded me that bundle can output some warnings. I ran the command and got a nice warning telling me that I was using an old version of Bundler:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JV4CYBSk6Lz1lg5ZsKSRHQ.png" /><figcaption>The nice warning with a (fragment of the) rebel symbol behind it :)</figcaption></figure><p>I don&#39;t know why I didn&#39;t update it before. Actually, I never read it, at all. I think I got used to ignoring warnings after working on a project that was full of them.</p><p>I just ran the command suggested by the warning itself and it was solved. It took me less than a minute of work.</p><h4>Day 4 — Excise some unused code</h4><p>The project I&#39;m working on is a small one, created and maintained by myself. I always tried to check and remove all unused methods when refactoring things.</p><p>But, in the e-mail, Ben recommended the <a href="https://unused.codes/">unused tool</a> to check if you have code that is not being used. I decided to install it and give it a try. As a result, I got a green message saying: &quot;Unused found no results&quot; 🎉.</p><p>To check if the tool was really working, I ran it in an old project that I was sure there was unused code and I got a very big list. So, even if I didn&#39;t code anything in this day, I learned about a very useful tool to run in my next projects from time to time.</p><h4>Day 5 — Trim those branches</h4><p>The last project I worked on was a big one with a huge codebase. There I learned that keeping your codebase clean is very important to keep your sanity.</p><p>Therefore, since the beginning of this new project, I kept cleaning the merged branches so, when I ran git branch -r I just got branches that we&#39;re currently working on.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T8xupUdIQ-1QnEbIA4jDsQ.png" /><figcaption>The result of git branch -r. Only 3 branches returned.</figcaption></figure><h4>Day 8— Extract a compound conditional</h4><p>Compound conditionals are statements composed of two or more conditionals. To find them I scanned my project for &amp;&amp; and || and got one occurrence that was used in three distinct controllers:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4088c5f218b04fce386ab906095d602e/href">https://medium.com/media/4088c5f218b04fce386ab906095d602e/href</a></iframe><p>It was a compound conditional made of two conditionals. The idea was to check if we should render the form_from_another_user_error. I created a protected method inside ApplicationControllercalled should_render_form_from_another_user_error? and placed the logic inside it:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/aef62236d2012ffbc7a690c361a3bb31/href">https://medium.com/media/aef62236d2012ffbc7a690c361a3bb31/href</a></iframe><p>Still not enough. The reason why I should render the error is not clear. To make this right I needed one more change: extract each conditional to its own method.</p><p>The first one is checking if the form doesn&#39;t belong to the current user so a method called form_from_another_user?(form) should solve it. The second one checks if the action is not a transfer so I decided to call it not_a_transfer_action?:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2fd942dbcf22f270da1aa299960597c2/href">https://medium.com/media/2fd942dbcf22f270da1aa299960597c2/href</a></iframe><p>Now, instead of having a compound conditional inside my controller I have one method with an explicit name composed by two methods with good names. No one will ever need to guess what this piece of code does. 💥</p><h4>Day 9— Slim down an overgrown class</h4><p>First of all, I needed to check what classes of my project were the longest ones. So I ran the command given on the task to check it: find ~/code/my_project -name &quot;*.rb&quot; | xargs wc -l | sort -rn | head and got this list in response:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_rTxw1XGEfwCyLQbKLCpUQ.png" /><figcaption>The list of my longest files</figcaption></figure><p>The command returned only specs and I don&#39;t know if having big specs files is a problem. Is it?</p><p>As a fallback task I needed to improve something about a class of my project. I went through my project searching for some class that I could refactor and found one folder named services containing only one class named third_party.rb.</p><p>The purpose of this class was not clear by its name or folder. This class is responsible to handle API connections with this third party software by including <a href="https://github.com/jnunemaker/httparty">HTTParty</a>.</p><p>I improved this code by creating a new folder called apis, moving the ThirdParty class to this new folder and renaming it to ThirdPartyApi. By doing it I made the purpose of this class clearer than before.</p><h4>Day 10— Create a bin/setup script</h4><p>This day&#39;s task was to create a script to setup my app for development use. I picked Ben&#39;s example, opened the bin folder and… found out that Rails generates a setup script.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d213af02e332d96644067af0ab5094e0/href">https://medium.com/media/d213af02e332d96644067af0ab5094e0/href</a></iframe><p>So, all I needed to do is to update my README.md to include how to use the script.</p><h4>Day 11— Run your tests with your wifi off</h4><p>No problems here. My tests ran fine without connection. The system uses a third-party API but it&#39;s already mocked in specs. I&#39;ll show you how I did it. First of all, let&#39;s take a look at the controller:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/52f4b074a51d2f8de8f8b54bf0740a3e/href">https://medium.com/media/52f4b074a51d2f8de8f8b54bf0740a3e/href</a></iframe><p>To perform this create action I need to connect to a third-party API. I put all the interaction with this API inside an interactor called PerformLogin. It gets the response from the API and I handle it on the controller based on the interactor response.</p><p>So, on my specs, all I needed to do is to mock the response from PerformLogin and all the interactions with the third-party API will not happen anymore:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/035627baa03a84dd1a0b0050d8101b3b/href">https://medium.com/media/035627baa03a84dd1a0b0050d8101b3b/href</a></iframe><h4>Is this the end?</h4><p>No! For now, we&#39;re half of the way through these daily challenges.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*_ykrg5LqlT49qMRecIpUxA.gif" /></figure><p>Now continue on to <a href="https://goiabada.blog/code-quality-challenge-a-diary-part-2-37f69ada821">Code Quality Challenge — A diary — Part 2</a>!</p><h4>Have any doubts?</h4><p>Have any questions about the code quality challenge? Want to know more about any of these daily tasks? Have anything to share about code quality? Talk to us :)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=eda590092820" width="1" height="1" alt=""><hr><p><a href="https://medium.com/goiabada/code-quality-challenge-a-diary-eda590092820">Code Quality Challenge — A diary</a> was originally published in <a href="https://medium.com/goiabada">Goiabada</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Git Tricks: Keeping branches even]]></title>
            <link>https://medium.com/goiabada/git-tricks-keeping-branches-even-7ddc8647d1f3?source=rss-a4b7e23341d2------2</link>
            <guid isPermaLink="false">https://medium.com/p/7ddc8647d1f3</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[gitflow]]></category>
            <category><![CDATA[english]]></category>
            <category><![CDATA[version-control]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[Daniel Zanzini]]></dc:creator>
            <pubDate>Mon, 21 Aug 2017 17:05:01 GMT</pubDate>
            <atom:updated>2017-08-21T19:33:49.670Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jEPcNA4z3P4h9CWT2-x9lA.png" /></figure><p>In one of our projects, we use git with 3 main branches: master, staging and production.</p><p>master has all the code that has already been reviewed and approved, staging has the code on our staging machine and production has what is currently running for the client. They all follow the same timeline: from master to staging, then to production, so we have something like this:</p><pre>---------o---o---o-&gt;<br>         P   S   M</pre><p>Then when we need to merge master into staging or staging into production we simply need to go to the target branch and merge it with the branch that is ahead of it:</p><pre>$ git checkout production<br>$ git merge staging</pre><p>Using this approach, no merge commit will be created, because this merge is <a href="https://ariya.io/2013/09/fast-forward-git-merge">Fast Forward</a> (FF). The commits from the ahead branch are just put after the last commit of the target branch. After that, we should have:</p><pre>-------------o---o-&gt;<br>            P,S  M</pre><p>But yesterday, one thing happened: staging diverged from master.<br>One of my coworkers merged a PR on master, that was not synced with remote, merged it to staging and pushed it. So we ended up with something like this:</p><pre>--a-----b---d--&gt; master<br>   \------c----&gt; staging</pre><p>We just noticed it afterwards, when we tried to merge master into staging again and received a prompt to edit the message of the merge commit. An easy fix for it would be to just merge it, but if we did that, all our merges would stop being FF and would generate merge commits, something we don’t want.</p><p>Two options were available to solve this problem. I&#39;ll walk through both of them now.</p><h3>Using reset and force push</h3><p>This approach keeps history clean by rewriting it but you&#39;ll need to push to remote using the <a href="https://git-scm.com/docs/git-push#git-push---force">force</a> option. This can cause some problems when working with other people. Be careful when using this approach.</p><p>First of all, <a href="https://git-scm.com/docs/git-cherry-pick">cherry-pick</a> the diverged commit from staging to master:</p><pre>$ git checkout master <br>$ git cherry-pick &lt;commit-C-from-staging-branch&gt;<br>$ git push origin master</pre><p>Which leads us to:</p><pre>--a-----b---d--c*-&gt; master<br>   \------c-------&gt; staging</pre><p>Notice that a new commit was created on master. This happened because cherry-pick creates a new commit with the same changes as the selected one.</p><p>Now we need to return staging to the point where it diverged. We can use reset here to remove the last commit from staging&#39;s history.</p><pre>$ git checkout staging<br>$ git reset --hard HEAD~1</pre><p>If you try to push staging now you won&#39;t be able to do it. At this point, your local staging has diverged from remote staging. Keep in mind that we&#39;re using --force. This will rewrite history for any person that is dealing with this branch, so sync with them before doing so.</p><pre>$ git push --force origin staging</pre><p>Which leads us to the same timeline:</p><pre>--a-----b---d--c*-&gt; master<br>  |staging</pre><p>At this time, staging doesn&#39;t have any different commits from master and is 3 commits behind. In this situation we can just run git merge master on staging. It will run smoothly, with FF and no merge commits, to the result of:</p><pre>--a-----b---d--c*-&gt; master, staging</pre><h3>Using merge commits to avoid force push</h3><p>This approach avoids the use of the --force option, so it&#39;s safer. But it will add one merge commit to your history line. This is not a big deal but can pollute your history if used frequently.</p><p>Start this approach by going to master and merge staging into it.</p><pre>$ git checkout master<br>$ git merge staging</pre><p>This will create a merge commit, so you&#39;ll be prompted to confirm the commit message. Do it and push staging to origin, which will lead us to this, with a new merge commit:</p><pre>--a-----b---d---m-&gt; master<br>   \------c----/--&gt; staging</pre><p>Notice that staging is still split from master. To fix this we need to merge master into staging. Since both branches are synced, the merge will be FF, so you can just push it after the merge.</p><pre>$ git checkout staging<br>$ git merge master<br>$ git push origin staging</pre><p>Now, our two branches will be synced and all our merges from now on will be FF, but notice that our history will stay polluted by the time staging diverged from master:</p><pre>--a-----b---d---m-&gt; master, staging<br>   \------c----/</pre><p>Git is extremely versatile and flexible so it usually offers different ways to accomplish the same goal. It&#39;s up to you to decide which one is best for your git flow. If you use another approach to keep your branches even, feel free to use the comments to share it with us.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7ddc8647d1f3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/goiabada/git-tricks-keeping-branches-even-7ddc8647d1f3">Git Tricks: Keeping branches even</a> was originally published in <a href="https://medium.com/goiabada">Goiabada</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>